diff --git a/.aci.yml b/.aci.yml index 15724571..0d8d3294 100644 --- a/.aci.yml +++ b/.aci.yml @@ -69,19 +69,22 @@ jobs: script: | #!/bin/bash if [[ `uname -m` == aarch64 ]]; then - wget https://studygolang.com/dl/golang/go1.20.6.linux-arm64.tar.gz --no-check-certificate + wget https://studygolang.com/dl/golang/go1.23.6.linux-arm64.tar.gz --no-check-certificate rm -rf /usr/local/go - tar -C /usr/local -xzf go1.20.6.linux-arm64.tar.gz + tar -C /usr/local -xzf go1.23.6.linux-arm64.tar.gz cp /usr/local/go/bin/go /usr/local/bin/ else - wget https://studygolang.com/dl/golang/go1.20.6.linux-amd64.tar.gz --no-check-certificate + wget https://studygolang.com/dl/golang/go1.23.6.linux-amd64.tar.gz --no-check-certificate rm -rf /usr/local/go - tar -C /usr/local -xzf go1.20.6.linux-amd64.tar.gz + tar -C /usr/local -xzf go1.23.6.linux-amd64.tar.gz cp /usr/local/go/bin/go /usr/local/bin/ fi + export PATH=/usr/local/go/bin:$PATH go env -w GOPROXY=https://goproxy.cn GOPATH="/usr/local" go install github.com/go-bindata/go-bindata/...@v3.1.2+incompatible cd "${BASE_WORKSPACE}/codeWorkspace" + mkdir -p frontend/dist + touch frontend/dist/index.html make pre-build build-with-swagger 规范检查: diff --git a/.gitignore b/.gitignore index 66372caa..9f0bd564 100644 --- a/.gitignore +++ b/.gitignore @@ -15,8 +15,47 @@ vendor # macOS files .DS_Store +# frontend +/frontend/pids +/frontend/logs +/frontend/node_modules +/frontend/npm-debug.log +/frontend/coverage/ +/frontend/build/ +/frontend/run +/frontend/.basement +/frontend/src/.umi +/frontend/src/.umi-production +/frontend/speed-measure.json +/frontend/dist +/frontend/unuseful-locale-key.txt +/frontend/docs.zip +/frontend/config.local.ts + + .idea/* *.iml .vscode/* .OWNERS +.meta +etc/ +log_obshell/ +run/ + +# frontend +/frontend/pids +/frontend/logs +/frontend/node_modules +/frontend/npm-debug.log +/frontend/coverage/ +/frontend/build/ +/frontend/run +/frontend/.basement +/frontend/src/.umi +/frontend/src/.umi-production +/frontend/speed-measure.json +/frontend/dist +/frontend/unuseful-locale-key.txt +/frontend/docs.zip +/frontend/config.local.ts diff --git a/Makefile b/Makefile index 956ee59f..dcab6bfc 100644 --- a/Makefile +++ b/Makefile @@ -20,9 +20,24 @@ build-release: set-release-flags obshell buildsucc build-with-swagger: enable-swagger build-release +build-for-test: pre-build enable-swagger set-disable-encryption-flags build-debug + +frontend-dep: + npm i -g pnpm@7 + +frontend-build: + cd frontend && pnpm i && pnpm build && cd ../ + +frontend-build-tester: + cd frontend && pnpm i && pnpm build:tester && cd ../ + rpm: cd ./rpm && VERSION=$(VERSION) RELEASE=$(RELEASE) NAME=$(NAME) OBSHELL_RELEASE=$(OBSHELL_RELEASE) rpmbuild -bb obshell.spec +set-disable-encryption-flags: + @echo Build with encryption disabled flags + $(eval LDFLAGS += $(LDFLAGS_DISABLE_ENCRYPTION)) + set-debug-flags: @echo Build with debug flags $(eval LDFLAGS += $(LDFLAGS_DEBUG)) diff --git a/Makefile.common b/Makefile.common index b04dced6..a1784c21 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1,5 +1,5 @@ PROCESSOR=2 -VERSION=4.2.5.0 +VERSION=4.2.6.0 NAME=obshell RELEASE=0 DIST=0 @@ -27,6 +27,7 @@ LDFLAGS += -X "github.com/oceanbase/obshell/agent/config.GitCommitTime=$(shell g LDFLAGS += -X "github.com/oceanbase/obshell/agent/config.BuildFlags=${BUILD_FLAG}" LDFLAGS_DEBUG = -X "github.com/oceanbase/obshell/agent/config.Mode=debug" LDFLAGS_RELEASE = -X "github.com/oceanbase/obshell/agent/config.Mode=release" +LDFLAGS_DISABLE_ENCRYPTION = -X "github.com/oceanbase/obshell/agent/config.EncryptionDisabled=true" OBSHELL_LDFLAGS = $(LDFLAGS) -X "github.com/oceanbase/obshell/agent/config.CurProcess=obshell" GOFILES ?= $(shell git ls-files '*.go') diff --git a/agent/api/agent_handler.go b/agent/api/agent_handler.go index 1044ca7b..a4657a13 100644 --- a/agent/api/agent_handler.go +++ b/agent/api/agent_handler.go @@ -35,18 +35,18 @@ var ( agentService = agentservice.AgentService{} ) -// @Summary join the specified agent -// @Description join the specified agent -// @Tags agent -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.JoinApiParam true "agent info with zone name" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 400 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/agent [post] -// @Router /api/v1/agent/join [post] +// @Summary join the specified agent +// @Description join the specified agent +// @Tags agent +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param body body param.JoinApiParam true "agent info with zone name" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/agent [post] +// @Router /api/v1/agent/join [post] func agentJoinHandler(c *gin.Context) { var param param.JoinApiParam if err := c.BindJSON(¶m); err != nil { @@ -54,7 +54,7 @@ func agentJoinHandler(c *gin.Context) { return } if !meta.OCS_AGENT.IsSingleAgent() { - common.SendResponse(c, nil, errors.Occurf(errors.ErrBadRequest, "%s:%d is not single agent", meta.OCS_AGENT.GetIp(), meta.OCS_AGENT.GetPort())) + common.SendResponse(c, nil, errors.Occurf(errors.ErrBadRequest, "%s is not single agent", meta.OCS_AGENT.String())) return } @@ -78,7 +78,7 @@ func agentJoinHandler(c *gin.Context) { param.AgentInfo.String(), agentStatus.Version, meta.OCS_AGENT.String(), constant.VERSION_RELEASE)) return } - if obVersion, err := binary.GetMyOBVersion(); err != nil { + if obVersion, _, err := binary.GetMyOBVersion(); err != nil { common.SendResponse(c, nil, errors.Occurf(errors.ErrUnexpected, "get ob version failed: %s", err.Error())) return } else if obVersion != agentStatus.OBVersion { @@ -86,7 +86,13 @@ func agentJoinHandler(c *gin.Context) { param.AgentInfo.String(), agentStatus.OBVersion, meta.OCS_AGENT.String(), obVersion)) return } - dag, err = agent.CreateJoinMasterDag(param.AgentInfo, param.ZoneName) + // send token to master early. + if err = agent.SendTokenToMaster(param.AgentInfo, param.MasterPassword); err != nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrTaskCreateFailed, err)) + return + } + + dag, err = agent.CreateJoinMasterDag(param.AgentInfo, param.ZoneName, param.MasterPassword) } if err != nil { @@ -96,18 +102,18 @@ func agentJoinHandler(c *gin.Context) { common.SendResponse(c, task.NewDagDetailDTO(dag), nil) } -// @Summary remove the specified agent -// @Description remove the specified agent -// @Tags agent -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body meta.AgentInfo true "agent info" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 400 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/agent [delete] -// @Router /api/v1/agent/remove [post] +// @Summary remove the specified agent +// @Description remove the specified agent +// @Tags agent +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param body body meta.AgentInfo true "agent info" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/agent [delete] +// @Router /api/v1/agent/remove [post] func agentRemoveHandler(c *gin.Context) { var param meta.AgentInfo if err := c.BindJSON(¶m); err != nil { @@ -178,3 +184,13 @@ func agentRemoveHandler(c *gin.Context) { } common.SendResponse(c, task.NewDagDetailDTO(dag), nil) } + +func agentSetPasswordHandler(c *gin.Context) { + var param param.SetAgentPasswordParam + if err := c.BindJSON(¶m); err != nil { + common.SendResponse(c, nil, err) + return + } + + common.SendResponse(c, nil, agentService.SetAgentPassword(param.Password)) +} diff --git a/agent/api/agent_route.go b/agent/api/agent_route.go index aed220a6..f1e4cebf 100644 --- a/agent/api/agent_route.go +++ b/agent/api/agent_route.go @@ -41,10 +41,13 @@ func InitOcsAgentRoutes(s *http2.State, r *gin.Engine, isLocalRoute bool) { } r.Use( gin.CustomRecovery(common.Recovery), // gin's crash-free middleware - common.PostHandlers("/debug/pprof", "/swagger"), - common.BodyDecrypt(), // decrypt request body + common.PostHandlers("/debug/pprof", "/swagger", + // get all obcluster parameters + constant.URI_API_V1+constant.URI_OBCLUSTER_GROUP+constant.URI_PARAMETERS, + ), + common.HeaderDecrypt(), + common.BodyDecrypt(constant.URI_API_V1+constant.URI_PACKAGE), // decrypt request body common.PaddingBody(), // if the response body is empty, the response body is padded with "{}" - common.PreHandlers( constant.URI_API_V1+constant.URI_UPGRADE+constant.URI_PACKAGE, constant.URI_API_V1+constant.URI_OBCLUSTER_GROUP+constant.URI_CONFIG, @@ -52,9 +55,35 @@ func InitOcsAgentRoutes(s *http2.State, r *gin.Engine, isLocalRoute bool) { constant.URI_API_V1+constant.URI_TENANT_GROUP+constant.URI_PATH_PARAM_NAME+constant.URI_BACKUP+constant.URI_CONFIG, constant.URI_API_V1+constant.URI_TENANT_GROUP+constant.URI_RESTORE, constant.URI_API_V1+constant.URI_RESTORE+constant.URI_WINDOWS, + // init cluster + constant.URI_OB_API_PREFIX+constant.URI_INIT, constant.URI_TASK_RPC_PREFIX+constant.URI_SUB_TASK, + // create tenant constant.URI_API_V1+constant.URI_TENANT_GROUP, + // set tenant password constant.URI_TENANT_API_PREFIX+constant.URI_PATH_PARAM_NAME+constant.URI_ROOTPASSWORD, + // create user + constant.URI_TENANT_API_PREFIX+constant.URI_PATH_PARAM_NAME+constant.URI_USER, + // delete user + constant.URI_TENANT_API_PREFIX+constant.URI_PATH_PARAM_NAME+constant.URI_USER+constant.URI_PATH_PARAM_USER, + // add obproxy + constant.URI_OBPROXY_API_PREFIX, + // set tenant variable + constant.URI_TENANT_API_PREFIX+constant.URI_PATH_PARAM_NAME+constant.URI_VARIABLES, + // set agent password + constant.URI_AGENT_API_PREFIX+constant.URI_PASSWORD, + // join master + constant.URI_AGENT_API_PREFIX+constant.URI_JOIN, + constant.URI_AGENT_API_PREFIX, + // scale out + constant.URI_API_V1+constant.URI_OB_GROUP+constant.URI_SCALE_OUT, + // send token + constant.URI_AGENT_RPC_PREFIX+constant.URI_TOKEN, + // upload obproxy package + constant.URI_OBPROXY_API_PREFIX+constant.URI_PACKAGE, + constant.URI_API_V1+constant.URI_PACKAGE, + // persist tenant root password + constant.URI_PATH_PARAM_NAME+constant.URI_ROOTPASSWORD+constant.URI_PERSIST, ), common.SetContentType, ) @@ -63,6 +92,7 @@ func InitOcsAgentRoutes(s *http2.State, r *gin.Engine, isLocalRoute bool) { r.Use(common.SetLocalRouteFlag) } else { initSwagger(r) + initFrontendRouter(r) } // groups @@ -81,6 +111,7 @@ func InitOcsAgentRoutes(s *http2.State, r *gin.Engine, isLocalRoute bool) { pool := v1.Group(constant.URI_POOL_GROUP) recyclebin := v1.Group(constant.URI_RECYCLEBIN_GROUP) zone := v1.Group(constant.URI_ZONE_GROUP) + pkg := v1.Group(constant.URI_PACKAGE) if !isLocalRoute { ob.Use(common.Verify()) @@ -107,6 +138,7 @@ func InitOcsAgentRoutes(s *http2.State, r *gin.Engine, isLocalRoute bool) { InitTenantRoutes(v1, isLocalRoute) InitBackupRoutes(v1, isLocalRoute) InitRestoreRoutes(v1, isLocalRoute) + InitObproxyRoutes(v1, isLocalRoute) // ob routes ob.POST(constant.URI_INIT, obInitHandler) @@ -116,6 +148,7 @@ func InitOcsAgentRoutes(s *http2.State, r *gin.Engine, isLocalRoute bool) { ob.POST(constant.URI_SCALE_OUT, obClusterScaleOutHandler) ob.POST(constant.URI_SCALE_IN, obClusterScaleInHandler) ob.POST(constant.URI_UPGRADE, obUpgradeHandler) + ob.GET(constant.URI_UPGRADE+constant.URI_ROUTE, obPkgUpgradeRouteHandler) ob.POST(constant.URI_UPGRADE+constant.URI_CHECK, obUpgradeCheckHandler) ob.GET(constant.URI_AGENTS, obAgentsHandler) @@ -126,6 +159,7 @@ func InitOcsAgentRoutes(s *http2.State, r *gin.Engine, isLocalRoute bool) { agent.POST(constant.URI_REMOVE, agentRemoveHandler) agent.POST(constant.URI_UPGRADE, agentUpgradeHandler) agent.POST(constant.URI_UPGRADE+constant.URI_CHECK, agentUpgradeCheckHandler) + agent.POST(constant.URI_PASSWORD, agentSetPasswordHandler) // agents routes agents.GET(constant.URI_STATUS, GetAllAgentStatus(s)) @@ -133,6 +167,11 @@ func InitOcsAgentRoutes(s *http2.State, r *gin.Engine, isLocalRoute bool) { // obcluster routes obcluster.PUT(constant.URI_CONFIG, obclusterConfigHandler(true)) obcluster.POST(constant.URI_CONFIG, obclusterConfigHandler(true)) + obcluster.GET(constant.URI_INFO, obclusterInfoHandler) + obcluster.GET(constant.URI_PARAMETERS, obclusterParametersHandler) + obcluster.PATCH(constant.URI_PARAMETERS, obclusterSetParametersHandler) + obcluster.GET(constant.URI_CHARSETS, getObclusterCharsets) + obcluster.GET(constant.URI_UNIT_CONFIG_LIMIT, checkClusterAgentWrapper(getUnitConfigLimitHandler)) // observer routes observer.PUT(constant.URI_CONFIG, obServerConfigHandler(true)) @@ -144,9 +183,12 @@ func InitOcsAgentRoutes(s *http2.State, r *gin.Engine, isLocalRoute bool) { // upgrade routes upgrade.POST(constant.URI_PACKAGE, pkgUploadHandler) + upgrade.GET(constant.URI_PACKAGE+constant.URI_INFO, pkgInfoHandler) upgrade.POST(constant.URI_PARAMS+constant.URI_BACKUP, paramsBackupHandler) upgrade.POST(constant.URI_PARAMS+constant.URI_RESTORE, paramsRestoreHandler) + pkg.POST("", common.VerifyFile(), newPkgUploadHandler) + // unit routes unit.POST("", unitConfigCreateHandler) unit.DELETE(constant.URI_PATH_PARAM_NAME, unitConfigDropHandler) @@ -161,9 +203,8 @@ func InitOcsAgentRoutes(s *http2.State, r *gin.Engine, isLocalRoute bool) { recyclebin.GET(constant.URI_TENANTS, recyclebinListTenantHandler) recyclebin.DELETE(constant.URI_TENANT_GROUP+constant.URI_PATH_PARAM_NAME, recyclebinPurgeTenantHandler) recyclebin.POST(constant.URI_TENANT_GROUP+constant.URI_PATH_PARAM_NAME, recyclebinFlashbackTenantHandler) - r.NoRoute(func(c *gin.Context) { - err := errors.Occur(errors.ErrBadRequest, "404 not found") - common.SendResponse(c, nil, err) + common.SendResponse(c, nil, errors.Occur(errors.ErrBadRequest, "404 not found")) + return }) } diff --git a/agent/api/common/forward_handler.go b/agent/api/common/forward_handler.go index 73ce6970..56ae0f76 100644 --- a/agent/api/common/forward_handler.go +++ b/agent/api/common/forward_handler.go @@ -18,13 +18,16 @@ package common import ( "context" + "encoding/json" "fmt" + "io" "time" "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/engine/coordinator" "github.com/oceanbase/obshell/agent/errors" "github.com/oceanbase/obshell/agent/global" libhttp "github.com/oceanbase/obshell/agent/lib/http" @@ -44,7 +47,7 @@ func autoForward(c *gin.Context) { agentService := agentservice.AgentService{} master := agentService.GetMasterAgentInfo() if master == nil { - SendResponse(c, nil, errors.Occur(errors.ErrUnauthorized)) + SendResponse(c, nil, errors.Occur(errors.ErrUnauthorized, "master agent not found")) return } @@ -62,13 +65,13 @@ func autoForward(c *gin.Context) { headerByte, exist := c.Get(constant.OCS_HEADER) if headerByte == nil || !exist { - SendResponse(c, nil, errors.Occur(errors.ErrUnauthorized)) + SendResponse(c, nil, errors.Occur(errors.ErrUnauthorized, "header not found")) return } header, ok := headerByte.(secure.HttpHeader) if !ok { - SendResponse(c, nil, errors.Occur(errors.ErrUnauthorized)) + SendResponse(c, nil, errors.Occur(errors.ErrUnauthorized, "header type error")) return } @@ -81,6 +84,35 @@ func autoForward(c *gin.Context) { sendRequsetForForward(c, ctx, master, headers, body) } +func AutoForwardToMaintainerWrapper(f func(*gin.Context)) func(*gin.Context) { + return func(c *gin.Context) { + ctx := NewContextWithTraceId(c) + var agentInfo meta.AgentInfoInterface + if coordinator.OCS_COORDINATOR != nil && coordinator.OCS_COORDINATOR.Maintainer.GetPort() != 0 { + agentInfo = coordinator.OCS_COORDINATOR.Maintainer + if meta.OCS_AGENT.Equal(agentInfo) { + log.WithContext(ctx).Info("Current agent is maintainer") + f(c) + return + } + bodyBytes, err := io.ReadAll(c.Request.Body) + if err != nil { + SendResponse(c, nil, errors.New("Failed to read request body when forwarding request")) + return + } + var bodyInterface interface{} + if err := json.Unmarshal(bodyBytes, &bodyInterface); err != nil { + SendResponse(c, nil, err) + return + } + ForwardRequest(c, agentInfo, bodyInterface) + } else { + log.WithContext(ctx).Info("forward request to maintainer but no maintainer found") + SendResponse(c, nil, errors.New("forward request to maintainer but no maintainer found")) + } + } +} + // ForwardRequest is used by handler to forward the request to other agent. func ForwardRequest(c *gin.Context, agentInfo meta.AgentInfoInterface, param interface{}) { ctx := NewContextWithTraceId(c) @@ -104,7 +136,7 @@ func sendRequsetForForward(c *gin.Context, ctx context.Context, agentInfo meta.A } request.SetBody(body) - uri := fmt.Sprintf("%s://%s:%d%s", global.Protocol, agentInfo.GetIp(), agentInfo.GetPort(), c.Request.URL) + uri := fmt.Sprintf("%s://%s%s", global.Protocol, agentInfo.String(), c.Request.URL) response, err := request.Execute(c.Request.Method, uri) if err != nil { log.WithError(err).Errorf("API response failed : [%v %v, client=%v, agent=%v]", c.Request.Method, c.Request.URL, c.ClientIP(), agentInfo.String()) diff --git a/agent/api/common/middleware.go b/agent/api/common/middleware.go index 38c9210f..c9d0aee8 100644 --- a/agent/api/common/middleware.go +++ b/agent/api/common/middleware.go @@ -18,6 +18,8 @@ package common import ( "bytes" + "crypto/sha256" + "encoding/hex" "io" "net" "net/http" @@ -30,7 +32,9 @@ import ( "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" + "github.com/oceanbase/obshell/agent/config" "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/engine/task" "github.com/oceanbase/obshell/agent/errors" ocshttp "github.com/oceanbase/obshell/agent/lib/http" "github.com/oceanbase/obshell/agent/lib/path" @@ -239,11 +243,9 @@ func PaddingBody() func(*gin.Context) { // PostHandlers returns a Gin middleware function that logs the response and duration of API requests. func PostHandlers(excludeRoutes ...string) func(*gin.Context) { return func(c *gin.Context) { - for _, it := range excludeRoutes { - if strings.HasPrefix(c.Request.RequestURI, it) { - c.Next() - return - } + if !strings.HasPrefix(c.Request.RequestURI, constant.URI_API_V1) && !strings.HasPrefix(c.Request.RequestURI, constant.URI_RPC_V1) { + c.Next() + return } startTime := time.Now() @@ -268,8 +270,21 @@ func PostHandlers(excludeRoutes ...string) func(*gin.Context) { if resp.Successful { if c.Request.RequestURI != statusURI { - log.WithContext(ctx).Infof("API response OK: [%v %v, client=%v, traceId=%v, duration=%v, status=%v, data=%+v]", - c.Request.Method, c.Request.URL, c.ClientIP(), resp.TraceId, resp.Duration, resp.Status, resp.Data) + printResponseData := true + for _, route := range excludeRoutes { + if strings.HasPrefix(c.Request.RequestURI, route) { + printResponseData = false + break + } + } + if printResponseData { + log.WithContext(ctx).Infof("API response OK: [%v %v, client=%v, traceId=%v, duration=%v, status=%v, data=%+v]", + c.Request.Method, c.Request.URL, c.ClientIP(), resp.TraceId, resp.Duration, resp.Status, resp.Data) + } else { + log.WithContext(ctx).Infof("API response OK: [%v %v, client=%v, traceId=%v, duration=%v, status=%v]", + c.Request.Method, c.Request.URL, c.ClientIP(), resp.TraceId, resp.Duration, resp.Status) + } + } else { log.WithContext(ctx).Debugf("API response OK: [%v %v, client=%v, traceId=%v, duration=%v, status=%v, data=%+v]", c.Request.Method, c.Request.URL, c.ClientIP(), resp.TraceId, resp.Duration, resp.Status, resp.Data) @@ -292,13 +307,21 @@ func Recovery(c *gin.Context, err interface{}) { // This is particularly useful to handle cases where gin might set the Content-Type to "text/plain" // due to certain types of errors, such as JSON binding errors. func SetContentType(c *gin.Context) { + if !strings.HasPrefix(c.Request.RequestURI, constant.URI_API_V1) && !strings.HasPrefix(c.Request.RequestURI, constant.URI_RPC_V1) { + c.Next() + return + } c.Writer.Header().Set("Content-Type", "application/json") - c.Next() } -func BodyDecrypt(skipRoutes ...string) func(*gin.Context) { +func HeaderDecrypt(skipRoutes ...string) func(*gin.Context) { return func(c *gin.Context) { + // check encryption config + if config.IsEncryptionDisabled() { + c.Next() + return + } for _, route := range skipRoutes { if route == c.Request.RequestURI { c.Next() @@ -307,34 +330,73 @@ func BodyDecrypt(skipRoutes ...string) func(*gin.Context) { } var err error - encryptedHeader := c.Request.Header.Get(constant.OCS_HEADER) - if encryptedHeader == "" { + if c.Request.Header.Get(constant.OCS_HEADER) == "" && c.Request.Header.Get(constant.OCS_AGENT_HEADER) == "" { c.Next() return } var header secure.HttpHeader - header, err = secure.DecryptHeader(c.Request.Header.Get(constant.OCS_HEADER)) - if err != nil { - log.WithContext(NewContextWithTraceId(c)).Errorf("header decrypt failed, err: %v", err) - c.Abort() - SendResponse(c, nil, errors.Occur(errors.ErrUnauthorized)) - return + if c.Request.Header.Get(constant.OCS_AGENT_HEADER) != "" { + header, err = secure.DecryptHeader(c.Request.Header.Get(constant.OCS_AGENT_HEADER)) + if err != nil { + log.WithContext(NewContextWithTraceId(c)).Errorf("header decrypt failed, err: %v", err) + c.Abort() + SendResponse(c, nil, errors.Occurf(errors.ErrUnauthorized, "header decrypt failed")) + return + } + c.Set(constant.OCS_AGENT_HEADER, header) + } else { + header, err = secure.DecryptHeader(c.Request.Header.Get(constant.OCS_HEADER)) + if err != nil { + log.WithContext(NewContextWithTraceId(c)).Errorf("header decrypt failed, err: %v", err) + c.Abort() + SendResponse(c, nil, errors.Occurf(errors.ErrUnauthorized, "header decrypt failed")) + return + } + c.Set(constant.OCS_HEADER, header) } - c.Set(constant.OCS_HEADER, header) + c.Next() + } +} - for _, route := range secure.GetSkipBodyEncryptRoutes() { +func BodyDecrypt(skipRoutes ...string) func(*gin.Context) { + return func(c *gin.Context) { + // check encryption config + if config.IsEncryptionDisabled() { + c.Next() + return + } + for _, route := range skipRoutes { if route == c.Request.RequestURI { c.Next() return } } + obHeaderByte, _ := c.Get(constant.OCS_HEADER) + agentHeaderByte, _ := c.Get(constant.OCS_AGENT_HEADER) + var headerByte any + if agentHeaderByte != nil { + headerByte = agentHeaderByte + } else if obHeaderByte != nil { + headerByte = obHeaderByte + } else { + c.Next() + return + } + + header, ok := headerByte.(secure.HttpHeader) + if !ok { + log.WithContext(NewContextWithTraceId(c)).Error("header type error") + c.Abort() + SendResponse(c, nil, errors.Occur(errors.ErrUnauthorized, "header type error")) + return + } // Decrypts the request body on routes where encryption is expected. encryptedBody, err := io.ReadAll(c.Request.Body) if err != nil { log.WithContext(NewContextWithTraceId(c)).Errorf("read body failed, err: %v", err) c.Abort() - SendResponse(c, nil, errors.Occur(errors.ErrUnauthorized)) + SendResponse(c, nil, errors.Occurf(errors.ErrUnauthorized, "read body failed")) return } if len(encryptedBody) == 0 { @@ -345,7 +407,7 @@ func BodyDecrypt(skipRoutes ...string) func(*gin.Context) { if err != nil { log.WithContext(NewContextWithTraceId(c)).Errorf("body decrypt failed, err: %v", err) c.Abort() - SendResponse(c, nil, errors.Occur(errors.ErrUnauthorized)) + SendResponse(c, nil, errors.Occurf(errors.ErrUnauthorized, "body decrypt failed")) return } c.Request.Body = io.NopCloser(bytes.NewBuffer(body)) @@ -355,91 +417,258 @@ func BodyDecrypt(skipRoutes ...string) func(*gin.Context) { } } -func Verify(skipRoutes ...string) func(*gin.Context) { - return func(c *gin.Context) { - log.WithContext(NewContextWithTraceId(c)).Infof("verfiy request: %s", c.Request.RequestURI) - for _, route := range skipRoutes { - if route == c.Request.RequestURI { - c.Next() - return - } - } - var header secure.HttpHeader - headerByte, exist := c.Get(constant.OCS_HEADER) - - if headerByte == nil || !exist { - log.WithContext(NewContextWithTraceId(c)).Error("header not found") - c.Abort() - SendResponse(c, nil, errors.Occur(errors.ErrUnauthorized)) - return +func VerifyObRouters(c *gin.Context, curTs int64, header *secure.HttpHeader, passwordType secure.VerifyType) { + pass := false + var err error + switch meta.OCS_AGENT.GetIdentity() { + case meta.SINGLE: + if err = secure.VerifyToken(header.Token); err == nil { + pass = true + break } - pass := false - - header, ok := headerByte.(secure.HttpHeader) - if !ok { - log.WithContext(NewContextWithTraceId(c)).Error("header type error") - c.Abort() - SendResponse(c, nil, errors.Occur(errors.ErrUnauthorized)) - return + if meta.AGENT_PWD.Inited() { + if passwordType == secure.AGENT_PASSWORD { + if err = secure.VerifyAuth(header.Auth, header.Ts, curTs, secure.AGENT_PASSWORD); err == nil { + pass = true + } else { + decryptAgentPassword, err1 := secure.Decrypt(header.Auth) + if err1 == nil && secure.VerifyAuth(decryptAgentPassword, header.Ts, curTs, secure.AGENT_PASSWORD) == nil { + pass = true + } + } + } else { + err = errors.New("agent password has been set, use agent password to verify") + } + } else { + pass = true } - - switch meta.OCS_AGENT.GetIdentity() { - case meta.SINGLE: + case meta.FOLLOWER: + // Follower verify token only. + if err = secure.VerifyToken(header.Token); err == nil { pass = true - case meta.FOLLOWER: - // Follower verify token only. - if secure.VerifyToken(header.Token) == nil { + } else { + if IsApiRoute(c) && header.ForwardType != secure.ManualForward { + // If the request is api and is not manual forwarded, auto forward it. + autoForward(c) + c.Abort() + return + } + } + case meta.MASTER: + if header.ForwardType == secure.ManualForward { + // When a request is manually forwarded, it must have a valid follower token. + if err = secure.VerifyTokenByAgentInfo(header.Token, header.ForwardAgent); err == nil { pass = true - } else { - if IsApiRoute(c) && header.ForwardType != secure.ManualForward { - // If the request is api and is not manual forwarded, auto forward it. - autoForward(c) - c.Abort() - return - } } - case meta.MASTER: - if header.ForwardType == secure.ManualForward { - // When a request is manually forwarded, it must have a valid follower token. - if err := secure.VerifyTokenByAgentInfo(header.Token, header.ForwardAgent); err == nil { + break + } else if header.ForwardType == secure.AutoForward { + // If the request is auto-forwarded, set IsAutoForwardedFlag to true for parse password. + c.Set(IsAutoForwardedFlag, true) + c.Set(FollowerAgentOfForward, header.ForwardAgent) + } + fallthrough + default: + if passwordType == secure.OCEANBASE_PASSWORD { + if !meta.OCEANBASE_PASSWORD_INITIALIZED && meta.AGENT_PWD.Inited() { + err = errors.New("oceanbase password is not initialized, use agent password to verify") + } else { + if err = secure.VerifyAuth(header.Auth, header.Ts, curTs, secure.OCEANBASE_PASSWORD); err == nil { pass = true } - break - } else if header.ForwardType == secure.AutoForward { - // If the request is auto-forwarded, set IsAutoForwardedFlag to true for parse password. - c.Set(IsAutoForwardedFlag, true) - c.Set(FollowerAgentOfForward, header.ForwardAgent) } - fallthrough - default: - curTs := time.Now().Unix() - if r, ok := c.Get(constant.REQUEST_RECEIVED_TIME); ok { - if receivedTs, ok := r.(int64); ok { - curTs = receivedTs - } + } else { + if meta.OCEANBASE_PASSWORD_INITIALIZED && !meta.AGENT_PWD.Inited() { + err = errors.New("agent password is not initialized, use oceanbase password to verify") + } else if !meta.AGENT_PWD.Inited() { + pass = true + } else if err = secure.VerifyAuth(header.Auth, header.Ts, curTs, secure.AGENT_PASSWORD); err == nil { + pass = true } - if err := secure.VerifyAuth(header.Auth, header.Ts, curTs); err != nil { - log.WithContext(NewContextWithTraceId(c)).Error(err.Error()) - } else { + } + } + if !pass { + log.WithContext(NewContextWithTraceId(c)).Errorf("Security verification failed: %s", err.Error()) + c.Abort() + SendResponse(c, nil, errors.Occurf(errors.ErrUnauthorized, err.Error())) + return + } +} + +func VerifyForSetAgentPassword(c *gin.Context, curTs int64, header *secure.HttpHeader, passwordType secure.VerifyType) { + pass := false + var err error + if meta.AGENT_PWD.Inited() { + if passwordType == secure.AGENT_PASSWORD { + if err = secure.VerifyAuth(header.Auth, header.Ts, curTs, secure.AGENT_PASSWORD); err == nil { pass = true } + } else { + err = errors.New("agent password has been set, use agent password to verify") + } + } else if meta.OCS_AGENT.IsClusterAgent() { + if passwordType == secure.OCEANBASE_PASSWORD { + if err = secure.VerifyAuth(header.Auth, header.Ts, curTs, secure.OCEANBASE_PASSWORD); err == nil { + pass = true + } + } else { + err = errors.New("oceanbase password has been set, use oceanbase password to verify") + } + } else if meta.OCS_AGENT.IsSingleAgent() { + pass = true + } + if !pass { + log.WithContext(NewContextWithTraceId(c)).Errorf("Security verification failed: %s", err.Error()) + c.Abort() + SendResponse(c, nil, errors.Occurf(errors.ErrUnauthorized, err.Error())) + return + } +} + +func VerifyAgentRoutes(c *gin.Context, curTs int64, header *secure.HttpHeader, passwordType secure.VerifyType) { + pass := false + var err error + if passwordType != secure.AGENT_PASSWORD { + err = errors.New("Please use agent password to verify") + } else { + if meta.AGENT_PWD.Inited() { + if err = secure.VerifyAuth(header.Auth, header.Ts, curTs, secure.AGENT_PASSWORD); err == nil { + pass = true + } + } else { + err = errors.New("agent password is not initialized") + } + } + if !pass { + log.WithContext(NewContextWithTraceId(c)).Errorf("Security verification failed: %s", err.Error()) + c.Abort() + SendResponse(c, nil, errors.Occurf(errors.ErrUnauthorized, err.Error())) + return + } +} + +func VerifyTaskRoutes(c *gin.Context, curTs int64, header *secure.HttpHeader, passwordType secure.VerifyType) { + id := c.Param("id") + if id == "" { + VerifyObRouters(c, curTs, header, passwordType) + return + } + if task.IsObproxyTask(id) { + VerifyAgentRoutes(c, curTs, header, passwordType) + return + } else { + VerifyObRouters(c, curTs, header, passwordType) + return + } +} + +func calculateSHA256(reader io.Reader) string { + hash := sha256.New() + + _, err := io.Copy(hash, reader) + if err != nil { + return "" + } + return hex.EncodeToString(hash.Sum(nil)) +} + +func VerifyFile() func(*gin.Context) { + return func(c *gin.Context) { + if config.IsEncryptionDisabled() { + c.Next() + return + } + file, _, err := c.Request.FormFile("file") + if err != nil { + c.Abort() + SendResponse(c, nil, errors.Occurf(errors.ErrKnown, "get file failed:%s", err)) + return + } + defer file.Close() + // calculate the file sha256 + sha256 := calculateSHA256(file) + encryptedSHA := c.Request.Header.Get("X-OCS-File-SHA256") + // decrypt the file sha256 + accept, err := secure.Decrypt(encryptedSHA) + if err != nil { + log.WithContext(NewContextWithTraceId(c)).Errorf("decrypt file sha256 failed, err: %v", err) + c.Abort() + SendResponse(c, nil, errors.Occur(errors.ErrUnauthorized, "decrypt file sha256 failed")) + return } - if !pass { - log.WithContext(NewContextWithTraceId(c)).Error("Security verification failed") + if accept != sha256 { + log.WithContext(NewContextWithTraceId(c)).Errorf("file sha256 not match, expect: %s, actual: %s", accept, sha256) c.Abort() - SendResponse(c, nil, errors.Occur(errors.ErrUnauthorized)) + SendResponse(c, nil, errors.Occur(errors.ErrUnauthorized, "file sha256 not match")) + return + } + c.Next() + } +} + +func Verify(routeType ...secure.RouteType) func(*gin.Context) { + return func(c *gin.Context) { + if config.IsEncryptionDisabled() { + c.Next() + return + } + log.WithContext(NewContextWithTraceId(c)).Infof("verfiy request: %s", c.Request.RequestURI) + var header secure.HttpHeader + obHeaderByte, _ := c.Get(constant.OCS_HEADER) + agentHeaderByte, _ := c.Get(constant.OCS_AGENT_HEADER) + var headerByte any + var passwordType secure.VerifyType + if agentHeaderByte != nil { + passwordType = secure.AGENT_PASSWORD + headerByte = agentHeaderByte + } else if obHeaderByte != nil { + passwordType = secure.OCEANBASE_PASSWORD + headerByte = obHeaderByte + } else { + log.WithContext(NewContextWithTraceId(c)).Error("header not found") + c.Abort() + SendResponse(c, nil, errors.Occur(errors.ErrUnauthorized, "header not found")) + return + } + if passwordType != secure.AGENT_PASSWORD && len(routeType) != 0 && routeType[0] == secure.ROUTE_OBPROXY { + log.WithContext(NewContextWithTraceId(c)).Error("agent header not found") + c.Abort() + SendResponse(c, nil, errors.Occur(errors.ErrUnauthorized, "aegnt header not found")) + return + } + + header, ok := headerByte.(secure.HttpHeader) + if !ok { + log.WithContext(NewContextWithTraceId(c)).Error("header type error") + c.Abort() + SendResponse(c, nil, errors.Occur(errors.ErrUnauthorized, "header type error")) return } // Verify the URI in the header matches the URI of the request. if header.Uri != c.Request.RequestURI { log.WithContext(NewContextWithTraceId(c)).Errorf("verify uri failed, uri: %s, expect: %s", header.Uri, c.Request.RequestURI) - authErr := errors.Occur(errors.ErrUnauthorized) + authErr := errors.Occurf(errors.ErrUnauthorized, "uri mismatch") c.Abort() SendResponse(c, nil, authErr) return } + curTs := time.Now().Unix() + if r, ok := c.Get(constant.REQUEST_RECEIVED_TIME); ok { + if receivedTs, ok := r.(int64); ok { + curTs = receivedTs + } + } + + if c.Request.RequestURI == constant.URI_AGENT_API_PREFIX+constant.URI_PASSWORD { + VerifyForSetAgentPassword(c, curTs, &header, passwordType) + } else if len(routeType) != 0 && routeType[0] == secure.ROUTE_OBPROXY { + VerifyAgentRoutes(c, curTs, &header, passwordType) + } else if len(routeType) != 0 && routeType[0] == secure.ROUTE_TASK { + VerifyTaskRoutes(c, curTs, &header, passwordType) + } else { + VerifyObRouters(c, curTs, &header, passwordType) + } // Verification succeeded, continue to the next middleware. c.Next() } diff --git a/agent/api/frontend_router.go b/agent/api/frontend_router.go new file mode 100644 index 00000000..c6ecfbf5 --- /dev/null +++ b/agent/api/frontend_router.go @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package api + +import ( + "github.com/gin-contrib/static" + "github.com/gin-gonic/gin" +) + +func initFrontendRouter(router *gin.Engine) { + router.Use(static.Serve("/", static.LocalFile("frontend/dist", false))) + router.NoRoute(func(c *gin.Context) { + c.Redirect(302, "/") + }) +} diff --git a/agent/api/info_handler.go b/agent/api/info_handler.go index d7989005..bcab4412 100644 --- a/agent/api/info_handler.go +++ b/agent/api/info_handler.go @@ -38,46 +38,47 @@ var localTaskService = task.NewLocalTaskService() // TimeHandler returns the current time // -// @ID getTime -// @Summary get current time -// @Description get current time -// @Tags v1 -// @Accept application/json -// @Produce application/json -// @Success 200 object http.OcsAgentResponse{data=time.Time} -// @Router /api/v1/time [get] +// @ID getTime +// @Summary get current time +// @Description get current time +// @Tags v1 +// @Accept application/json +// @Produce application/json +// @Success 200 object http.OcsAgentResponse{data=time.Time} +// @Router /api/v1/time [get] func TimeHandler(c *gin.Context) { common.SendResponse(c, time.Now(), nil) } // InfoHandler returns the agent info // -// @ID getAgentInfo -// @Summary get agent info -// @Description get agent info -// @Tags v1 -// @Accept application/json -// @Produce application/json -// @Success 200 object http.OcsAgentResponse{data=meta.AgentStatus} -// @Router /api/v1/info [get] +// @ID getAgentInfo +// @Summary get agent info +// @Description get agent info +// @Tags v1 +// @Accept application/json +// @Produce application/json +// @Success 200 object http.OcsAgentResponse{data=meta.AgentStatus} +// @Router /api/v1/info [get] func InfoHandler(s *http.State) gin.HandlerFunc { return func(c *gin.Context) { - obVersion, err := binary.GetMyOBVersion() - agentStatus := meta.NewAgentStatus(meta.OCS_AGENT, global.Pid, s.GetState(), global.StartAt, global.HomePath, obVersion) - common.SendResponse(c, agentStatus, err) + obVersion, _, _ := binary.GetMyOBVersion() // when occur err, obVersion is empty + agentStatus := meta.NewAgentStatus(meta.OCS_AGENT, global.Pid, s.GetState(), global.StartAt, global.HomePath, obVersion, meta.AGENT_PWD.Inited(), meta.IsObproxyAgent()) + agentStatus.Architecture = global.Architecture + common.SendResponse(c, agentStatus, nil) } } // GitInfoHandler returns the agent git info // -// @ID getGitInfo -// @Summary get git info -// @Description get git info -// @Tags v1 -// @Accept application/json -// @Produce application/json -// @Success 200 object http.OcsAgentResponse{data=config.GitInfo} -// @Router /api/v1/git-info [get] +// @ID getGitInfo +// @Summary get git info +// @Description get git info +// @Tags v1 +// @Accept application/json +// @Produce application/json +// @Success 200 object http.OcsAgentResponse{data=config.GitInfo} +// @Router /api/v1/git-info [get] func GitInfoHandler(c *gin.Context) { common.SendResponse(c, config.GetGitInfo(), nil) } @@ -96,20 +97,21 @@ func GetAgentStatus(s *http.State) (http.AgentStatus, error) { status.Agent.Identity = meta.OCS_AGENT.GetIdentity() status.Port = meta.OCS_AGENT.GetPort() } + status.SqlPort = meta.MYSQL_PORT status.OBState = oceanbase.GetState() return status, err } // StatusHandler returns the agent status // -// @ID getStatus -// @Summary get agent status -// @Description get agent status -// @Tags v1 -// @Accept application/json -// @Produce application/json -// @Success 200 object http.OcsAgentResponse{data=http.AgentStatus} -// @Router /api/v1/status [get] +// @ID getStatus +// @Summary get agent status +// @Description get agent status +// @Tags v1 +// @Accept application/json +// @Produce application/json +// @Success 200 object http.OcsAgentResponse{data=http.AgentStatus} +// @Router /api/v1/status [get] func StatusHandler(s *http.State) gin.HandlerFunc { return func(c *gin.Context) { status, err := GetAgentStatus(s) @@ -119,14 +121,14 @@ func StatusHandler(s *http.State) gin.HandlerFunc { // StatusHandler returns the agent status // -// @ID getAllAgentsStatus -// @Summary get all agent status -// @Description get all agent status -// @Tags v1 -// @Accept application/json -// @Produce application/json -// @Success 200 object http.OcsAgentResponse{dat=map[string]http.AgentStatus} -// @Router /api/v1/agents/status [get] +// @ID getAllAgentsStatus +// @Summary get all agent status +// @Description get all agent status +// @Tags v1 +// @Accept application/json +// @Produce application/json +// @Success 200 object http.OcsAgentResponse{data=map[string]http.AgentStatus} +// @Router /api/v1/agents/status [get] func GetAllAgentStatus(s *http.State) gin.HandlerFunc { return func(c *gin.Context) { agentsStatus := make(map[string]http.AgentStatus) diff --git a/agent/api/obcluster_handler.go b/agent/api/obcluster_handler.go index e0576134..3a827769 100644 --- a/agent/api/obcluster_handler.go +++ b/agent/api/obcluster_handler.go @@ -48,20 +48,19 @@ func parseRootPwd(pwd string, isForward bool) (string, error) { return pwd, nil } -// @ID obclusterConfig -// @Summary put ob cluster configs -// @Description put ob cluster configs -// @Tags ob -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.ObClusterConfigParams true "obcluster configs" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 401 object http.OcsAgentResponse -// @Failure 400 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/obcluster/config [put] -// @Router /api/v1/obcluster/config [post] +// @ID obclusterConfig +// @Summary put ob cluster configs +// @Description put ob cluster configs +// @Tags ob +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param body body param.ObClusterConfigParams true "obcluster configs" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 401 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/obcluster/config [POST] func obclusterConfigHandler(deleteAll bool) func(c *gin.Context) { return func(c *gin.Context) { var params param.ObClusterConfigParams @@ -120,20 +119,19 @@ func obclusterConfigHandler(deleteAll bool) func(c *gin.Context) { } } -// @ID obServerConfig -// @Summary put observer configs -// @Description put observer configs -// @Tags ob -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.ObServerConfigParams true "ob server configs" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/observer/config [put] -// @Router /api/v1/observer/config [post] +// @ID obServerConfig +// @Summary put observer configs +// @Description put observer configs +// @Tags ob +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param body body param.ObServerConfigParams true "ob server configs" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/observer/config [POST] func obServerConfigHandler(deleteAll bool) func(c *gin.Context) { return func(c *gin.Context) { var params param.ObServerConfigParams @@ -178,18 +176,18 @@ func obServerConfigHandler(deleteAll bool) func(c *gin.Context) { } } -// @ID obInit -// @Summary init ob cluster -// @Description init ob cluster -// @Tags ob -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/ob/init [post] +// @ID obInit +// @Summary init ob cluster +// @Description init ob cluster +// @Tags ob +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/ob/init [post] func obInitHandler(c *gin.Context) { var param param.ObInitParam if err := c.BindJSON(¶m); err != nil { @@ -214,19 +212,19 @@ func obInitHandler(c *gin.Context) { } } -// @ID obStop -// @Summary stop observers -// @Description stop observers or the whole cluster, use param to specify -// @Tags ob -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.ObStopParam true "use 'Scope' to specify the servers/zones/cluster, use 'Force'(optional) to specify whether alter system, use 'ForcePassDag'(optional) to force pass the prev stop dag if need" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/ob/stop [post] +// @ID obStop +// @Summary stop observers +// @Description stop observers or the whole cluster, use param to specify +// @Tags ob +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param body body param.ObStopParam true "use 'Scope' to specify the servers/zones/cluster, use 'Force'(optional) to specify whether alter system, use 'ForcePassDag'(optional) to force pass the prev stop dag if need" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/ob/stop [post] func obStopHandler(c *gin.Context) { var param param.ObStopParam if err := c.BindJSON(¶m); err != nil { @@ -247,19 +245,19 @@ func obStopHandler(c *gin.Context) { } } -// @ID obStart -// @Summary start observers -// @Description start observers or the whole cluster, use param to specify -// @Tags ob -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.StartObParam true "use 'Scope' to specify the servers/zones/cluster, use 'ForcePassDag'(optional) to force pass the prev start dag if need" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/ob/start [post] +// @ID obStart +// @Summary start observers +// @Description start observers or the whole cluster, use param to specify +// @Tags ob +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param body body param.StartObParam true "use 'Scope' to specify the servers/zones/cluster, use 'ForcePassDag'(optional) to force pass the prev start dag if need" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/ob/start [post] func obStartHandler(c *gin.Context) { var param param.StartObParam if err := c.BindJSON(¶m); err != nil { @@ -298,18 +296,18 @@ func obStartHandler(c *gin.Context) { } } -// @ID ScaleOut -// @Summary cluster scale-out -// @Description cluster scale-out -// @Tags ob -// @Accept application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.ClusterScaleOutParam true "scale-out param" -// @Produce application/json -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/ob/scale_out [get] +// @ID ScaleOut +// @Summary cluster scale-out +// @Description cluster scale-out +// @Tags ob +// @Accept application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param body body param.ClusterScaleOutParam true "scale-out param" +// @Produce application/json +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/ob/scale_out [POST] func obClusterScaleOutHandler(c *gin.Context) { var param param.ClusterScaleOutParam if err := c.BindJSON(¶m); err != nil { @@ -320,19 +318,19 @@ func obClusterScaleOutHandler(c *gin.Context) { common.SendResponse(c, data, err) } -// @Summary cluster scale-in -// @Description cluster scale-in -// @Tags ob -// @Accept application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.ClusterScaleInParam true "scale-in param" -// @Produce application/json -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Success 204 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/ob/scale_in [post] -// @Router /api/v1/observer [delete] +// @Summary cluster scale-in +// @Description cluster scale-in +// @Tags ob +// @Accept application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param body body param.ClusterScaleInParam true "scale-in param" +// @Produce application/json +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Success 204 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/ob/scale_in [post] +// @Router /api/v1/observer [delete] func obClusterScaleInHandler(c *gin.Context) { var param param.ClusterScaleInParam if err := c.BindJSON(¶m); err != nil { @@ -359,15 +357,15 @@ func obClusterScaleInHandler(c *gin.Context) { } } -// @ID GetObInfo -// @Summary get ob and agent info -// @Description get ob and agent info -// @Tags ob -// @Accept application/json -// @Produce application/json -// @Success 200 object http.OcsAgentResponse{data=param.ObInfoResp} -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/ob/info [get] +// @ID GetObInfo +// @Summary get ob and agent info +// @Description get ob and agent info +// @Tags ob +// @Accept application/json +// @Produce application/json +// @Success 200 object http.OcsAgentResponse{data=param.ObInfoResp} +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/ob/info [get] func obInfoHandler(c *gin.Context) { if meta.OCS_AGENT.IsFollowerAgent() { master := agentService.GetMasterAgentInfo() @@ -382,6 +380,72 @@ func obInfoHandler(c *gin.Context) { common.SendResponse(c, data, err) } +// @ID obclusterInfo +// @Summary get obcluster info +// @Description get obcluster info +// @Tags obcluster +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse{data=bo.ClusterInfo} +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/obcluster/info [get] +func obclusterInfoHandler(c *gin.Context) { + if !meta.OCS_AGENT.IsClusterAgent() { + common.SendResponse(c, nil, errors.Occurf(errors.ErrKnown, "%s is not cluster agent.", meta.OCS_AGENT.String())) + return + } + clusterInfo, err := ob.GetObclusterSummary() + common.SendResponse(c, clusterInfo, err) +} + +// @ID obclusterParameters +// @Summary get obcluster parameters +// @Description get obcluster parameters +// @Tags obcluster +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse{data=[]bo.ClusterParameter} +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/obcluster/parameters [get] +func obclusterParametersHandler(c *gin.Context) { + if !meta.OCS_AGENT.IsClusterAgent() { + common.SendResponse(c, nil, errors.Occurf(errors.ErrKnown, "%s is not cluster agent.", meta.OCS_AGENT.String())) + return + } + clusterInfo, err := ob.GetAllParameters() + common.SendResponse(c, clusterInfo, err) +} + +// @ID obclusterSetParameters +// @Summary set obcluster parameters +// @Description set obcluster parameters +// @Tags obcluster +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param body body param.SetObclusterParametersParam true "obcluster parameters" +// @Success 204 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/obcluster/parameters [patch] +func obclusterSetParametersHandler(c *gin.Context) { + if !meta.OCS_AGENT.IsClusterAgent() { + common.SendResponse(c, nil, errors.Occurf(errors.ErrKnown, "%s is not cluster agent.", meta.OCS_AGENT.String())) + return + } + var param param.SetObclusterParametersParam + if err := c.BindJSON(¶m); err != nil { + common.SendResponse(c, nil, err) + return + } + common.SendResponse(c, nil, ob.SetObclusterParameters(param.Params)) +} + func isEmergencyMode(c *gin.Context, scope *param.Scope) (res bool, agentErr *errors.OcsAgentError) { if common.IsLocalRoute(c) && ob.ScopeOnlySelf(scope) && !meta.OCS_AGENT.IsClusterAgent() { return true, nil @@ -392,19 +456,19 @@ func isEmergencyMode(c *gin.Context, scope *param.Scope) (res bool, agentErr *er return false, nil } -// @ID agentUpgradeCheck -// @Summary check agent upgrade -// @Description check agent upgrade -// @Tags upgrade -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.UpgradeCheckParam true "agent upgrade check params" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/agent/upgrade/check [post] +// @ID agentUpgradeCheck +// @Summary check agent upgrade +// @Description check agent upgrade +// @Tags upgrade +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param body body param.UpgradeCheckParam true "agent upgrade check params" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/agent/upgrade/check [post] func agentUpgradeCheckHandler(c *gin.Context) { var param param.UpgradeCheckParam if err := c.BindJSON(¶m); err != nil { @@ -415,19 +479,19 @@ func agentUpgradeCheckHandler(c *gin.Context) { common.SendResponse(c, task, err) } -// @ID obUpgradeCheck -// @Summary check ob upgrade -// @Description check ob upgrade -// @Tags upgrade -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.UpgradeCheckParam true "ob upgrade check params" -// @Success 200 object http.OcsAgentResponse -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/ob/upgrade/check [post] +// @ID obUpgradeCheck +// @Summary check ob upgrade +// @Description check ob upgrade +// @Tags upgrade +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param body body param.UpgradeCheckParam true "ob upgrade check params" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/ob/upgrade/check [post] func obUpgradeCheckHandler(c *gin.Context) { var param param.UpgradeCheckParam if err := c.BindJSON(¶m); err != nil { @@ -438,18 +502,42 @@ func obUpgradeCheckHandler(c *gin.Context) { common.SendResponse(c, task, err) } -// @ID UpgradePkgUpload -// @Summary upload upgrade package -// @Description upload upgrade package -// @Tags upgrade -// @Accept multipart/form-data -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param file formData file true "ob upgrade package" -// @Success 200 object http.OcsAgentResponse{data=oceanbase.UpgradePkgInfo} -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/upgrade/package [post] +// @ID UpgradePkgRoute +// @Summary get upgrade route of target ob package +// @Description get upgrade route of target ob package +// @Tags upgrade +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param version query string true "version" +// @Param release query string true "release" +// @Success 200 object []ob.RouteNode +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/ob/upgrade/route [get] +func obPkgUpgradeRouteHandler(c *gin.Context) { + version := c.Query("version") + release := c.Query("release") + if version == "" || release == "" { + common.SendResponse(c, nil, errors.Occur(errors.ErrIllegalArgument, "version or release is empty")) + return + } + routes, err := ob.GetObPackageUpgradeDepYaml(version, release) + common.SendResponse(c, routes, err) +} + +// @ID UpgradePkgUpload +// @Summary upload upgrade package +// @Description upload upgrade package +// @Tags upgrade +// @Accept multipart/form-data +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param file formData file true "ob upgrade package" +// @Success 200 object http.OcsAgentResponse{data=oceanbase.UpgradePkgInfo} +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/upgrade/package [post] func pkgUploadHandler(c *gin.Context) { if !meta.OCS_AGENT.IsClusterAgent() { common.SendResponse(c, nil, errors.Occur(errors.ErrObclusterNotFound, "Unable to proceed with package upload. Please ensure the 'init' command is executed before attempting to upload.")) @@ -457,7 +545,7 @@ func pkgUploadHandler(c *gin.Context) { } file, _, err := c.Request.FormFile("file") if err != nil { - common.SendResponse(c, nil, errors.Occur(errors.ErrKnown, "get file failed.", err)) + common.SendResponse(c, nil, errors.Occurf(errors.ErrKnown, "get file failed: %s", err)) return } defer file.Close() @@ -465,53 +553,107 @@ func pkgUploadHandler(c *gin.Context) { common.SendResponse(c, &data, agentErr) } -// @ID ParamsBackup -// @Summary backup params -// @Description backup params -// @Tags upgrade -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Success 200 object http.OcsAgentResponse{data=[]oceanbase.ObParameters} -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/upgrade/params/backup [post] +// @ID UpgradePkgInfo +// @Summary get all upgrade package infos +// @Description get all upgrade package infos +// @Tags upgrade +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse{data=[]bo.UpgradePkgInfo} +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/upgrade/package/info [get] +func pkgInfoHandler(c *gin.Context) { + if !meta.OCS_AGENT.IsClusterAgent() { + common.SendResponse(c, nil, errors.Occur(errors.ErrObclusterNotFound, "Unable to get package infos from ocs database. Please ensure the 'init' command is executed before attempting to upload.")) + return + } + + data, agentErr := ob.GetAllUpgradePkgInfos() + common.SendResponse(c, data, agentErr) +} + +// @ID NewPkgUpload +// @Summary upload upgrade package without body encryption +// @Description upload upgrade package without body encryption +// @Tags package +// @Accept multipart/form-data +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param X-OCS-File-SHA256 header string true "SHA256 of the file" +// @Param file formData file true "ob upgrade package" +// @Success 200 object http.OcsAgentResponse{data=bo.UpgradePkgInfo} +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/package [post] +func newPkgUploadHandler(c *gin.Context) { + if !meta.OCS_AGENT.IsClusterAgent() { + common.SendResponse(c, nil, errors.Occur(errors.ErrObclusterNotFound, "Unable to proceed with package upload. Please ensure the 'init' command is executed before attempting to upload.")) + return + } + file, _, err := c.Request.FormFile("file") + if err != nil { + common.SendResponse(c, nil, errors.Occurf(errors.ErrKnown, "get file failed: %s", err)) + return + } + defer file.Close() + data, agentErr := ob.UpgradePkgUpload(file) + if agentErr != nil || data == nil { + common.SendResponse(c, nil, agentErr) + return + } + bo := data.ToBO() + common.SendResponse(c, &bo, agentErr) +} + +// @ID ParamsBackup +// @Summary backup params +// @Description backup params +// @Tags upgrade +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse{data=[]oceanbase.ObParameters} +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/upgrade/params/backup [post] func paramsBackupHandler(c *gin.Context) { data, err := ob.ParamsBackup() common.SendResponse(c, data, err) } -// @ID ParamsRestore -// @Summary restore params -// @Description restore params -// @Tags upgrade -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.RestoreParams true "restore params" -// @Success 200 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/upgrade/params/restore [post] +// @ID ParamsRestore +// @Summary restore params +// @Description restore params +// @Tags upgrade +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param body body param.RestoreParams true "restore params" +// @Success 200 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/upgrade/params/restore [post] func paramsRestoreHandler(c *gin.Context) { var param param.RestoreParams err := ob.ParamsRestore(param) common.SendResponse(c, nil, err) } -// @ID agentUpgrade -// @Summary upgrade agent -// @Description upgrade agent -// @Tags upgrade -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.UpgradeCheckParam true "agent upgrade check params" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/agent/upgrade [post] +// @ID agentUpgrade +// @Summary upgrade agent +// @Description upgrade agent +// @Tags upgrade +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param body body param.UpgradeCheckParam true "agent upgrade check params" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/agent/upgrade [post] func agentUpgradeHandler(c *gin.Context) { var param param.UpgradeCheckParam if err := c.BindJSON(¶m); err != nil { @@ -522,19 +664,19 @@ func agentUpgradeHandler(c *gin.Context) { common.SendResponse(c, dag, err) } -// @ID obUpgrade -// @Summary upgrade ob -// @Description upgrade ob -// @Tags upgrade -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.ObUpgradeParam true "ob upgrade params" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/ob/upgrade [post] +// @ID obUpgrade +// @Summary upgrade ob +// @Description upgrade ob +// @Tags upgrade +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param body body param.ObUpgradeParam true "ob upgrade params" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/ob/upgrade [post] func obUpgradeHandler(c *gin.Context) { var param param.ObUpgradeParam if err := c.BindJSON(¶m); err != nil { @@ -558,3 +700,39 @@ func obAgentsHandler(c *gin.Context) { data, err := ob.GetObAgents() common.SendResponse(c, data, err) } + +// @ID getObclusterCharsets +// @Summary get obcluster charsets +// @Description get obcluster charsets +// @Tags ob +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse{data=[]bo.CharsetInfo} +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/obcluster/charsets [get] +func getObclusterCharsets(c *gin.Context) { + if !meta.OCS_AGENT.IsClusterAgent() { + common.SendResponse(c, nil, errors.Occurf(errors.ErrKnown, "%s is not cluster agent.", meta.OCS_AGENT.String())) + return + } + charsets, err := ob.GetObclusterCharsets() + common.SendResponse(c, charsets, err) +} + +// @ID getUnitConfigLimit +// @Summary get resource unit config limit +// @Description get resource unit config limit +// @Tags obcluster +// @Accept application/json +// @Produce application/json +// @Success 200 object http.OcsAgentResponse{data=param.ClusterUnitConfigLimit} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/obcluster/unit-config-limit [get] +func getUnitConfigLimitHandler(c *gin.Context) { + unit := ob.GetClusterUnitSpecLimit() + common.SendResponse(c, unit, nil) +} diff --git a/agent/api/obproxy_route.go b/agent/api/obproxy_route.go new file mode 100644 index 00000000..57b8c064 --- /dev/null +++ b/agent/api/obproxy_route.go @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package api + +import ( + "github.com/gin-gonic/gin" + + "github.com/oceanbase/obshell/agent/api/common" + "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/executor/obproxy" + "github.com/oceanbase/obshell/agent/secure" + "github.com/oceanbase/obshell/param" +) + +func InitObproxyRoutes(r *gin.RouterGroup, isLocalRoute bool) { + obproxy := r.Group(constant.URI_OBPROXY_GROUP) + if !isLocalRoute { + obproxy.Use(common.Verify(secure.ROUTE_OBPROXY)) + } + + // obproxy routes + obproxy.POST("", obproxyAddHandler) + obproxy.DELETE("", obproxyDeleteHandler) + obproxy.POST(constant.URI_START, obproxyStartHandler) + obproxy.POST(constant.URI_STOP, obproxyStopHandler) + obproxy.POST(constant.URI_PACKAGE, obproxyPkgUploadHandler) + obproxy.POST(constant.URI_UPGRADE, obproxyUpgradeHandler) +} + +// @ID obproxyAdd +// @Summary Add obproxy +// @Tags Obproxy +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Agent-Header header string true "Authorization" +// @Param body body param.AddObproxyParam true "Add obproxy" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/obproxy [post] +func obproxyAddHandler(c *gin.Context) { + var param param.AddObproxyParam + if err := c.BindJSON(¶m); err != nil { + common.SendResponse(c, nil, err) + return + } + dag, err := obproxy.AddObproxy(param) + common.SendResponse(c, dag, err) +} + +// @ID obproxyStop +// @Summary Stop obproxy +// @Tags Obproxy +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Agent-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/obproxy/stop [post] +func obproxyStopHandler(c *gin.Context) { + dag, err := obproxy.StopObproxy() + common.SendResponse(c, dag, err) +} + +// @ID obproxyStart +// @Summary Start obproxy +// @Tags Obproxy +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Agent-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/obproxy/start [post] +func obproxyStartHandler(c *gin.Context) { + dag, err := obproxy.StartObproxy() + common.SendResponse(c, dag, err) +} + +// @ID obproxyDelete +// @Summary Delete obproxy +// @Tags Obproxy +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Agent-Header header string true "Authorization" +// @Success 204 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/obproxy [delete] +func obproxyDeleteHandler(c *gin.Context) { + dag, err := obproxy.DeleteObproxy() + if dag == nil && err == nil { + common.SendNoContentResponse(c, nil) + } + common.SendResponse(c, dag, err) +} + +// @ID obproxyUpgrade +// @Summary Upgrade obproxy +// @Tags Obproxy +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Agent-Header header string true "Authorization" +// @Param body body param.UpgradeObproxyParam true "Upgrade obproxy" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/obproxy/upgrade [post] +func obproxyUpgradeHandler(c *gin.Context) { + var param param.UpgradeObproxyParam + if err := c.BindJSON(¶m); err != nil { + common.SendResponse(c, nil, err) + return + } + + dag, err := obproxy.UpgradeObproxy(param) + common.SendResponse(c, dag, err) +} + +// @ID obproxyPkgUpload +// @Summary Upload obproxy package +// @Tags Obproxy +// @Accept multipart/form-data +// @Produce application/json +// @Param X-OCS-Agent-Header header string true "Authorization" +// @Param file formData file true "Obproxy package" +// @Success 200 object http.OcsAgentResponse{data=sqlite.UpgradePkgInfo} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/obproxy/package [post] +func obproxyPkgUploadHandler(c *gin.Context) { + file, _, err := c.Request.FormFile("file") + if err != nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrKnown, "get file failed.", err)) + return + } + defer file.Close() + data, agentErr := obproxy.UpgradePkgUpload(file) + common.SendResponse(c, &data, agentErr) +} diff --git a/agent/api/pool_handler.go b/agent/api/pool_handler.go index 10d461d8..32df574e 100644 --- a/agent/api/pool_handler.go +++ b/agent/api/pool_handler.go @@ -25,19 +25,19 @@ import ( "github.com/oceanbase/obshell/agent/meta" ) -// @ID poolDrop -// @Summary drop resource pool -// @Description drop resource pool which is not used by any tenant -// @Tags resource-pool -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param name path string true "resource pool name" -// @Success 200 object http.OcsAgentResponse -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/resource-pool/{name} [delete] +// @ID poolDrop +// @Summary drop resource pool +// @Description drop resource pool which is not used by any tenant +// @Tags resource-pool +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "resource pool name" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/resource-pool/{name} [delete] func poolDropHandler(c *gin.Context) { name := c.Param(constant.URI_PARAM_NAME) if name == "" { @@ -52,18 +52,18 @@ func poolDropHandler(c *gin.Context) { common.SendResponse(c, nil, err) } -// @ID poolList -// @Summary list all resource pools -// @Description list all resource pools in the cluster -// @Tags resource-pool -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Success 200 object http.OcsAgentResponse{data=[]oceanbase.DbaObResourcePool} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/resources-pool [get] +// @ID poolList +// @Summary list all resource pools +// @Description list all resource pools in the cluster +// @Tags resource-pool +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse{data=[]oceanbase.DbaObResourcePool} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/resources-pool [get] func poolListHandler(c *gin.Context) { if !meta.OCS_AGENT.IsClusterAgent() { common.SendResponse(c, nil, errors.Occurf(errors.ErrKnown, "%s is not cluster agent.", meta.OCS_AGENT.String())) diff --git a/agent/api/recyclebin_handler.go b/agent/api/recyclebin_handler.go index eecf8741..151bce87 100644 --- a/agent/api/recyclebin_handler.go +++ b/agent/api/recyclebin_handler.go @@ -26,19 +26,19 @@ import ( "github.com/oceanbase/obshell/param" ) -// @ID recyclebinTenantPurge -// @Summary purge recyclebin tenant -// @Description purge tenant in recyclebin -// @Tags recyclebin -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param name path string true "original tenant name or object name in recyclebin" -// @Success 200 object http.OcsAgentResponse -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/recyclebin/bin/:name [delete] +//@ID recyclebinTenantPurge +//@Summary purge recyclebin tenant +//@Description purge tenant in recyclebin +//@Tags recyclebin +//@Accept application/json +//@Produce application/json +//@Param X-OCS-Header header string true "Authorization" +//@Param name path string true "original tenant name or object name in recyclebin" +//@Success 200 object http.OcsAgentResponse +//@Failure 400 object http.OcsAgentResponse +//@Failure 401 object http.OcsAgentResponse +//@Failure 500 object http.OcsAgentResponse +//@Router /api/v1/recyclebin/bin/:name [delete] func recyclebinPurgeTenantHandler(c *gin.Context) { name := c.Param(constant.URI_PARAM_NAME) if name == "" { @@ -56,18 +56,18 @@ func recyclebinPurgeTenantHandler(c *gin.Context) { } } -// @ID recyclebinTenantList -// @Summary list all tenants in recyclebin -// @Description list all tenants in recyclebin -// @Tags recyclebin -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Success 200 object http.OcsAgentResponse{data=[]oceanbase.DbaRecyclebin} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/recyclebin/tenants [get] +//@ID recyclebinTenantList +//@Summary list all tenants in recyclebin +//@Description list all tenants in recyclebin +//@Tags recyclebin +//@Accept application/json +//@Produce application/json +//@Param X-OCS-Header header string true "Authorization" +//@Success 200 object http.OcsAgentResponse{data=[]oceanbase.DbaRecyclebin} +//@Failure 400 object http.OcsAgentResponse +//@Failure 401 object http.OcsAgentResponse +//@Failure 500 object http.OcsAgentResponse +//@Router /api/v1/recyclebin/tenants [get] func recyclebinListTenantHandler(c *gin.Context) { if !meta.OCS_AGENT.IsClusterAgent() { common.SendResponse(c, nil, errors.Occurf(errors.ErrKnown, "%s is not cluster agent.", meta.OCS_AGENT.String())) @@ -77,20 +77,20 @@ func recyclebinListTenantHandler(c *gin.Context) { common.SendResponse(c, tenants, err) } -// @ID recyclebinFlashbackTenant -// @Summary flashback tenant from recyclebin -// @Description flashback tenant from recyclebin -// @Tags recyclebin -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param name path string true "original tenant name or object name in recyclebin" -// @Param body body param.FlashBackTenantParam true "Flashback tenant param" -// @Success 200 object http.OcsAgentResponse -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/recyclebin/flashback/{name} [post] +//@ID recyclebinFlashbackTenant +//@Summary flashback tenant from recyclebin +//@Description flashback tenant from recyclebin +//@Tags recyclebin +//@Accept application/json +//@Produce application/json +//@Param X-OCS-Header header string true "Authorization" +//@Param name path string true "original tenant name or object name in recyclebin" +//@Param body body param.FlashBackTenantParam true "Flashback tenant param" +//@Success 200 object http.OcsAgentResponse +//@Failure 400 object http.OcsAgentResponse +//@Failure 401 object http.OcsAgentResponse +//@Failure 500 object http.OcsAgentResponse +//@Router /api/v1/recyclebin/flashback/{name} [post] func recyclebinFlashbackTenantHandler(c *gin.Context) { name := c.Param(constant.URI_PARAM_NAME) if name == "" { diff --git a/agent/api/secure_handler.go b/agent/api/secure_handler.go index d7a5eebf..31fe60e3 100644 --- a/agent/api/secure_handler.go +++ b/agent/api/secure_handler.go @@ -23,14 +23,14 @@ import ( "github.com/oceanbase/obshell/agent/secure" ) -// @ID getSecret -// @Summary get secret -// @Description get secret -// @Tags v1 -// @Accept application/json -// @Produce application/json -// @Success 200 object http.OcsAgentResponse{data=meta.AgentSecret} -// @Router /api/v1/secret [get] +// @ID getSecret +// @Summary get secret +// @Description get secret +// @Tags v1 +// @Accept application/json +// @Produce application/json +// @Success 200 object http.OcsAgentResponse{data=meta.AgentSecret} +// @Router /api/v1/secret [get] func secretHandler(c *gin.Context) { ctx := common.NewContextWithTraceId(c) data := secure.GetSecret(ctx) diff --git a/agent/api/task_handler.go b/agent/api/task_handler.go index 472a7563..6cc383f8 100644 --- a/agent/api/task_handler.go +++ b/agent/api/task_handler.go @@ -22,22 +22,27 @@ import ( "github.com/oceanbase/obshell/agent/api/common" "github.com/oceanbase/obshell/agent/constant" "github.com/oceanbase/obshell/agent/executor/task" + "github.com/oceanbase/obshell/agent/secure" ) func InitTaskRoutes(r *gin.RouterGroup, isLocalRoute bool) { group := r.Group(constant.URI_TASK_GROUP) if !isLocalRoute { - group.Use(common.Verify()) + group.Use(common.Verify(secure.ROUTE_TASK)) } group.GET(constant.URI_SUB_TASK+"/:id", task.GetSubTaskDetail) group.GET(constant.URI_NODE+"/:id", task.GetNodeDetail) group.GET(constant.URI_DAG+"/:id", task.GetDagDetail) + group.POST(constant.URI_DAG+"/:id", task.DagHandler) + group.GET(constant.URI_DAGS+constant.URI_OB_GROUP, task.GetAllClusterDags) + group.GET(constant.URI_DAGS+constant.URI_AGENT_GROUP, task.GetAllAgentDags) + group.GET(constant.URI_SUB_TASK+"/:id"+constant.URI_LOGS, task.GetFullSubTaskLogs) group.GET(constant.URI_DAG+constant.URI_MAINTAIN+constant.URI_OB_GROUP, task.GetObLastMaintenanceDag) group.GET(constant.URI_DAG+constant.URI_MAINTAIN+constant.URI_AGENT_GROUP, task.GetAgentLastMaintenanceDag) group.GET(constant.URI_DAG+constant.URI_MAINTAIN+constant.URI_AGENTS_GROUP, task.GetAllAgentLastMaintenanceDag) group.GET(constant.URI_DAG+constant.URI_UNFINISH, task.GetUnfinishedDags) group.GET(constant.URI_DAG+constant.URI_OB_GROUP+constant.URI_UNFINISH, task.GetClusterUnfinishDags) group.GET(constant.URI_DAG+constant.URI_AGENT_GROUP+constant.URI_UNFINISH, task.GetAgentUnfinishDags) + group.GET(constant.URI_DAG+constant.URI_AGENT_GROUP+constant.URI_MAIN_DAGS, task.GetAgentMainDags) - group.POST(constant.URI_DAG+"/:id", task.DagHandler) } diff --git a/agent/api/tenant_handler.go b/agent/api/tenant_handler.go index 02352c39..bf8c70c6 100644 --- a/agent/api/tenant_handler.go +++ b/agent/api/tenant_handler.go @@ -16,6 +16,9 @@ package api import ( + "strconv" + "time" + "github.com/gin-gonic/gin" "github.com/oceanbase/obshell/agent/api/common" @@ -44,33 +47,59 @@ func InitTenantRoutes(v1 *gin.RouterGroup, isLocalRoute bool) { tenant.PUT(constant.URI_PATH_PARAM_NAME+constant.URI_PRIMARYZONE, tenantModifyPrimaryZoneHandler) tenant.PUT(constant.URI_PATH_PARAM_NAME+constant.URI_ROOTPASSWORD, tenantModifyPasswordHandler) + tenant.POST(constant.URI_PATH_PARAM_NAME+constant.URI_ROOTPASSWORD+constant.URI_PERSIST, checkClusterAgentWrapper(common.AutoForwardToMaintainerWrapper(persistTenantRootPassword))) tenant.PUT(constant.URI_PATH_PARAM_NAME+constant.URI_WHITELIST, tenantModifyWhitelistHandler) tenant.PUT(constant.URI_PATH_PARAM_NAME+constant.URI_PARAMETERS, tenantSetParametersHandler) tenant.PUT(constant.URI_PATH_PARAM_NAME+constant.URI_VARIABLES, tenantSetVariableHandler) tenant.GET(constant.URI_PATH_PARAM_NAME, getTenantInfo) + tenant.GET(constant.URI_PATH_PARAM_NAME+constant.URI_PRECHECK, tenantHandlerWrapper(tenantPrecheck)) tenant.GET(constant.URI_PATH_PARAM_NAME+constant.URI_PARAMETER+constant.URI_PATH_PARAM_PARA, getTenantParameter) tenant.GET(constant.URI_PATH_PARAM_NAME+constant.URI_VARIABLE+constant.URI_PATH_PARAM_VAR, getTenantVariable) tenant.GET(constant.URI_PATH_PARAM_NAME+constant.URI_PARAMETERS, getTenantParameters) tenant.GET(constant.URI_PATH_PARAM_NAME+constant.URI_VARIABLES, getTenantVariables) + tenant.POST(constant.URI_PATH_PARAM_NAME+constant.URI_USER, tenantHandlerWrapper(createUserHandler)) + tenant.DELETE(constant.URI_PATH_PARAM_NAME+constant.URI_USER+constant.URI_PATH_PARAM_USER, tenantHandlerWrapper(dropUserHandler)) + tenant.GET(constant.URI_PATH_PARAM_NAME+constant.URI_USER, tenantHandlerWrapper(listUsers)) + tenant.GET(constant.URI_PATH_PARAM_NAME+constant.URI_USER+constant.URI_PATH_PARAM_USER, tenantHandlerWrapper(getUser)) + tenant.PUT(constant.URI_PATH_PARAM_NAME+constant.URI_USER+constant.URI_PATH_PARAM_USER+constant.URI_DB_PRIVILEGE, tenantHandlerWrapper(modifyDbPrivilege)) + tenant.PUT(constant.URI_PATH_PARAM_NAME+constant.URI_USER+constant.URI_PATH_PARAM_USER+constant.URI_GLOBAL_PRIVILEGE, tenantHandlerWrapper(modifyGlobalPrivilege)) + tenant.PUT(constant.URI_PATH_PARAM_NAME+constant.URI_USER+constant.URI_PATH_PARAM_USER+constant.URI_PASSWORD, tenantHandlerWrapper(changePassword)) + tenant.PUT(constant.URI_PATH_PARAM_NAME+constant.URI_USER+constant.URI_PATH_PARAM_USER+constant.URI_LOCK, tenantHandlerWrapper(lockUser)) + tenant.GET(constant.URI_PATH_PARAM_NAME+constant.URI_USER+constant.URI_PATH_PARAM_USER+constant.URI_STATS, tenantHandlerWrapper(getUserStats)) + tenant.DELETE(constant.URI_PATH_PARAM_NAME+constant.URI_USER+constant.URI_PATH_PARAM_USER+constant.URI_LOCK, tenantHandlerWrapper(unlockUser)) + tenant.POST(constant.URI_PATH_PARAM_NAME+constant.URI_DATABASES, tenantHandlerWrapper(createDatabase)) + tenant.GET(constant.URI_PATH_PARAM_NAME+constant.URI_DATABASES, tenantHandlerWrapper(listDatabases)) + tenant.PUT(constant.URI_PATH_PARAM_NAME+constant.URI_DATABASES+constant.URI_PATH_PARAM_DATABASE, tenantHandlerWrapper(updateDatabase)) + tenant.GET(constant.URI_PATH_PARAM_NAME+constant.URI_DATABASES+constant.URI_PATH_PARAM_DATABASE, tenantHandlerWrapper(getDatabase)) + tenant.DELETE(constant.URI_PATH_PARAM_NAME+constant.URI_DATABASES+constant.URI_PATH_PARAM_DATABASE, tenantHandlerWrapper(deleteDatabase)) + + // for compaction + tenant.GET(constant.URI_PATH_PARAM_NAME+constant.URI_COMPACTION, getTenantCompactionHandler) + tenant.POST(constant.URI_PATH_PARAM_NAME+constant.URI_COMPACT, tenantMajorCompactionHandler) + tenant.GET(constant.URI_TOP_COMPACTIONS, getTenantTopCompactionsHandler) + tenant.DELETE(constant.URI_PATH_PARAM_NAME+constant.URI_COMPACTION_ERROR, clearTenantCompactionErrorHandler) + + // for slow sql + tenant.GET(constant.URI_TOP_SLOW_SQLS, getTenantTopSlowSqlRankHandler) tenants.GET(constant.URI_OVERVIEW, getTenantOverView) } -// @ID tenantCreate -// @Summary create tenant -// @Description create tenant -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.CreateTenantParam true "create tenant params" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 400 object http.OcsAgentResponse -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenant [post] +// @ID tenantCreate +// @Summary create tenant +// @Description create tenant +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param body body param.CreateTenantParam true "create tenant params" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant [post] func tenantCreateHandler(c *gin.Context) { var param param.CreateTenantParam if err := c.BindJSON(¶m); err != nil { @@ -89,30 +118,20 @@ func tenantCreateHandler(c *gin.Context) { common.SendResponse(c, dag, err) } -func tenantCheckWithName(c *gin.Context) (string, error) { - name := c.Param(constant.URI_PARAM_NAME) - if name == "" { - return "", errors.Occur(errors.ErrIllegalArgument, "Tenant name is empty.") - } - if !meta.OCS_AGENT.IsClusterAgent() { - return "", errors.Occurf(errors.ErrKnown, "%s is not cluster agent.", meta.OCS_AGENT.String()) - } - return name, nil -} - -// @ID tenantDrop -// @Summary drop tenant -// @Description drop tenant -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.DropTenantParam true "drop tenant params" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenant/{name} [delete] +// @ID tenantDrop +// @Summary drop tenant +// @Description drop tenant +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param body body param.DropTenantParam true "drop tenant params" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name} [delete] func tenantDropHandler(c *gin.Context) { var param param.DropTenantParam if err := c.BindJSON(¶m); err != nil { @@ -132,19 +151,20 @@ func tenantDropHandler(c *gin.Context) { } } -// @ID tenantRename -// @Summary rename tenant -// @Description rename tenant -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.RenameTenantParam true "rename tenant params" -// @Success 200 object http.OcsAgentResponse -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenant/{name} [put] +// @ID tenantRename +// @Summary rename tenant +// @Description rename tenant +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param body body param.RenameTenantParam true "rename tenant params" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name} [put] func tenantRenameHandler(c *gin.Context) { var param param.RenameTenantParam if err := c.BindJSON(¶m); err != nil { @@ -160,18 +180,19 @@ func tenantRenameHandler(c *gin.Context) { common.SendResponse(c, nil, tenant.RenameTenant(param)) } -// @ID tenantLock -// @Summary lock tenant -// @Description lock tenant -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Success 200 object http.OcsAgentResponse -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenant/{name}/lock [post] +// @ID tenantLock +// @Summary lock tenant +// @Description lock tenant +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/lock [post] func tenantLockHandler(c *gin.Context) { name, err := tenantCheckWithName(c) if err != nil { @@ -181,18 +202,19 @@ func tenantLockHandler(c *gin.Context) { common.SendResponse(c, nil, tenant.LockTenant(name)) } -// @ID tenantUnlock -// @Summary unlock tenant -// @Description unlock tenant -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Success 200 object http.OcsAgentResponse -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenant/{name}/lock [delete] +// @ID tenantUnlock +// @Summary unlock tenant +// @Description unlock tenant +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/lock [delete] func tenantUnlockHandler(c *gin.Context) { name, err := tenantCheckWithName(c) if err != nil { @@ -202,19 +224,20 @@ func tenantUnlockHandler(c *gin.Context) { common.SendResponse(c, nil, tenant.UnlockTenant(name)) } -// @ID tenantAddReplicas -// @Summary add replicas to tenant -// @Description add replicas to tenant -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.ScaleOutTenantReplicasParam true "add tenant replicas params" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenant/{name}/replicas [post] +// @ID tenantAddReplicas +// @Summary add replicas to tenant +// @Description add replicas to tenant +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param body body param.ScaleOutTenantReplicasParam true "add tenant replicas params" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/replicas [post] func tenantAddReplicasHandler(c *gin.Context) { name, err := tenantCheckWithName(c) if err != nil { @@ -230,19 +253,20 @@ func tenantAddReplicasHandler(c *gin.Context) { common.SendResponse(c, dag, err) } -// @ID tenantRemoveReplicas -// @Summary remove replicas from tenant -// @Description remove replicas from tenant -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.ScaleInTenantReplicasParam true "remove tenant replicas params" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenant/{name}/replicas [delete] +// @ID tenantRemoveReplicas +// @Summary remove replicas from tenant +// @Description remove replicas from tenant +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param body body param.ScaleInTenantReplicasParam true "remove tenant replicas params" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/replicas [delete] func tenantRemoveReplicasHandler(c *gin.Context) { name, err := tenantCheckWithName(c) if err != nil { @@ -261,19 +285,20 @@ func tenantRemoveReplicasHandler(c *gin.Context) { } } -// @ID tenantModifyReplicas -// @Summary modify tenant replicas -// @Description modify tenant replicas -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.ModifyReplicasParam true "modify tenant replicas params" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenant/{name}/replicas [patch] +// @ID tenantModifyReplicas +// @Summary modify tenant replicas +// @Description modify tenant replicas +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param body body param.ModifyReplicasParam true "modify tenant replicas params" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/replicas [patch] func tenantModifyReplicasHandler(c *gin.Context) { name, err := tenantCheckWithName(c) if err != nil { @@ -293,19 +318,20 @@ func tenantModifyReplicasHandler(c *gin.Context) { } } -// @ID tenantModifyWhitelist -// @Summary modify tenant whitelist -// @Description modify tenant whitelist -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.ModifyTenantWhitelistParam true "modify whitelist params" -// @Success 200 object http.OcsAgentResponse -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenant/{name}/whitelist [put] +// @ID tenantModifyWhitelist +// @Summary modify tenant whitelist +// @Description modify tenant whitelist +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param body body param.ModifyTenantWhitelistParam true "modify whitelist params" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/whitelist [put] func tenantModifyWhitelistHandler(c *gin.Context) { name, err := tenantCheckWithName(c) if err != nil { @@ -325,19 +351,20 @@ func tenantModifyWhitelistHandler(c *gin.Context) { common.SendResponse(c, nil, err) } -// @ID tenantModifyPassword -// @Summary modify tenant root password -// @Description modify tenant root password -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.ModifyTenantRootPasswordParam true "modify tenant root password params" -// @Success 200 object http.OcsAgentResponse -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenant/{name}/rootpassword [put] +// @ID tenantModifyPassword +// @Summary modify tenant root password +// @Description modify tenant root password +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param body body param.ModifyTenantRootPasswordParam true "modify tenant root password params" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/password [put] func tenantModifyPasswordHandler(c *gin.Context) { name, err := tenantCheckWithName(c) if err != nil { @@ -356,19 +383,46 @@ func tenantModifyPasswordHandler(c *gin.Context) { common.SendResponse(c, nil, err) } -// @ID tenantModifyPrimaryZone -// @Summary modify tenant primary zone -// @Description modify tenant primary zone -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.ModifyTenantPrimaryZoneParam true "modify tenant primary zone params" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenant/{name}/primaryzone [put] +// @ID persistTenantRootPassword +// @Summary persist tenant root password +// @Description persist tenant root password +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param body body param.PersistTenantRootPasswordParam true "persist tenant root password param" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/password/persist [POST] +func persistTenantRootPassword(c *gin.Context) { + //all checks are done in the wrapper, just save the password + name := c.Param(constant.URI_PARAM_NAME) + var param param.PersistTenantRootPasswordParam + if err := c.BindJSON(¶m); err != nil { + common.SendResponse(c, nil, err) + return + } + err := tenant.PersistTenantRootPassword(c, name, param.Password) + common.SendResponse(c, nil, err) +} + +// @ID tenantModifyPrimaryZone +// @Summary modify tenant primary zone +// @Description modify tenant primary zone +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param body body param.ModifyTenantPrimaryZoneParam true "modify tenant primary zone params" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/primary-zone [put] func tenantModifyPrimaryZoneHandler(c *gin.Context) { name, err := tenantCheckWithName(c) if err != nil { @@ -384,19 +438,20 @@ func tenantModifyPrimaryZoneHandler(c *gin.Context) { common.SendResponse(c, dag, err) } -// @ID tenantSetParameters -// @Summary set tenant parameters -// @Description set tenant parameters -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.SetTenantParametersParam true "set tenant parameters params" -// @Success 200 object http.OcsAgentResponse -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenant/{name}/parameters [put] +// @ID tenantSetParameters +// @Summary set tenant parameters +// @Description set tenant parameters +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param body body param.SetTenantParametersParam true "set tenant parameters params" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/parameters [put] func tenantSetParametersHandler(c *gin.Context) { name, err := tenantCheckWithName(c) if err != nil { @@ -411,19 +466,20 @@ func tenantSetParametersHandler(c *gin.Context) { common.SendResponse(c, nil, tenant.SetTenantParameters(name, param.Parameters)) } -// @ID tenantSetVariable -// @Summary set tenant variables -// @Description set tenant variables -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param body body param.SetTenantVariablesParam true "set tenant global variables params" -// @Success 200 object http.OcsAgentResponse -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenant/{name}/variables [put] +// @ID tenantSetVariable +// @Summary set tenant variables +// @Description set tenant variables +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param body body param.SetTenantVariablesParam true "set tenant global variables params" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/variables [put] func tenantSetVariableHandler(c *gin.Context) { name, err := tenantCheckWithName(c) if err != nil { @@ -435,21 +491,22 @@ func tenantSetVariableHandler(c *gin.Context) { common.SendResponse(c, nil, err) return } - common.SendResponse(c, nil, tenant.SetTenantVariables(name, param.Variables)) + common.SendResponse(c, nil, tenant.SetTenantVariables(c, name, param)) } -// @ID getTenantInfo -// @Summary get tenant info -// @Description get tenant info -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Success 200 object http.OcsAgentResponse{data=bo.TenantInfo} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenant/{name} [get] +// @ID getTenantInfo +// @Summary get tenant info +// @Description get tenant info +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Success 200 object http.OcsAgentResponse{data=bo.TenantInfo} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name} [get] func getTenantInfo(c *gin.Context) { name, err := tenantCheckWithName(c) if err != nil { @@ -460,19 +517,20 @@ func getTenantInfo(c *gin.Context) { common.SendResponse(c, tenantInfo, err) } -// @ID getTenantParameter -// @Summary get tenant parameter -// @Description get tenant parameter -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param para path string true "parameter name" -// @Success 200 object http.OcsAgentResponse{data=oceanbase.GvObParameter} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenant/{name}/parameter/{para} [get] +// @ID getTenantParameter +// @Summary get tenant parameter +// @Description get tenant parameter +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param para path string true "parameter name" +// @Success 200 object http.OcsAgentResponse{data=oceanbase.GvObParameter} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/parameter/{para} [get] func getTenantParameter(c *gin.Context) { name, err := tenantCheckWithName(c) if err != nil { @@ -490,19 +548,20 @@ func getTenantParameter(c *gin.Context) { common.SendResponse(c, parameter, err) } -// @ID getTenantParameters -// @Summary get tenant parameters -// @Description get tenant parameters -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param filter query string false "filter format" -// @Success 200 object http.OcsAgentResponse{data=[]oceanbase.GvObParameter} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenant/{name}/parameters [get] +// @ID getTenantParameters +// @Summary get tenant parameters +// @Description get tenant parameters +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param filter query string false "filter format" +// @Success 200 object http.OcsAgentResponse{data=[]oceanbase.GvObParameter} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/parameters [get] func getTenantParameters(c *gin.Context) { name, err := tenantCheckWithName(c) if err != nil { @@ -514,19 +573,20 @@ func getTenantParameters(c *gin.Context) { common.SendResponse(c, parameters, err) } -// @ID getTenantVariable -// @Summary get tenant variable -// @Description get tenant variable -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param var path string true "variable name" -// @Success 200 object http.OcsAgentResponse{data=oceanbase.CdbObSysVariable} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenant/{name}/variable/{var} [get] +// @ID getTenantVariable +// @Summary get tenant variable +// @Description get tenant variable +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param var path string true "variable name" +// @Success 200 object http.OcsAgentResponse{data=oceanbase.CdbObSysVariable} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/variable/{var} [get] func getTenantVariable(c *gin.Context) { name, err := tenantCheckWithName(c) if err != nil { @@ -544,19 +604,20 @@ func getTenantVariable(c *gin.Context) { common.SendResponse(c, variable, err) } -// @ID getTenantVariables -// @Summary get tenant variables -// @Description get tenant variables -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param filter query string false "filter format" -// @Success 200 object http.OcsAgentResponse{data=[]oceanbase.CdbObSysVariable} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenant/{name}/variable/{} [get] +// @ID getTenantVariables +// @Summary get tenant variables +// @Description get tenant variables +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param filter query string false "filter format" +// @Success 200 object http.OcsAgentResponse{data=[]oceanbase.CdbObSysVariable} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/variables [get] func getTenantVariables(c *gin.Context) { name, err := tenantCheckWithName(c) if err != nil { @@ -568,22 +629,609 @@ func getTenantVariables(c *gin.Context) { common.SendResponse(c, variables, err) } -// @ID getTenantOverView -// @Summary get tenant overview -// @Description get tenant overview -// @Tags tenant -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Success 200 object http.OcsAgentResponse{data=[]oceanbase.DbaObTenant} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/tenants/overview [get] +// @ID getTenantOverView +// @Summary get tenant overview +// @Description get tenant overview +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param mode query string false "tenant compitable mode: MYSQL or ORACLE" +// @Success 200 object http.OcsAgentResponse{data=[]oceanbase.DbaObTenant} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenants/overview [get] func getTenantOverView(c *gin.Context) { if !meta.OCS_AGENT.IsClusterAgent() { common.SendResponse(c, nil, errors.Occurf(errors.ErrKnown, "%s is not cluster agent.", meta.OCS_AGENT.String())) } - tenants, err := tenant.GetTenantsOverView() + mode := c.Query("mode") + tenants, err := tenant.GetTenantsOverView(mode) common.SendResponse(c, tenants, err) } + +// @ID createUser +// @Summary create user +// @Description create user +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param body body param.CreateUserParam true "create user params" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/user [post] +func createUserHandler(c *gin.Context) { + name, err := tenantCheckWithName(c) + if err != nil { + common.SendResponse(c, nil, err) + return + } + var param param.CreateUserParam + if err := c.BindJSON(¶m); err != nil { + common.SendResponse(c, nil, err) + return + } + common.SendResponse(c, nil, tenant.CreateUser(name, ¶m)) +} + +// @ID dropUser +// @Summary drop user +// @Description drop user +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param user path string true "user name" +// @Param body body param.DropUserParam true "drop user params" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/user/{user} [delete] +func dropUserHandler(c *gin.Context) { + name, err := tenantCheckWithName(c) + if err != nil { + common.SendResponse(c, nil, err) + return + } + user := c.Param(constant.URI_PARAM_USER) + if user == "" { + common.SendResponse(c, nil, errors.Occur(errors.ErrIllegalArgument, "User name is empty.")) + return + } + + var param param.DropUserParam + if err := c.BindJSON(¶m); err != nil { + common.SendResponse(c, nil, err) + return + } + + common.SendResponse(c, nil, tenant.DropUser(name, user, ¶m)) +} + +// @ID listUsers +// @Summary list users +// @Description list users from a tenant +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Success 200 object http.OcsAgentResponse{data=[]bo.ObUser} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/user [GET] +func listUsers(c *gin.Context) { + var param param.TenantRootPasswordParam + if err := c.BindJSON(¶m); err != nil { + common.SendResponse(c, nil, err) + return + } + name := c.Param(constant.URI_PARAM_NAME) + obusers, err := tenant.ListUsers(name, param.RootPassword) + common.SendResponse(c, obusers, err) +} + +// @ID getUser +// @Summary get user +// @Description get user from a tenant +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param user path string true "user name" +// @Success 200 object http.OcsAgentResponse{data=bo.ObUser} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/user/{user} [GET] +func getUser(c *gin.Context) { + var param param.TenantRootPasswordParam + if err := c.BindJSON(¶m); err != nil { + common.SendResponse(c, nil, err) + return + } + name := c.Param(constant.URI_PARAM_NAME) + user := c.Param(constant.URI_PARAM_USER) + obuser, err := tenant.GetUser(name, user, param.RootPassword) + common.SendResponse(c, obuser, err) +} + +// @ID modifyDbPrivilege +// @Summary modify db privilege of a user +// @Description modify db privilege of a user +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param user path string true "user name" +// @Param body body param.ModifyUserDbPrivilegeParam true "modify db privilege param" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/user/{user}/db-privilege [PUT] +func modifyDbPrivilege(c *gin.Context) { + name := c.Param(constant.URI_PARAM_NAME) + user := c.Param(constant.URI_PARAM_USER) + modifyUserDbPrivilegeParam := param.ModifyUserDbPrivilegeParam{} + err := c.BindJSON(&modifyUserDbPrivilegeParam) + if err != nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrIllegalArgument, "Modify user db privilege param parse failed")) + return + } + err = tenant.ModifyUserDbPrivilege(name, user, &modifyUserDbPrivilegeParam) + common.SendResponse(c, nil, err) +} + +// @ID getStats +// @Summary get user stats +// @Description get user stats +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param user path string true "user name" +// @Success 200 object http.OcsAgentResponse{data=bo.ObUserStats} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/user/{user}/stats [GET] +func getUserStats(c *gin.Context) { + var param param.TenantRootPasswordParam + if err := c.BindJSON(¶m); err != nil { + common.SendResponse(c, nil, err) + return + } + name := c.Param(constant.URI_PARAM_NAME) + user := c.Param(constant.URI_PARAM_USER) + userStats, err := tenant.GetUserStats(name, user, param.RootPassword) + common.SendResponse(c, userStats, err) +} + +// @ID tenantPreCheck +// @Summary check tenant accessibility +// @Description check tenant accessibility +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Success 200 object http.OcsAgentResponse{data=bo.ObTenantPreCheckResult} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/precheck [GET] +func tenantPrecheck(c *gin.Context) { + name := c.Param(constant.URI_PARAM_NAME) + if name == "" { + common.SendResponse(c, nil, errors.Occur(errors.ErrIllegalArgument, "Tenant name is empty.")) + return + } + var param param.TenantRootPasswordParam + if err := c.BindJSON(¶m); err != nil { + common.SendResponse(c, nil, err) + return + } + preCheckResult, err := tenant.TenantPreCheck(name, param.RootPassword) + common.SendResponse(c, preCheckResult, err) +} + +// @ID modifyGlobalPrivilege +// @Summary modify global privilege of a user +// @Description modify global privilege of a user +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param user path string true "user name" +// @Param body body param.ModifyUserGlobalPrivilegeParam true "modify global privilege param" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/user/{user}/global-privilege [PUT] +func modifyGlobalPrivilege(c *gin.Context) { + name := c.Param(constant.URI_PARAM_NAME) + user := c.Param(constant.URI_PARAM_USER) + modifyUserGlobalPrivilegeParam := param.ModifyUserGlobalPrivilegeParam{} + err := c.BindJSON(&modifyUserGlobalPrivilegeParam) + if err != nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrIllegalArgument, "Modify user global privilege param parse failed")) + return + } + err = tenant.ModifyUserGlobalPrivilege(name, user, &modifyUserGlobalPrivilegeParam) + common.SendResponse(c, nil, err) +} + +// @ID changePassword +// @Summary change user password +// @Description change user password +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param user path string true "user name" +// @Param body body param.ChangeUserPasswordParam true "change password param" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/user/{user}/password [PUT] +func changePassword(c *gin.Context) { + name := c.Param(constant.URI_PARAM_NAME) + user := c.Param(constant.URI_PARAM_USER) + changeUserPasswordParam := param.ChangeUserPasswordParam{} + err := c.BindJSON(&changeUserPasswordParam) + if err != nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrIllegalArgument, "Change user password param parse failed")) + return + } + err = tenant.ChangeUserPassword(name, user, &changeUserPasswordParam) + common.SendResponse(c, nil, err) +} + +// @ID lockUser +// @Summary lock user +// @Description lock user +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param user path string true "user name" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/user/{user}/lock [PUT] +func lockUser(c *gin.Context) { + var param param.TenantRootPasswordParam + if err := c.BindJSON(¶m); err != nil { + common.SendResponse(c, nil, err) + return + } + name := c.Param(constant.URI_PARAM_NAME) + user := c.Param(constant.URI_PARAM_USER) + err := tenant.LockUser(name, user, param.RootPassword) + common.SendResponse(c, nil, err) +} + +// @ID unlockUser +// @Summary unlock user +// @Description unlock user +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param user path string true "user name" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/user/{user}/lock [DELETE] +func unlockUser(c *gin.Context) { + name := c.Param(constant.URI_PARAM_NAME) + user := c.Param(constant.URI_PARAM_USER) + var param param.TenantRootPasswordParam + if err := c.BindJSON(¶m); err != nil { + common.SendResponse(c, nil, err) + return + } + err := tenant.UnlockUser(name, user, param.RootPassword) + common.SendResponse(c, nil, err) +} + +// @ID listDatabases +// @Summary list databases +// @Description list databases from a tenant +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Success 200 object http.OcsAgentResponse{data=[]bo.Database} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/databases [GET] +func listDatabases(c *gin.Context) { + name := c.Param(constant.URI_PARAM_NAME) + var param param.TenantRootPasswordParam + if err := c.BindJSON(¶m); err != nil { + common.SendResponse(c, nil, err) + return + } + databases, err := tenant.ListDatabases(name, param.RootPassword) + common.SendResponse(c, databases, err) +} + +// @ID getDatabase +// @Summary get database +// @Description get database from a tenant +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param database path string true "database name" +// @Success 200 object http.OcsAgentResponse{data=bo.Database} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/databases/{database} [GET] +func getDatabase(c *gin.Context) { + name := c.Param(constant.URI_PARAM_NAME) + databaseName := c.Param(constant.URI_PARAM_DATABASE) + var param param.TenantRootPasswordParam + if err := c.BindJSON(¶m); err != nil { + common.SendResponse(c, nil, err) + return + } + database, err := tenant.GetDatabase(name, databaseName, param.RootPassword) + common.SendResponse(c, database, err) +} + +// @ID deleteDatabase +// @Summary delete database +// @Description delete database +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param database path string true "database name" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/databases/{database} [DELETE] +func deleteDatabase(c *gin.Context) { + name := c.Param(constant.URI_PARAM_NAME) + databaseName := c.Param(constant.URI_PARAM_DATABASE) + var param param.TenantRootPasswordParam + if err := c.BindJSON(¶m); err != nil { + common.SendResponse(c, nil, err) + return + } + err := tenant.DeleteDatabase(name, databaseName, param.RootPassword) + common.SendResponse(c, nil, err) +} + +// @ID updateDatabase +// @Summary update database +// @Description update database +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param database path string true "database name" +// @Param body body param.ModifyDatabaseParam true "modify database param" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/databases/{database} [PUT] +func updateDatabase(c *gin.Context) { + name := c.Param(constant.URI_PARAM_NAME) + databaseName := c.Param(constant.URI_PARAM_DATABASE) + modifyDatabaseParam := param.ModifyDatabaseParam{} + err := c.BindJSON(&modifyDatabaseParam) + if err != nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrIllegalArgument, "Modify database param parse failed")) + return + } + err = tenant.AlterDatabase(name, databaseName, &modifyDatabaseParam) + common.SendResponse(c, nil, err) +} + +// @ID createDatabase +// @Summary create database +// @Description create database +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param name path string true "tenant name" +// @Param body body param.CreateDatabaseParam true "create database param" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/databases [POST] +func createDatabase(c *gin.Context) { + name := c.Param(constant.URI_PARAM_NAME) + createDatabaseParam := param.CreateDatabaseParam{} + err := c.BindJSON(&createDatabaseParam) + if err != nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrIllegalArgument, "Create database param parse failed")) + return + } + err = tenant.CreateDatabase(name, &createDatabaseParam) + common.SendResponse(c, nil, err) +} + +// @ID getTenantCompaction +// @Summary get tenant major compaction info +// @Description get tenant major compaction info +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse{data=bo.TenantCompaction} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/compaction [get] +func getTenantCompactionHandler(c *gin.Context) { + name, err := tenantCheckWithName(c) + if err != nil { + common.SendResponse(c, nil, err) + return + } + compaction, err := tenant.GetTenantCompaction(name) + common.SendResponse(c, compaction, err) +} + +// @ID tenantMajorCompaction +// @Summary trigger tenant major compaction +// @Description trigger tenant major compaction +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/compact [post] +func tenantMajorCompactionHandler(c *gin.Context) { + name, err := tenantCheckWithName(c) + if err != nil { + common.SendResponse(c, nil, err) + return + } + common.SendResponse(c, nil, tenant.TenantMajorCompaction(name)) +} + +// @ID tenantClearCompactionError +// @Summary clear tenant major compaction error +// @Description clear tenant major compaction error +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/{name}/compaction-error [delete] +func clearTenantCompactionErrorHandler(c *gin.Context) { + name, err := tenantCheckWithName(c) + if err != nil { + common.SendResponse(c, nil, err) + return + } + common.SendResponse(c, nil, tenant.ClearTenantCompactionError(name)) +} + +// @ID getTenantTopCompaction +// @Summary query tenant information ranked by the cost of major compaction. +// @Description query tenant information ranked by the cost of major compaction, limited to the top n. +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param limit query string false "top n" +// @Success 200 object http.OcsAgentResponse{data=[]bo.TenantCompactionHistory} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/top-compactions [get] +func getTenantTopCompactionsHandler(c *gin.Context) { + topStr := c.Query("limit") + top := 3 + if topStr != "" && topStr != "0" { + parsedTop, err := strconv.Atoi(topStr) + if err != nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrIllegalArgument, "Invalid top value.")) + return + } + top = parsedTop + } + + compaction, err := tenant.GetTopCompactions(top) + common.SendResponse(c, compaction, err) +} + +// @ID getTenantTopSlowSqlRank +// @Summary query tenant information ranked by the number of slow SQL statements. +// @Description query tenant information ranked by the number of slow SQL statements, limited to the top n. +// @Tags tenant +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param start_time query string true "start time" +// @Param end_time query string true "end time" +// @Param limit query string false "top n" +// @Success 200 object http.OcsAgentResponse{data=[]bo.TenantSlowSqlCount} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/tenant/top-slow-sqls [get] +func getTenantTopSlowSqlRankHandler(c *gin.Context) { + // Require the SQL processing end time to be between start_time and end_time. + start_time := c.Query("start_time") + end_time := c.Query("end_time") + top := c.Query("limit") + var param param.QuerySlowSqlRankParam + if top == "" { + param.Top = 3 + } else { + parsedTop, err := strconv.Atoi(top) + if err != nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrIllegalArgument, "Invalid top value.")) + return + } + param.Top = parsedTop + } + if start_time != "" { + parsedTime, err := time.Parse(time.RFC3339, start_time) + if err != nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrIllegalArgument, "Invalid start_time.")) + return + } + param.StartTime = parsedTime + } else { + common.SendResponse(c, nil, errors.Occur(errors.ErrIllegalArgument, "start_time is required.")) + return + } + if end_time != "" { + parsedTime, err := time.Parse(time.RFC3339, end_time) + if err != nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrIllegalArgument, "Invalid end_time.")) + return + } + param.EndTime = parsedTime + } else { + common.SendResponse(c, nil, errors.Occur(errors.ErrIllegalArgument, "end_time is required.")) + return + } + + res, err := tenantService.GetSlowSqlRank(param.Top, param.StartTime.UnixMicro(), param.EndTime.UnixMicro()) + common.SendResponse(c, res, err) +} diff --git a/agent/api/tenant_utils.go b/agent/api/tenant_utils.go new file mode 100644 index 00000000..e0c49757 --- /dev/null +++ b/agent/api/tenant_utils.go @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package api + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + + log "github.com/sirupsen/logrus" + + "github.com/gin-gonic/gin" + "github.com/oceanbase/obshell/agent/api/common" + "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/meta" + tenantservice "github.com/oceanbase/obshell/agent/service/tenant" + "github.com/oceanbase/obshell/param" +) + +// Reentrant +func getRootPasswordFromBody(c *gin.Context) (*param.TenantRootPasswordParam, error) { + bodyBytes, err := io.ReadAll(c.Request.Body) + if err != nil { + return nil, errors.Errorf("read request body failed: %s", err.Error()) + } + bodyInterface := make(map[string]interface{}) + c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) + + if err := json.Unmarshal(bodyBytes, &bodyInterface); err != nil { + return nil, errors.Errorf("unmarshal request body failed: %s", err.Error()) + } + + var param param.TenantRootPasswordParam + if password, ok := bodyInterface["root_password"]; ok { + passwordStr := fmt.Sprintf("%v", password) + param.RootPassword = &passwordStr + } else { + param.RootPassword = nil + } + + return ¶m, nil +} + +// Non-reentrant +func getBodyFromContext(c *gin.Context) (map[string]interface{}, error) { + bodyBytes, err := io.ReadAll(c.Request.Body) + if err != nil { + return nil, errors.Errorf("read request body failed: %s", err.Error()) + } + bodyInterface := make(map[string]interface{}) + if err := json.Unmarshal(bodyBytes, &bodyInterface); err != nil { + return nil, errors.Errorf("unmarshal request body failed: %s", err.Error()) + } + return bodyInterface, nil +} + +func tenantHandlerWrapper(f func(*gin.Context)) func(*gin.Context) { + return func(c *gin.Context) { + // prev check + err := checkClusterAgent() + if err != nil { + common.SendResponse(c, nil, err) + return + } + tenantName := c.Param(constant.URI_PARAM_NAME) + if tenantName == "" { + common.SendResponse(c, nil, errors.Occur(errors.ErrBadRequest, "tenant name is empty")) + return + } + if exist, err := tenantService.IsTenantExist(tenantName); err != nil { + common.SendResponse(c, nil, errors.Occurf(errors.ErrUnexpected, "check tenant '%s' exist failed", tenantName)) + return + } else if !exist { + common.SendResponse(c, nil, errors.Occurf(errors.ErrBadRequest, "Tenant '%s' not exists.", tenantName)) + return + } + + isLocked, err := tenantService.IsTenantLocked(tenantName) + if err != nil { + common.SendResponse(c, nil, errors.Occurf(errors.ErrUnexpected, "check tenant '%s' locked failed", tenantName)) + return + } + if isLocked { + common.SendResponse(c, nil, errors.Occur(errors.ErrKnown, "Tenant has been locked.")) + return + } + + if tenantName == constant.TENANT_SYS { + f(c) + return + } + + param, err := getRootPasswordFromBody(c) + if err != nil { + common.SendResponse(c, nil, err) + return + } + + if param.RootPassword != nil { + // attention: please ensure that the body of all API requests forwarded to the execute agent always contains the "password" field; otherwise, it may cause an infinite loop. + ForwardToActiveAgentWrapper(f)(c) + } else { + common.AutoForwardToMaintainerWrapper(ForwardToActiveAgentWrapper(f))(c) + } + } +} + +func resetTenantRootPassword(c *gin.Context, password *string) error { + body, err := getBodyFromContext(c) + if err != nil { + return err + } + body["root_password"] = password + modifiedBodyBytes, err := json.Marshal(body) + if err != nil { + return err + } + c.Request.Body = io.NopCloser(bytes.NewBuffer(modifiedBodyBytes)) + return nil +} + +func ForwardToActiveAgentWrapper(f func(*gin.Context)) func(*gin.Context) { + return func(c *gin.Context) { + tenantName := c.Param(constant.URI_PARAM_NAME) + param, err := getRootPasswordFromBody(c) + if err != nil { + common.SendResponse(c, nil, err) + return + } + if param.RootPassword == nil { + // Only maintainers will execute this logic. + passwordMap := tenantservice.GetPasswordMap() + password, _ := passwordMap.Get(tenantName) + param.RootPassword = &password + if err := resetTenantRootPassword(c, param.RootPassword); err != nil { + log.WithContext(c).Errorf("reset tenant root password failed: %s", err.Error()) + common.SendResponse(c, nil, err) + return + } + } + + executeAgent, err := GetExecuteAgentForTenant(tenantName) + if err != nil { + common.SendResponse(c, nil, errors.Occurf(errors.ErrUnexpected, "get execute agent failed: %s", err.Error())) + return + } + if meta.OCS_AGENT.Equal(executeAgent) { + f(c) + } else { + bodyInterface, err := getBodyFromContext(c) + if err != nil { + log.WithContext(c).Errorf("get body from context failed: %s", err.Error()) + common.SendResponse(c, nil, err) + return + } + common.ForwardRequest(c, executeAgent, bodyInterface) + } + } +} + +func GetExecuteAgentForTenant(tenantName string) (meta.AgentInfoInterface, error) { + isTenantOn, err := tenantService.IsTenantActiveAgent(tenantName, meta.OCS_AGENT.GetIp(), meta.RPC_PORT) + if err != nil { + return nil, err + } + if isTenantOn { + return meta.OCS_AGENT, nil + } + executeAgent, err := tenantService.GetTenantActiveAgent(tenantName) + if err != nil { + return nil, err + } + if executeAgent == nil { + return executeAgent, errors.New("tenant is not active") + } + return executeAgent, err +} + +func tenantCheckWithName(c *gin.Context) (string, error) { + name := c.Param(constant.URI_PARAM_NAME) + if name == "" { + return "", errors.Occur(errors.ErrIllegalArgument, "Tenant name is empty.") + } + if !meta.OCS_AGENT.IsClusterAgent() { + return "", errors.Occurf(errors.ErrKnown, "%s is not cluster agent.", meta.OCS_AGENT.String()) + } + return name, nil +} diff --git a/agent/api/unit_handler.go b/agent/api/unit_handler.go index e0c29874..ae45fdbb 100644 --- a/agent/api/unit_handler.go +++ b/agent/api/unit_handler.go @@ -26,18 +26,18 @@ import ( "github.com/oceanbase/obshell/param" ) -// @ID unitConfigCreate -// @Summary create resource unit config -// @Description create resource unit config -// @Tags unit -// @Accept application/json -// @Produce application/json -// @Param body body param.CreateResourceUnitConfigParams true "Resource unit config" -// @Success 200 object http.OcsAgentResponse -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/unit/config [post] +// @ID unitConfigCreate +// @Summary create resource unit config +// @Description create resource unit config +// @Tags unit +// @Accept application/json +// @Produce application/json +// @Param body body param.CreateResourceUnitConfigParams true "Resource unit config" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/unit/config [post] func unitConfigCreateHandler(c *gin.Context) { var param param.CreateResourceUnitConfigParams if err := c.BindJSON(¶m); err != nil { @@ -56,18 +56,18 @@ func unitConfigCreateHandler(c *gin.Context) { common.SendResponse(c, nil, err) } -// @ID unitConfigDrop -// @Summary drop resource unit config -// @Description drop resource unit config -// @Tags unit -// @Accept application/json -// @Produce application/json -// @Param name path string true "resource unit name" -// @Success 200 object http.OcsAgentResponse -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/unit/config/{name} [delete] +// @ID unitConfigDrop +// @Summary drop resource unit config +// @Description drop resource unit config +// @Tags unit +// @Accept application/json +// @Produce application/json +// @Param name path string true "resource unit name" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/unit/config/{name} [delete] func unitConfigDropHandler(c *gin.Context) { name := c.Param(constant.URI_PARAM_NAME) if name == "" { @@ -82,18 +82,18 @@ func unitConfigDropHandler(c *gin.Context) { common.SendResponse(c, nil, err) } -// @ID unitConfigList -// @Summary get all resource unit configs -// @Description get all resource unit configs in the cluster -// @Tags unit -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Success 200 object http.OcsAgentResponse{data=[]oceanbase.DbaObUnitConfig} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/units/config [get] +// @ID unitConfigList +// @Summary get all resource unit configs +// @Description get all resource unit configs in the cluster +// @Tags unit +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse{data=[]oceanbase.DbaObUnitConfig} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/units/config [get] func unitConfigListHandler(c *gin.Context) { if !meta.OCS_AGENT.IsClusterAgent() { common.SendResponse(c, nil, errors.Occurf(errors.ErrKnown, "%s is not cluster agent.", meta.OCS_AGENT.String())) @@ -103,18 +103,18 @@ func unitConfigListHandler(c *gin.Context) { common.SendResponse(c, units, err) } -// @ID unitConfigGet -// @Summary get resource unit config -// @Description get resource unit config -// @Tags unit -// @Accept application/json -// @Produce application/json -// @Param name path string true "resource unit name" -// @Success 200 object http.OcsAgentResponse{data=oceanbase.DbaObUnitConfig} -// @Failure 400 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/unit/config/{name} [get] +// @ID unitConfigGet +// @Summary get resource unit config +// @Description get resource unit config +// @Tags unit +// @Accept application/json +// @Produce application/json +// @Param name path string true "resource unit name" +// @Success 200 object http.OcsAgentResponse{data=oceanbase.DbaObUnitConfig} +// @Failure 400 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/unit/config/{name} [get] func unitConfigGetHandler(c *gin.Context) { name := c.Param(constant.URI_PARAM_NAME) if name == "" { diff --git a/agent/api/utils.go b/agent/api/utils.go new file mode 100644 index 00000000..88837dcd --- /dev/null +++ b/agent/api/utils.go @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package api + +import ( + "github.com/gin-gonic/gin" + "github.com/oceanbase/obshell/agent/api/common" + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/meta" +) + +func checkClusterAgentWrapper(f func(*gin.Context)) func(*gin.Context) { + return func(c *gin.Context) { + err := checkClusterAgent() + if err != nil { + common.SendResponse(c, nil, err) + return + } + f(c) + } +} + +func checkClusterAgent() error { + if !meta.OCS_AGENT.IsClusterAgent() { + return errors.Occurf(errors.ErrKnown, "%s is not cluster agent.", meta.OCS_AGENT.String()) + } + return nil +} diff --git a/agent/api/web/server.go b/agent/api/web/server.go index 63f750fb..3fa8e0c4 100644 --- a/agent/api/web/server.go +++ b/agent/api/web/server.go @@ -19,8 +19,12 @@ package web import ( "context" "fmt" + "io" + "io/fs" "net" "net/http" + "path/filepath" + "strings" "time" "github.com/gin-gonic/gin" @@ -30,11 +34,13 @@ import ( "github.com/oceanbase/obshell/agent/api/common" "github.com/oceanbase/obshell/agent/config" "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/errors" "github.com/oceanbase/obshell/agent/global" http2 "github.com/oceanbase/obshell/agent/lib/http" "github.com/oceanbase/obshell/agent/lib/path" "github.com/oceanbase/obshell/agent/lib/process" "github.com/oceanbase/obshell/agent/rpc" + "github.com/oceanbase/obshell/frontend" ) type Server struct { @@ -84,9 +90,51 @@ func NewServer(mode config.AgentMode, conf config.ServerConfig) *Server { api.InitOcsAgentRoutes(ret.state, localRouter, true) rpc.InitOcsAgentRpcRoutes(ret.state, router, false) rpc.InitOcsAgentRpcRoutes(ret.state, localRouter, true) + router.NoRoute(func(c *gin.Context) { + requestedPath := c.Request.URL.Path + if strings.Contains(requestedPath, constant.URI_API_V1) || strings.Contains(requestedPath, constant.URI_RPC_V1) { + common.SendResponse(c, nil, errors.Occur(errors.ErrBadRequest, "404 not found")) + return + } + + staticFp, err := fs.Sub(frontend.Dist, "dist") + if err != nil { + log.WithError(err).Fatal("Failed to access static filesystem") + return + } + if requestedPath == "/" || strings.TrimSpace(requestedPath) == "" { + writeIndexlHtml(c) + return + } + _, err = staticFp.Open(filepath.Clean(strings.TrimPrefix(requestedPath, "/"))) + if err != nil { + writeIndexlHtml(c) + return + } + http.FileServer(http.FS(staticFp)).ServeHTTP(c.Writer, c.Request) + }) return ret } +func writeIndexlHtml(c *gin.Context) { + staticFp, _ := fs.Sub(frontend.Dist, "dist") + content, err := staticFp.Open("index.html") + if err != nil { + log.Fatalf("Critical error: %s file not found in the static file system!", "index.html") + } + + fileContent, err := io.ReadAll(content) + if err != nil { + log.Printf("Failed to read index.html content: %v", err) + c.String(http.StatusInternalServerError, "Failed to load index.html") + return + } + + c.Writer.Header().Set("Content-Type", "text/html; charset=utf-8") + c.Writer.WriteHeader(http.StatusOK) + c.Writer.Write(fileContent) +} + // NewServerOnlyLocal initializes gin mode, register api and rpc routers for // local router engine instances, and returns a new server instance. func NewServerOnlyLocal(mode config.AgentMode, conf config.ServerConfig) *Server { diff --git a/agent/api/zone_handler.go b/agent/api/zone_handler.go index 7852884a..63d36499 100644 --- a/agent/api/zone_handler.go +++ b/agent/api/zone_handler.go @@ -25,20 +25,20 @@ import ( "github.com/oceanbase/obshell/agent/meta" ) -// @ID DeleteZone +//@ID DeleteZone // -// @Summary delete zone -// @Description delete zone -// @Tags ob -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param zoneName path string true "zone name" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Success 204 object http.OcsAgentResponse -// @Failure 401 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/zone/{zoneName} [delete] +// @Summary delete zone +// @Description delete zone +// @Tags ob +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param zoneName path string true "zone name" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Success 204 object http.OcsAgentResponse +// @Failure 401 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/zone/{zoneName} [delete] func zoneDeleteHandler(c *gin.Context) { zoneName := c.Param(constant.URI_PARAM_NAME) if zoneName == "" { diff --git a/agent/assets/i18n/error/en.json b/agent/assets/i18n/error/en.json index 1cbbb92d..57126ed6 100644 --- a/agent/assets/i18n/error/en.json +++ b/agent/assets/i18n/error/en.json @@ -3,6 +3,7 @@ "err.illegal.argument": "Illegal argument: %v", "err.unexpected": "Unexpected error: %v", "err.known": "Known error: %v", + "err.not.found": "Element not found: %v", "err.sql.execute.failed": "Execute sql failed: %v", "err.task.create.failed": "Create task failed: %v", @@ -10,5 +11,5 @@ "err.obcluster.not.found": "There is no obcluster now. %v", "err.user.permission.denied": "Permission denied: %v", - "err.unauthorized": "Verification failed" + "err.unauthorized": "Verification failed: %v" } diff --git a/agent/cmd/admin/start.go b/agent/cmd/admin/start.go index c93f7146..28740a0d 100644 --- a/agent/cmd/admin/start.go +++ b/agent/cmd/admin/start.go @@ -130,8 +130,12 @@ func isDaemonRunning() (pid int32, res bool) { if err != nil { return 0, false } - if _, err = proc.NewProcess(pid); err != nil { + if pidInfo, err := proc.NewProcess(pid); err != nil { return pid, false + } else { + if name, err := pidInfo.Name(); err == nil && name != constant.PROC_OBSHELL { + return pid, false + } } return pid, true } diff --git a/agent/cmd/daemon/start_daemon.go b/agent/cmd/daemon/start_daemon.go index 11c1a047..7250b2a2 100644 --- a/agent/cmd/daemon/start_daemon.go +++ b/agent/cmd/daemon/start_daemon.go @@ -20,7 +20,6 @@ import ( "fmt" "net" "os" - "syscall" "time" log "github.com/sirupsen/logrus" @@ -123,22 +122,7 @@ func (d *Daemon) startSocket(socketListener *net.UnixListener) { func (d *Daemon) writePid() (err error) { pid := os.Getpid() log.Info("obshell daemon pid is ", pid) - return writePid(path.DaemonPidPath(), pid) -} - -// writePid writes the pid to the specified path atomically. -// If the file already exists, an error is returned. -func writePid(path string, pid int) (err error) { - f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_EXCL|os.O_SYNC|syscall.O_CLOEXEC, 0644) - if err != nil { - return err - } - defer f.Close() - _, err = fmt.Fprint(f, pid) - if err != nil { - return err - } - return nil + return process.WritePid(path.DaemonPidPath(), pid) } func (d *Daemon) isForUpgrade() bool { diff --git a/agent/cmd/daemon/start_process.go b/agent/cmd/daemon/start_process.go index d302f0f4..08d4c373 100644 --- a/agent/cmd/daemon/start_process.go +++ b/agent/cmd/daemon/start_process.go @@ -120,7 +120,7 @@ func (s *Server) startServerProc() (err error) { } func (s *Server) writePid() error { - return writePid(path.ObshellPidPath(), s.GetPid()) + return process.WritePid(path.ObshellPidPath(), s.GetPid()) } func (s *Server) handleProcExited(procState process.ProcState, count *int) (err error) { diff --git a/agent/cmd/daemon/stop_process.go b/agent/cmd/daemon/stop_process.go index 1e9c3d96..2cd01ba8 100644 --- a/agent/cmd/daemon/stop_process.go +++ b/agent/cmd/daemon/stop_process.go @@ -18,6 +18,7 @@ package daemon import ( "os" + "strconv" "time" proc "github.com/shirou/gopsutil/v3/process" @@ -64,14 +65,20 @@ func (s *Server) cleanup() { } if system.IsFileExist(path.ObshellPidPath()) { - obshellPid, err := process.GetObshellPid() + obshellPidStr, err := process.GetObshellPidStr() if err != nil { log.WithError(err).Error("failed to get obshell pid") return } + obshellPid, err := strconv.Atoi(obshellPidStr) + if err != nil { + log.Infof("unexpect obshell pid: %s, delete directly", obshellPidStr) + os.Remove(path.ObshellPidPath()) + } + log.Info("the stopped obshell pid is ", obshellPid) - if _, err = proc.NewProcess(obshellPid); err != nil { + if _, err = proc.NewProcess(int32(obshellPid)); err != nil { if system.IsFileExist(path.ObshellPidPath()) { log.Infof("remove obshell pid file %s", path.ObshellPidPath()) os.Remove(path.ObshellPidPath()) diff --git a/agent/cmd/server/init.go b/agent/cmd/server/init.go index d3aa3e5b..9249d73d 100644 --- a/agent/cmd/server/init.go +++ b/agent/cmd/server/init.go @@ -18,7 +18,7 @@ package server import ( "fmt" - "os" + "path/filepath" "syscall" "time" @@ -31,6 +31,7 @@ import ( "github.com/oceanbase/obshell/agent/errors" "github.com/oceanbase/obshell/agent/executor/agent" "github.com/oceanbase/obshell/agent/executor/ob" + "github.com/oceanbase/obshell/agent/executor/obproxy" "github.com/oceanbase/obshell/agent/executor/pool" "github.com/oceanbase/obshell/agent/executor/recyclebin" "github.com/oceanbase/obshell/agent/executor/script" @@ -98,14 +99,12 @@ func (a *Agent) initSqlite() (err error) { // initServerForUpgrade will only start the unix socket service When upgrading. func (a *Agent) initServerForUpgrade() error { log.Info("init local server [upgrade mode]") - serverConfig := config.ServerConfig{ - Ip: "0.0.0.0", - Port: meta.OCS_AGENT.GetPort(), - Address: fmt.Sprintf("0.0.0.0:%d", meta.OCS_AGENT.GetPort()), - RunDir: path.RunDir(), - UpgradeMode: true, + serverConfig, err := config.NewServerConfig(meta.OCS_AGENT.GetIp(), meta.OCS_AGENT.GetPort(), path.RunDir(), true) + if err != nil { + return err } - a.server = web.NewServerOnlyLocal(config.DebugMode, serverConfig) + + a.server = web.NewServerOnlyLocal(config.DebugMode, *serverConfig) socketListener, err := a.server.NewUnixListener() if err != nil { return err @@ -227,14 +226,12 @@ func (a *Agent) checkAgentInfo() { // initServer will only initialize the Server and will not start the service. func (a *Agent) initServer() { log.Info("init server") - serverConfig := config.ServerConfig{ - Ip: "0.0.0.0", - Port: meta.OCS_AGENT.GetPort(), - Address: fmt.Sprintf("0.0.0.0:%d", meta.OCS_AGENT.GetPort()), - RunDir: path.RunDir(), + serverConfig, err := config.NewServerConfig(meta.OCS_AGENT.GetIp(), meta.OCS_AGENT.GetPort(), path.RunDir(), false) + if err != nil { + process.ExitWithFailure(constant.EXIT_CODE_ERROR_INVAILD_AGENT, fmt.Sprintf("init server failed, err: %v", err)) } log.Infof("server config is %v", serverConfig) - a.server = web.NewServer(config.DebugMode, serverConfig) + a.server = web.NewServer(config.DebugMode, *serverConfig) a.startChan = make(chan bool, 1) } @@ -253,6 +250,7 @@ func (a *Agent) initTask() { recyclebin.RegisterRecyclebinTask() task.RegisterTaskType(script.ImportScriptForTenantTask{}) pool.RegisterPoolTask() + obproxy.RegisterTaskType() } // Check if the ob config file exists. @@ -267,12 +265,16 @@ func (a *Agent) isUpgradeMode() bool { if a.OldServerPid != 0 { // If the old agent is running in the same directory as the new agent, // it is considered an upgrade. - cwdDir, err := os.Readlink(fmt.Sprintf("/proc/%d/cwd", a.OldServerPid)) + cwdDir, err := filepath.EvalSymlinks(fmt.Sprintf("/proc/%d/cwd", a.OldServerPid)) + if err != nil { + return false + } + curDir, err := filepath.EvalSymlinks(global.HomePath) if err != nil { return false } log.Infof("the cwd of %d is %s", a.OldServerPid, cwdDir) - if global.HomePath == cwdDir { + if curDir == cwdDir { log.Info("The obshell is in upgrade mode.") a.upgradeMode = true // Unset root password env to avoid cover sqlite when upgrade (agent restart) diff --git a/agent/cmd/server/run.go b/agent/cmd/server/run.go index dc1da2c6..5315158d 100644 --- a/agent/cmd/server/run.go +++ b/agent/cmd/server/run.go @@ -79,17 +79,23 @@ func (a *Agent) restoreSecure() (err error) { log.WithError(err).Error("reinit secure failed") return err } - } else { - log.Info("restore secure info successed, check password in sqlite") - err = secure.LoadPassword(a.GetRootPassword()) - if err != nil { - log.WithError(err).Info("check password in sqlite failed") - if !meta.OCS_AGENT.IsClusterAgent() { - process.ExitWithFailure(constant.EXIT_CODE_ERROR_NOT_CLUSTER_AGENT, "check password in sqlite failed: not cluster agent") - } - } else { - log.Info("check password in sqlite successed") + } + + log.Info("restore secure info successed, check password of root@sys in sqlite") + err = secure.LoadOceanbasePassword(a.GetRootPassword()) + if err != nil { + log.WithError(err).Info("check password of root@sys in sqlite failed") + if !meta.OCS_AGENT.IsClusterAgent() { + process.ExitWithFailure(constant.EXIT_CODE_ERROR_NOT_CLUSTER_AGENT, "check password of root@sys in sqlite failed: not cluster agent") } + } else { + log.Info("check password of root@sys in sqlite successed") + } + + log.Info("check agent password from sqlite") + err = secure.LoadAgentPassword() + if err != nil { + log.WithError(err).Error("check agent password from sqlite failed") } return nil } diff --git a/agent/config/oceanbase.go b/agent/config/oceanbase.go index c92ca16d..4e25cce6 100644 --- a/agent/config/oceanbase.go +++ b/agent/config/oceanbase.go @@ -21,12 +21,13 @@ import ( "strings" "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/meta" ) func NewObDataSourceConfig() *ObDataSourceConfig { return &ObDataSourceConfig{ username: constant.DB_USERNAME, - ip: constant.LOCAL_IP, + ip: meta.OCS_AGENT.GetLocalIp(), dBName: constant.DB_OCS, charset: constant.DB_DEFAULT_CHARSET, parseTime: true, @@ -37,6 +38,19 @@ func NewObDataSourceConfig() *ObDataSourceConfig { } } +func NewObproxyDataSourceConfig() *ObDataSourceConfig { + return &ObDataSourceConfig{ + username: constant.DB_PROXYSYS_USERNAME, + ip: constant.LOCAL_IP, + charset: constant.DB_DEFAULT_CHARSET, + parseTime: true, + location: constant.DB_DEFAULT_LOCATION, + maxIdleConns: constant.DB_DEFAULT_MAX_IDLE_CONNS, + maxOpenConns: constant.DB_DEFAULT_MAX_OPEN_CONNS, + connMaxLifetime: constant.DB_DEFAULT_CONN_MAX_LIFETIME, + } +} + type ObDataSourceConfig struct { // dsn config username string @@ -182,7 +196,7 @@ func (config *ObDataSourceConfig) GetSkipPwdCheck() bool { } func (config *ObDataSourceConfig) GetDSN() string { - dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/", config.username, config.password, config.ip, config.port) + dsn := fmt.Sprintf("%s:%s@tcp(%s)/", config.username, config.password, meta.NewAgentInfo(config.ip, config.port).String()) if config.dBName != "" { dsn += config.dBName } diff --git a/agent/config/server.go b/agent/config/server.go index fc18033a..75d1d640 100644 --- a/agent/config/server.go +++ b/agent/config/server.go @@ -16,6 +16,19 @@ package config +import ( + "errors" + "fmt" + "net" + "strings" +) + +var EncryptionDisabled string = "false" + +func IsEncryptionDisabled() bool { + return strings.ToUpper(EncryptionDisabled) == "TRUE" +} + type AgentMode = string const ( @@ -30,3 +43,29 @@ type ServerConfig struct { RunDir string UpgradeMode bool } + +func NewServerConfig(ip string, port int, runDir string, UpgradeMode bool) (*ServerConfig, error) { + address, err := generateAddress(ip, port) + if err != nil { + return nil, err + } + + return &ServerConfig{ + Ip: ip, + Port: port, + Address: address, + RunDir: runDir, + UpgradeMode: UpgradeMode, + }, nil +} + +func generateAddress(ip string, port int) (string, error) { + ipParsed := net.ParseIP(ip) + if ipParsed == nil { + return "", errors.New("invalid ip") + } + if ipParsed.To4() != nil { + return fmt.Sprint("0.0.0.0:", port), nil + } + return fmt.Sprint("[::]:", port), nil +} diff --git a/agent/constant/agent.go b/agent/constant/agent.go index d578b6ab..f8bbe204 100644 --- a/agent/constant/agent.go +++ b/agent/constant/agent.go @@ -78,6 +78,8 @@ const ( PROC_OBSHELL_CLIENT = "client" PROC_OBSERVER = "observer" + + PROC_OBPROXY = "obproxy" ) // upload pkg names @@ -85,6 +87,7 @@ const ( PKG_OBSHELL = "obshell" PKG_OCEANBASE_CE = "oceanbase-ce" PKG_OCEANBASE_CE_LIBS = "oceanbase-ce-libs" + PKG_OBPROXY_CE = "obproxy-ce" ) var SUPPORT_PKG_NAMES = []string{ diff --git a/agent/constant/gorm.go b/agent/constant/gorm.go index 9ef3507a..747c7fc6 100644 --- a/agent/constant/gorm.go +++ b/agent/constant/gorm.go @@ -18,9 +18,11 @@ package constant const ( // source config default value - DB_USERNAME = "root" - LOCAL_IP = "127.0.0.1" - DB_DEFAILT_TIMEOUT = 10 + DB_USERNAME = "root" + DB_PROXYSYS_USERNAME = "root@proxysys" + LOCAL_IP = "127.0.0.1" + LOCAL_IP_V6 = "::1" + DB_DEFAULT_CHARSET = "utf8mb4" DB_DEFAULT_LOCATION = "Local" diff --git a/agent/constant/ob_parameter.go b/agent/constant/ob_parameter.go new file mode 100644 index 00000000..df27baaf --- /dev/null +++ b/agent/constant/ob_parameter.go @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package constant + +const ( + PARAMETER_ENABLE_REBALANCE = "enable_rebalance" + PARAMETER_GLOBAL_INDEX_AUTO_SPLIT_POLICY = "global_index_auto_split_policy" + PARAMETER_MIN_FULL_RESOURCE_POOL_MEMORY = "__min_full_resource_pool_memory" + + VARIABLE_TIME_ZONE = "time_zone" + VARIABLE_OB_TCP_INVITED_NODES = "ob_tcp_invited_nodes" + VARIABLE_READ_ONLY = "read_only" +) + +var ( + // READONLY variables + CREATE_TENANT_STATEMENT_VARIABLES = []string{"lower_case_table_names"} + // Those variables could not set by sys tenant. + VARIAbLES_COLLATION_OR_CHARACTER = []string{ + "collation_server", + "collation_database", + "collation_connection", + "character_set_server", + "character_set_database", + "character_set_connection", + } +) diff --git a/agent/constant/obproxy.go b/agent/constant/obproxy.go new file mode 100644 index 00000000..1bdb3741 --- /dev/null +++ b/agent/constant/obproxy.go @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package constant + +const ( + OBPROXY_INFO_SQL_PORT = "sql_port" + OBPROXY_INFO_OBPROXY_SYS_PASSWORD = "obproxy_sys_password" + OBPROXY_INFO_HOME_PATH = "home_path" + OBPROXY_INFO_PROXYRO_PASSWORD = "proxyro_password" + OBPROXY_INFO_VERSION = "version" + + OBPROXY_CONFIG_PROMETHUES_LISTEN_PORT = "prometheus_listen_port" + OBPROXY_CONFIG_RS_LIST = "rootservice_list" + OBPROXY_CONFIG_CONFIG_SERVER_URL = "obproxy_config_server_url" + OBPROXY_CONFIG_LISTEN_PORT = "listen_port" + OBPROXY_CONFIG_CLUSTER_NAME = "cluster_name" + OBPROXY_CONFIG_RPC_LISTEN_PORT = "rpc_listen_port" + OBPROXY_CONFIG_OBPROXY_SYS_PASSWORD = "obproxy_sys_password" + OBPROXY_CONFIG_ROOT_SERVICE_CLUSTER_NAME = "rootservice_cluster_name" + OBPROXY_CONFIG_PROXYRO_PASSWORD = "observer_sys_password" + OBPROXY_CONFIG_PROXY_LOCAL_CMD = "proxy_local_cmd" + OBPROXY_CONFIG_HOT_UPGRADE_ROLLBACK_TIMEOUT = "hot_upgrade_rollback_timeout" + OBPROXY_CONFIG_HOT_UPGRADE_EXIT_TIMEOUT = "hot_upgrade_exit_timeout" + + OBPROXY_MIN_VERSION_SUPPORT = "4.0.0" + + OBPROXY_INFO_STATUS = "status" + + OBPROXY_DIR_ETC = "etc" + OBPROXY_DIR_BIN = "bin" + OBPROXY_DIR_LIB = "lib" + OBPROXY_DIR_LOG = "log" + OBPROXY_DIR_RUN = "run" + BIN_OBPROXY = "obproxy" + BIN_OBPROXYD = "obproxyd" + + RESTART_FOR_PROXY_LOCAL_CMD = "2" + + OBPROXY_DEFAULT_SQL_PORT = 2883 + OBPROXY_DEFAULT_EXPORTER_PORT = 2884 + OBPROXY_DEFAULT_RPC_PORT = 2885 + + DEFAULT_HOT_RESTART_TIME_OUT = 1800 // 30 minutes +) diff --git a/agent/constant/oceanbase.go b/agent/constant/oceanbase.go index 3368d057..d047b53f 100644 --- a/agent/constant/oceanbase.go +++ b/agent/constant/oceanbase.go @@ -24,22 +24,56 @@ var OB_CONFIG_COMPATIBLE_MAP = map[string]string{ CONFIG_MYSQL_PORT: "mysqlPort", } +var OB_INNER_USERS = []string{"PUBLIC", "LBACSYS", "ORAAUDITOR", "__oceanbase_inner_standby_user", "ocp_monitor"} +var OB_NO_PRIVILEGE_DBS = []string{"information_schema"} +var OB_RESTRICTED_DBS = []string{"oceanbase", "mysql", "SYS", "LBACSYS", "ORAAUDITOR"} + +const ( + OB_MYSQL_PRIVILEGE_ALTER = "ALTER" + OB_MYSQL_PRIVILEGE_CREATE = "CREATE" + OB_MYSQL_PRIVILEGE_DELETE = "DELETE" + OB_MYSQL_PRIVILEGE_DROP = "DROP" + OB_MYSQL_PRIVILEGE_INSERT = "INSERT" + OB_MYSQL_PRIVILEGE_SELECT = "SELECT" + OB_MYSQL_PRIVILEGE_UPDATE = "UPDATE" + OB_MYSQL_PRIVILEGE_INDEX = "INDEX" + OB_MYSQL_PRIVILEGE_CREATE_VIEW = "CREATE_VIEW" + OB_MYSQL_PRIVILEGE_SHOW_VIEW = "SHOW_VIEW" + OB_MYSQL_PRIVILEGE_CREATE_USER = "CREATE_USER" + OB_MYSQL_PRIVILEGE_PROCESS = "PROCESS" + OB_MYSQL_PRIVILEGE_SUPER = "SUPER" + OB_MYSQL_PRIVILEGE_SHOW_DATABASES = "SHOW_DATABASES" + OB_MYSQL_PRIVILEGE_GRANT_OPTION = "GRANT_OPTION" +) + +const ( + OB_CONNECTION_TYPE_DIRECT = "DIRECT" + OB_CONNECTION_TYPE_PROXY = "PROXY" +) + +var OB_MYSQL_PRIVILEGES = []string{OB_MYSQL_PRIVILEGE_ALTER, OB_MYSQL_PRIVILEGE_CREATE, OB_MYSQL_PRIVILEGE_DELETE, OB_MYSQL_PRIVILEGE_DROP, OB_MYSQL_PRIVILEGE_INSERT, OB_MYSQL_PRIVILEGE_INDEX, OB_MYSQL_PRIVILEGE_SELECT, OB_MYSQL_PRIVILEGE_UPDATE, OB_MYSQL_PRIVILEGE_CREATE_VIEW, OB_MYSQL_PRIVILEGE_SHOW_VIEW, OB_MYSQL_PRIVILEGE_CREATE_USER, OB_MYSQL_PRIVILEGE_PROCESS, OB_MYSQL_PRIVILEGE_SUPER, OB_MYSQL_PRIVILEGE_SHOW_DATABASES, OB_MYSQL_PRIVILEGE_GRANT_OPTION} + const ( DB_OCEANBASE = "oceanbase" DB_OCS = "ocs" + DEFAULT_HOST = "%" + + SYS_USER_PROXYRO = "proxyro" + CONFIG_RPC_PORT = "rpc_port" CONFIG_MYSQL_PORT = "mysql_port" DEFAULT_MYSQL_PORT = 2881 DEFAULT_RPC_PORT = 2882 - CONFIG_HOME_PATH = "homePath" - CONFIG_ROOT_PWD = "rootPwd" - CONFIG_DATA_DIR = "data_dir" - CONFIG_REDO_DIR = "redo_dir" - CONFIG_CLOG_DIR = "clog_dir" - CONFIG_SLOG_DIR = "slog_dir" + CONFIG_HOME_PATH = "homePath" + CONFIG_ROOT_PWD = "rootPwd" + CONFIG_AGENT_PASSWORD = "agentRootPwd" + CONFIG_DATA_DIR = "data_dir" + CONFIG_REDO_DIR = "redo_dir" + CONFIG_CLOG_DIR = "clog_dir" + CONFIG_SLOG_DIR = "slog_dir" CONFIG_LOCAL_IP = "local_ip" CONFIG_DEV_NAME = "devname" diff --git a/agent/constant/secure.go b/agent/constant/secure.go index 596622c1..a376170b 100644 --- a/agent/constant/secure.go +++ b/agent/constant/secure.go @@ -20,6 +20,7 @@ import "time" const ( OCS_HEADER = "X-OCS-Header" + OCS_AGENT_HEADER = "X-OCS-Agent-Header" REQUEST_RECEIVED_TIME = "request_received_time" RESPONSE_PWD_KEY = "password" AGENT_PRIVATE_KEY = "private_key" diff --git a/agent/constant/task.go b/agent/constant/task.go index 00378a9e..98c1c5f0 100644 --- a/agent/constant/task.go +++ b/agent/constant/task.go @@ -25,10 +25,12 @@ const ( ) const ( - CLUSTER_TASK_ID_PREFIX = '1' - LOCAL_TASK_IPV4_ID_PREFIX = '2' - LOCAL_TASK_IPV6_ID_PREFIX = '3' - ENGINE_WAIT_TIME = 30 * time.Second + CLUSTER_TASK_ID_PREFIX = '1' + LOCAL_TASK_IPV4_ID_PREFIX = '2' + LOCAL_TASK_IPV6_ID_PREFIX = '3' + OBPROXY_TASK_IPV4_ID_PREFIX = '4' + OBPROXY_TASK_IPV6_ID_PREFIX = '5' + ENGINE_WAIT_TIME = 30 * time.Second SYNC_INTERVAL = 1 * time.Second SYNC_TASK_BUFFER_SIZE = 10000 diff --git a/agent/constant/tenant.go b/agent/constant/tenant.go index 58d615e0..c3bebff3 100644 --- a/agent/constant/tenant.go +++ b/agent/constant/tenant.go @@ -46,11 +46,7 @@ const ( CHECK_JOB_INTERVAL = 10 * time.Second CHECK_TENANT_EXIST_INTERVAL = 5 * time.Second RESOURCE_UNIT_CONFIG_CPU_MINE = 1 - - VARIABLE_TIME_ZONE = "time_zone" - VARIABLE_OB_TCP_INVITED_NODES = "ob_tcp_invited_nodes" - - PARAMETER_ENABLE_REBALANCE = "enable_rebalance" + SLOW_SQL_THRESHOLD = 100000 ALTER_RESOURCE_TENANT_UNIT_NUM = "ALTER_RESOURCE_TENANT_UNIT_NUM" ALTER_TENANT_LOCALITY = "ALTER_TENANT_LOCALITY" diff --git a/agent/constant/uri.go b/agent/constant/uri.go index 9e81baea..abfb50d8 100644 --- a/agent/constant/uri.go +++ b/agent/constant/uri.go @@ -34,6 +34,7 @@ const ( URI_POOL_GROUP = "/resource-pool" URI_POOLS_GROUP = "/resource-pools" URI_RECYCLEBIN_GROUP = "/recyclebin" + URI_OBPROXY_GROUP = "/obproxy" URI_INFO = "/info" URI_TIME = "/time" @@ -41,18 +42,23 @@ const ( URI_STATUS = "/status" URI_SECRET = "secret" - URI_JOIN = "/join" - URI_REMOVE = "/remove" + URI_JOIN = "/join" + URI_REMOVE = "/remove" + URI_PASSWORD = "/password" + URI_TOKEN = "/token" URI_SYNC_BIN = "/sync-bin" URI_DAG = "/dag" + URI_DAGS = "/dags" URI_NODE = "/node" URI_SUB_TASK = "/sub_task" URI_LOG = "/log" + URI_LOGS = "/logs" URI_MAINTAIN = "/maintain" URI_UNFINISH = "/unfinish" URI_MAINTAINER = "/maintainer" + URI_MAIN_DAGS = "/main_dags" // OB api URI_CONFIG = "/config" @@ -66,10 +72,12 @@ const ( URI_SCALE_OUT = "/scale_out" URI_SCALE_IN = "/scale_in" URI_AGENTS = "/agents" + URI_CHARSETS = "/charsets" // Used for upgrade URI_UPGRADE = "/upgrade" URI_CHECK = "/check" + URI_ROUTE = "/route" URI_PACKAGE = "/package" URI_PARAMS = "/params" URI_BACKUP = "/backup" @@ -77,26 +85,44 @@ const ( URI_WINDOWS = "/windows" // Used for tenant - URI_TENANTS = "/tenants" - URI_LOCK = "/lock" - URI_NAME = "/name" - URI_REPLICAS = "/replicas" - URI_PRIMARYZONE = "/primary-zone" - URI_ROOTPASSWORD = "/password" - URI_WHITELIST = "/whitelist" - URI_PARAMETERS = "/parameters" - URI_VARIABLES = "/variables" - URI_VARIABLE = "/variable" - URI_PARAMETER = "/parameter" - URI_OVERVIEW = "/overview" - URI_TENANT = "/tenant" - - URI_PARAM_NAME = "name" - URI_PATH_PARAM_NAME = "/:" + URI_PARAM_NAME - URI_PARAM_VAR = "variable" - URI_PATH_PARAM_VAR = "/:" + URI_PARAM_VAR - URI_PARAM_PARA = "parameter" - URI_PATH_PARAM_PARA = "/:" + URI_PARAM_PARA + URI_TENANTS = "/tenants" + URI_LOCK = "/lock" + URI_NAME = "/name" + URI_REPLICAS = "/replicas" + URI_PRIMARYZONE = "/primary-zone" + URI_ROOTPASSWORD = "/password" + URI_WHITELIST = "/whitelist" + URI_PARAMETERS = "/parameters" + URI_VARIABLES = "/variables" + URI_VARIABLE = "/variable" + URI_PARAMETER = "/parameter" + URI_OVERVIEW = "/overview" + URI_TENANT = "/tenant" + URI_USER = "/user" + URI_COMPACT = "/compact" + URI_COMPACTION = "/compaction" + URI_COMPACTION_ERROR = "/compaction-error" + URI_TOP_COMPACTIONS = "/top-compactions" + URI_TOP_SLOW_SQLS = "/top-slow-sqls" + URI_DATABASES = "/databases" + URI_DB_PRIVILEGE = "/db-privilege" + URI_GLOBAL_PRIVILEGE = "/global-privilege" + URI_PERSIST = "/persist" + URI_STATS = "/stats" + URI_PRECHECK = "/precheck" + + URI_UNIT_CONFIG_LIMIT = "/unit-config-limit" + + URI_PARAM_NAME = "name" + URI_PATH_PARAM_NAME = "/:" + URI_PARAM_NAME + URI_PARAM_VAR = "variable" + URI_PATH_PARAM_VAR = "/:" + URI_PARAM_VAR + URI_PARAM_PARA = "parameter" + URI_PATH_PARAM_PARA = "/:" + URI_PARAM_PARA + URI_PARAM_USER = "user" + URI_PATH_PARAM_USER = "/:" + URI_PARAM_USER + URI_PARAM_DATABASE = "database" + URI_PATH_PARAM_DATABASE = "/:" + URI_PARAM_DATABASE // Used for backup URI_ARCHIVE = "/log" @@ -112,6 +138,7 @@ const ( URI_OBSERVER_API_PREFIX = URI_API_V1 + URI_OBSERVER_GROUP URI_ZONE_API_PREFIX = URI_API_V1 + URI_ZONE_GROUP URI_TENANT_API_PREFIX = URI_API_V1 + URI_TENANT_GROUP + URI_OBPROXY_API_PREFIX = URI_API_V1 + URI_OBPROXY_GROUP URI_TASK_RPC_PREFIX = URI_RPC_V1 + URI_TASK_GROUP URI_AGENT_RPC_PREFIX = URI_RPC_V1 + URI_AGENT_GROUP diff --git a/agent/engine/coordinator/coordinator.go b/agent/engine/coordinator/coordinator.go index ff3be726..19a21d18 100644 --- a/agent/engine/coordinator/coordinator.go +++ b/agent/engine/coordinator/coordinator.go @@ -225,7 +225,7 @@ func (c *Coordinator) buildMaintainerByPolling() error { } if err := c.getMaintainerbyRpc(&agent); err != nil { - log.WithError(err).Warnf("get maintainer from '%s:%d' failed", agent.GetIp(), agent.GetPort()) + log.WithError(err).Warnf("get maintainer from '%s' failed", agent.String()) continue } return nil @@ -235,7 +235,7 @@ func (c *Coordinator) buildMaintainerByPolling() error { func (c *Coordinator) getMaintainerbyRpc(agentInfo meta.AgentInfoInterface) error { now := time.Now() - log.Infof("try get maintainer rpc request from '%s:%d' to '%s:%d' ", meta.OCS_AGENT.GetIp(), meta.OCS_AGENT.GetPort(), agentInfo.GetIp(), agentInfo.GetPort()) + log.Infof("try get maintainer rpc request from '%s' to '%s' ", meta.OCS_AGENT.String(), agentInfo.String()) maintainer := Maintainer{} if err := secure.SendGetRequest(agentInfo, constant.URI_RPC_V1+constant.URI_MAINTAINER, nil, &maintainer); err != nil { return err diff --git a/agent/engine/executor/executor.go b/agent/engine/executor/executor.go index d1d56511..a4d077e5 100644 --- a/agent/engine/executor/executor.go +++ b/agent/engine/executor/executor.go @@ -233,7 +233,7 @@ func sendUpdateTaskRpc(remoteTaskId int64, task task.ExecutableTask) error { if coordinator.OCS_COORDINATOR.IsFaulty() { return errors.New("faulty does not have maintainer") } - log.Infof("send update task rpc to %s:%d, remote task id %d", coordinator.OCS_COORDINATOR.Maintainer.GetIp(), coordinator.OCS_COORDINATOR.Maintainer.GetPort(), remoteTaskId) + log.Infof("send update task rpc to %s, remote task id %d", coordinator.OCS_COORDINATOR.Maintainer.String(), remoteTaskId) remoteTask := createRemoteTask(remoteTaskId, task) maintainerAgent := coordinator.OCS_COORDINATOR.Maintainer return secure.SendPatchRequest(maintainerAgent, constant.URI_TASK_RPC_PREFIX+constant.URI_SUB_TASK, remoteTask, nil) diff --git a/agent/engine/executor/task_log_sync.go b/agent/engine/executor/task_log_sync.go index d78a0355..f1e21a79 100644 --- a/agent/engine/executor/task_log_sync.go +++ b/agent/engine/executor/task_log_sync.go @@ -104,6 +104,6 @@ func (synchronizer *taskLogSynchronizer) syncTaskLog(taskLog *sqlite.SubTaskLog) func postTaskLogToRemote(taskLog task.TaskExecuteLogDTO) error { maintainerAgent := coordinator.OCS_COORDINATOR.Maintainer - log.Infof("send task log to %s:%d", maintainerAgent.GetIp(), maintainerAgent.GetPort()) + log.Infof("send task log to %s", maintainerAgent.String()) return secure.SendPostRequest(maintainerAgent, constant.URI_TASK_RPC_PREFIX+constant.URI_LOG, taskLog, nil) } diff --git a/agent/engine/scheduler/task_handler.go b/agent/engine/scheduler/task_handler.go index e88ca706..d1975589 100644 --- a/agent/engine/scheduler/task_handler.go +++ b/agent/engine/scheduler/task_handler.go @@ -238,7 +238,7 @@ func (s *Scheduler) updateExecuterAgent(node *task.Node, subTask task.Executable ctx := node.GetContext() agents := ctx.GetParam(task.EXECUTE_AGENTS) if agents == nil { // Not specified execute agent. - log.withScheduler(s).Infof("subtask %d update executer agent %s:%d to %s:%d\n", subTask.GetID(), subTask.GetExecuteAgent().Ip, subTask.GetExecuteAgent().Port, meta.OCS_AGENT.GetIp(), meta.OCS_AGENT.GetPort()) + log.withScheduler(s).Infof("subtask %d update executer agent %s to %s\n", subTask.GetID(), subTask.GetExecuteAgent().String(), meta.OCS_AGENT.String()) subTask.SetExecuteAgent(*meta.NewAgentInfoByInterface(meta.OCS_AGENT)) } } @@ -278,14 +278,14 @@ func (s *Scheduler) runSubTask(subTask *task.RemoteTask) error { } } else { if err := s.sendRunSubTaskRpc(subTask); err != nil { - return errors.Wrapf(err, "send run sub task rpc to %s:%d error", agentInfo.Ip, agentInfo.Port) + return errors.Wrapf(err, "send run sub task rpc to %s error", agentInfo.String()) } } return nil } func (s *Scheduler) sendRunSubTaskRpc(subTask *task.RemoteTask) error { - log.withScheduler(s).Infof("send run sub task %d to %s:%d", subTask.TaskID, subTask.ExecuterAgent.Ip, subTask.ExecuterAgent.Port) + log.withScheduler(s).Infof("send run sub task %d to %s", subTask.TaskID, subTask.ExecuterAgent.String()) return secure.SendPostRequest(&subTask.ExecuterAgent, constant.URI_TASK_RPC_PREFIX+constant.URI_SUB_TASK, subTask, nil) } diff --git a/agent/engine/task/context.go b/agent/engine/task/context.go index bddcbcc6..bfecef20 100644 --- a/agent/engine/task/context.go +++ b/agent/engine/task/context.go @@ -58,7 +58,7 @@ func (ctx *TaskContext) GetData(key string) interface{} { } func (ctx *TaskContext) GetAgentData(agent meta.AgentInfoInterface, key string) interface{} { - return ctx.GetAgentDataByAgentKey(fmt.Sprintf("%s:%d", agent.GetIp(), agent.GetPort()), key) + return ctx.GetAgentDataByAgentKey(agent.String(), key) } func (ctx *TaskContext) GetAgentDataByAgentKey(agentKey string, key string) interface{} { diff --git a/agent/engine/task/dag.go b/agent/engine/task/dag.go index 8e4bd5ab..f4a0d448 100644 --- a/agent/engine/task/dag.go +++ b/agent/engine/task/dag.go @@ -20,6 +20,20 @@ import ( "time" ) +type DagType uint8 + +const ( + DAG_OB DagType = iota + DAG_OBPROXY +) + +var ( + DAG_TYPE_MAP = map[DagType]string{ + DAG_OB: "ob", + DAG_OBPROXY: "obproxy", + } +) + type Dag struct { dagType string stage int diff --git a/agent/engine/task/maintenance_type.go b/agent/engine/task/maintenance_type.go index 27ac2b3b..49c33eec 100644 --- a/agent/engine/task/maintenance_type.go +++ b/agent/engine/task/maintenance_type.go @@ -44,6 +44,7 @@ const ( NOT_UNDER_MAINTENANCE GLOBAL_MAINTENANCE TENANT_MAINTENANCE + OBPROXY_MAINTENACE ) func UnMaintenance() Maintainer { @@ -65,6 +66,12 @@ func TenantMaintenance(tenantName string) Maintainer { } } +func ObproxyMaintenance() Maintainer { + return &maintenance{ + maintenanceType: OBPROXY_MAINTENACE, + } +} + func NewMaintenance(maintenanceType int, maintenanceKey string) Maintainer { return &maintenance{ maintenanceType: maintenanceType, diff --git a/agent/engine/task/node.go b/agent/engine/task/node.go index 3e00b648..072dcb11 100644 --- a/agent/engine/task/node.go +++ b/agent/engine/task/node.go @@ -33,6 +33,7 @@ type Node struct { nodeType string upStream *Node downStream *Node + dagId int TaskInfo ctx *TaskContext } @@ -45,6 +46,10 @@ func (node *Node) GetNodeType() string { return node.nodeType } +func (node *Node) GetDagId() int { + return node.dagId +} + func (node *Node) GetSubTasks() []ExecutableTask { return node.subtasks } @@ -166,12 +171,13 @@ func NewNodeWithContext(task ExecutableTask, paralle bool, ctx *TaskContext) *No return node } -func NewNodeWithId(id int64, name string, nodeType string, state int, operator int, structName string, ctx *TaskContext, isLocalTask bool, startTime time.Time, endTime time.Time) *Node { +func NewNodeWithId(id int64, name string, dagId int, nodeType string, state int, operator int, structName string, ctx *TaskContext, isLocalTask bool, startTime time.Time, endTime time.Time) *Node { node := &Node{ taskType: TASK_TYPE[structName], subtasks: make([]ExecutableTask, 0), nodeType: nodeType, ctx: ctx, + dagId: dagId, TaskInfo: TaskInfo{ id: id, name: name, diff --git a/agent/engine/task/task.go b/agent/engine/task/task.go index 2fbe6774..1a7d3a27 100644 --- a/agent/engine/task/task.go +++ b/agent/engine/task/task.go @@ -564,7 +564,7 @@ func CreateSubTaskInstance( }, executeTimes: executeTimes, executerAgent: executerAgent, - localAgentKey: fmt.Sprintf("%s:%d", executerAgent.GetIp(), executerAgent.GetPort()), + localAgentKey: executerAgent.String(), } taskInstance := reflect.New(TASK_TYPE[taskType]).Elem() diff --git a/agent/engine/task/task_dto.go b/agent/engine/task/task_dto.go index 90960bcc..e7decf53 100644 --- a/agent/engine/task/task_dto.go +++ b/agent/engine/task/task_dto.go @@ -204,28 +204,28 @@ func NewTaskStatusDTO(task *TaskInfo) *TaskStatusDTO { func NewDagDetailDTO(dag *Dag) *DagDetailDTO { return &DagDetailDTO{ - GenericDTO: newGenericDTO(dag), + GenericDTO: newGenericDTO(dag, dag.GetDagType()), DagDetail: NewDagDetail(dag), } } -func NewNodeDetailDTO(node *Node) *NodeDetailDTO { +func NewNodeDetailDTO(node *Node, dagType string) *NodeDetailDTO { return &NodeDetailDTO{ - GenericDTO: newGenericDTO(node), + GenericDTO: newGenericDTO(node, dagType), NodeDetail: NewNodeDetail(node), } } -func NewTaskDetailDTO(task ExecutableTask) *TaskDetailDTO { +func NewTaskDetailDTO(task ExecutableTask, dagType string) *TaskDetailDTO { return &TaskDetailDTO{ - GenericDTO: newGenericDTO(task), + GenericDTO: newGenericDTO(task, dagType), TaskDetail: NewTaskDetail(task), } } -func newGenericDTO(instance TaskInfoInterface) *GenericDTO { +func newGenericDTO(instance TaskInfoInterface, dagType string) *GenericDTO { return &GenericDTO{ - GenericID: ConvertToGenericID(instance), + GenericID: ConvertToGenericID(instance, dagType), } } @@ -268,23 +268,37 @@ func NewTaskDetail(task ExecutableTask) *TaskDetail { } // ConvertToGenericID will convert task instance id to generic dto id. -func ConvertToGenericID(instance TaskInfoInterface) string { +func ConvertToGenericID(instance TaskInfoInterface, dagType string) string { if instance.IsLocalTask() { - return ConvertLocalIDToGenericID(instance.GetID()) + return ConvertLocalIDToGenericID(instance.GetID(), dagType) } return fmt.Sprintf("1%d", instance.GetID()) } -func ConvertIDToGenericID(dagID int64, isLocal bool) string { +func ConvertIDToGenericID(dagID int64, isLocal bool, dagType string) string { if isLocal { - return ConvertLocalIDToGenericID(dagID) + return ConvertLocalIDToGenericID(dagID, dagType) } else { return fmt.Sprintf("1%d", dagID) } } +func ConvertObproxyIDToGenericID(id int64) string { + ipParsed := net.ParseIP(meta.OCS_AGENT.GetIp()) + if ipParsed.To4() != nil { + bigInt := new(big.Int).SetBytes(ipParsed.To4()) + return fmt.Sprintf("4%010d%05d%d", bigInt, meta.OCS_AGENT.GetPort(), id) + } else { + bigInt := new(big.Int).SetBytes(ipParsed.To16()) + return fmt.Sprintf("5%039d%05d%d", bigInt, meta.OCS_AGENT.GetPort(), id) + } +} + // ConvertLocalIDToGenericID will convert id of local task to generic id. -func ConvertLocalIDToGenericID(id int64) string { +func ConvertLocalIDToGenericID(id int64, dagType string) string { + if DAG_TYPE_MAP[DAG_OBPROXY] == dagType { + return ConvertObproxyIDToGenericID(id) + } ipParsed := net.ParseIP(meta.OCS_AGENT.GetIp()) if ipParsed.To4() != nil { bigInt := new(big.Int).SetBytes(ipParsed.To4()) @@ -295,11 +309,17 @@ func ConvertLocalIDToGenericID(id int64) string { } } +func IsObproxyTask(genericID string) bool { + return genericID[0] == constant.OBPROXY_TASK_IPV4_ID_PREFIX || genericID[0] == constant.OBPROXY_TASK_IPV6_ID_PREFIX +} + // ConvertGenericID will onvert dto id to instance id. func ConvertGenericID(genericID string) (id int64, agent meta.AgentInfoInterface, err error) { if genericID[0] == constant.CLUSTER_TASK_ID_PREFIX && len(genericID) <= 1 || - genericID[0] == constant.LOCAL_TASK_IPV4_ID_PREFIX && len(genericID) <= 16 || - genericID[0] == constant.LOCAL_TASK_IPV6_ID_PREFIX && len(genericID) <= 45 { + (genericID[0] == constant.LOCAL_TASK_IPV4_ID_PREFIX || + genericID[0] == constant.OBPROXY_TASK_IPV4_ID_PREFIX) && len(genericID) <= 16 || + (genericID[0] == constant.LOCAL_TASK_IPV6_ID_PREFIX || + genericID[0] == constant.OBPROXY_TASK_IPV6_ID_PREFIX) && len(genericID) <= 45 { err = fmt.Errorf("invalid id: %s", genericID) return } @@ -309,10 +329,10 @@ func ConvertGenericID(genericID string) (id int64, agent meta.AgentInfoInterface switch genericID[0] { case constant.CLUSTER_TASK_ID_PREFIX: idIdx = 1 - case constant.LOCAL_TASK_IPV4_ID_PREFIX: + case constant.LOCAL_TASK_IPV4_ID_PREFIX, constant.OBPROXY_TASK_IPV4_ID_PREFIX: // Ipv4 address. ipIdx, portIdx, idIdx = 11, 16, 16 - case constant.LOCAL_TASK_IPV6_ID_PREFIX: + case constant.LOCAL_TASK_IPV6_ID_PREFIX, constant.OBPROXY_TASK_IPV6_ID_PREFIX: // Ipv6 address. ipIdx, portIdx, idIdx, isV6 = 40, 45, 45, true default: diff --git a/agent/engine/task/template.go b/agent/engine/task/template.go index cf60be10..f0018c23 100644 --- a/agent/engine/task/template.go +++ b/agent/engine/task/template.go @@ -21,6 +21,7 @@ type Template struct { nodes []*Node Name string maintenance Maintainer + Type string } func (template *Template) AddNode(node *Node) { @@ -89,3 +90,8 @@ func (builder *TemplateBuilder) SetMaintenance(maintenanceType Maintainer) *Temp builder.Template.maintenance = maintenanceType return builder } + +func (builder *TemplateBuilder) SetType(dagType DagType) *TemplateBuilder { + builder.Template.Type = DAG_TYPE_MAP[dagType] + return builder +} diff --git a/agent/errors/errorcode.go b/agent/errors/errorcode.go index 881182c4..12a51190 100644 --- a/agent/errors/errorcode.go +++ b/agent/errors/errorcode.go @@ -26,6 +26,7 @@ const ( unauthorized ErrorKind = http.StatusUnauthorized notFound ErrorKind = http.StatusNotFound unexpected ErrorKind = http.StatusInternalServerError + notfound ErrorKind = http.StatusNotFound known ErrorKind = http.StatusInternalServerError ) @@ -54,6 +55,7 @@ var ( ErrBadRequest = NewErrorCode(1000, badRequest, "err.bad.request") ErrIllegalArgument = NewErrorCode(1001, illegalArgument, "err.illegal.argument") ErrUnexpected = NewErrorCode(1002, unexpected, "err.unexpected") + ErrNotFound = NewErrorCode(1003, notfound, "err.not.found") ErrKnown = NewErrorCode(1010, known, "err.known") // ob operation error codes, range: 10000 ~ 10999 @@ -61,6 +63,9 @@ var ( ErrUnauthorized = NewErrorCode(10008, unauthorized, "err.unauthorized") ErrObclusterNotFound = NewErrorCode(10009, known, "err.obcluster.not.found") + // tenant obperation err codes, range: 20000 ~ 20999 + ErrTenantNotConnectable = NewErrorCode(20000, unexpected, "err.tenant.not.connectable") + // task error codes, range: 2300 ~ 2399 ErrTaskNotFound = NewErrorCode(2300, notFound, "err.task.not.found") ErrTaskCreateFailed = NewErrorCode(2301, known, "err.task.create.failed") diff --git a/agent/errors/type.go b/agent/errors/type.go index 52e802c4..daba3ddd 100644 --- a/agent/errors/type.go +++ b/agent/errors/type.go @@ -27,3 +27,7 @@ func IsTaskNotFoundErr(err error) bool { func IsUnkonwnTimeZoneErr(err error) bool { return strings.Contains(err.Error(), "Unknown or incorrect time zone") } + +func IsRecordNotFoundErr(err error) bool { + return strings.Contains(err.Error(), "record not found") +} diff --git a/agent/executor/agent/enter.go b/agent/executor/agent/enter.go index 66a1e1d9..f8009da0 100644 --- a/agent/executor/agent/enter.go +++ b/agent/executor/agent/enter.go @@ -33,6 +33,7 @@ var ( const ( // task param PARAM_MASTER_AGENT = "masterAgent" + PARAM_MASTER_AGENT_PASSWORD = "masterAgentPassword" PARAM_ZONE = "zone" PARAM_AGENT = "agent" PARAM_TAKE_OVER_MASTER_AGENT = "takeOverMasterAgent" diff --git a/agent/executor/agent/follower_remove.go b/agent/executor/agent/follower_remove.go index 89a21339..afa3852f 100644 --- a/agent/executor/agent/follower_remove.go +++ b/agent/executor/agent/follower_remove.go @@ -77,7 +77,7 @@ func CreateRemoveFollowerAgentDag(agent meta.AgentInfo, fromAPI bool) (*task.Dag // Follower agent send rpc to master agent to remove itself or master agent receive api to remove follower agent. // Then, master agent create a task to remove follower agent. // Master will clear observer and zone config if there is no other follower agent in the zone. - name := fmt.Sprintf("Remove follower agent %s:%d", agent.Ip, agent.Port) + name := fmt.Sprintf("Remove follower agent %s", agent.String()) builder := task.NewTemplateBuilder(name) if fromAPI { builder.AddNode(newAgentRemoveFollowerRPCNode([]meta.AgentInfo{agent})) @@ -118,13 +118,13 @@ func (t *RemoveFollowerAgentTask) Execute() (err error) { return errors.Wrap(err, "get param failed") } - t.ExecuteLogf("finding agent %s:%d info", agent.Ip, agent.Port) + t.ExecuteLogf("finding agent %s info", agent.String()) agentInstance, err := GetFollowerAgent(&agent) if err != nil { return errors.Wrap(err, "get follower agent failed") } if agentInstance == nil { - t.ExecuteLogf("agent %s:%d is not exists", agent.Ip, agent.Port) + t.ExecuteLogf("agent %s is not exists", agent.String()) return nil } @@ -145,11 +145,11 @@ func (t *RemoveFollowerAgentTask) Execute() (err error) { } } - t.ExecuteLogf("deleting agent %s:%d", agent.Ip, agent.Port) + t.ExecuteLogf("deleting agent %s", agent.String()) if err = agentService.DeleteAgent(&agent); err != nil { return errors.Wrap(err, "delete agent failed") } - t.ExecuteLogf("remove follower agent %s:%d success", agent.Ip, agent.Port) + t.ExecuteLogf("remove follower agent %s success", agent.String()) return nil } @@ -185,7 +185,7 @@ func GetFollowerAgent(agent meta.AgentInfoInterface) (agentInstance *meta.AgentI if err != nil { err = errors.Wrap(err, "get agent instance failed") } else if agentInstance != nil && !agentInstance.IsFollowerAgent() { - err = errors.Errorf("agent %s:%d is not follower", agent.GetIp(), agent.GetPort()) + err = errors.Errorf("agent %s is not follower", agent.String()) } return } diff --git a/agent/executor/agent/join_follower.go b/agent/executor/agent/join_follower.go index 345cff6c..d5742787 100644 --- a/agent/executor/agent/join_follower.go +++ b/agent/executor/agent/join_follower.go @@ -23,6 +23,7 @@ import ( "github.com/oceanbase/obshell/agent/engine/task" "github.com/oceanbase/obshell/agent/errors" "github.com/oceanbase/obshell/agent/global" + "github.com/oceanbase/obshell/agent/lib/http" "github.com/oceanbase/obshell/agent/meta" "github.com/oceanbase/obshell/agent/secure" "github.com/oceanbase/obshell/param" @@ -30,13 +31,29 @@ import ( type AgentJoinMasterTask struct { task.Task + masterPassword string } type AgentBeFollowerTask struct { task.Task } -func CreateJoinMasterDag(masterAgent meta.AgentInfo, zone string) (*task.Dag, error) { +func SendTokenToMaster(agentInfo meta.AgentInfo, masterPassword string) error { + token, err := secure.NewToken(&agentInfo) + if err != nil { + return errors.Wrap(err, "get token failed") + } + param := param.AddTokenParam{ + AgentInfo: *meta.NewAgentInfoByInterface(meta.OCS_AGENT), + Token: token, + } + if err := secure.SendRequestWithPassword(&agentInfo, constant.URI_AGENT_RPC_PREFIX+constant.URI_TOKEN, http.POST, masterPassword, param, nil); err != nil { + return errors.Wrap(err, "send post request failed") + } + return nil +} + +func CreateJoinMasterDag(masterAgent meta.AgentInfo, zone string, masterPassword string) (*task.Dag, error) { // Agent receive api to join master, then create a task to be follower. builder := task.NewTemplateBuilder(DAG_JOIN_TO_MASTER) @@ -53,8 +70,16 @@ func CreateJoinMasterDag(masterAgent meta.AgentInfo, zone string) (*task.Dag, er builder.AddTask(beFollowerAgent, false) builder.SetMaintenance(task.GlobalMaintenance()) + + // Encrypt master agent password. + agentPassword, err := secure.Encrypt(masterPassword) + if err != nil { + return nil, errors.Wrap(err, "encrypt master password failed") + } template := builder.Build() - ctx := task.NewTaskContext().SetParam(PARAM_ZONE, zone).SetParam(PARAM_MASTER_AGENT, masterAgent) + ctx := task.NewTaskContext().SetParam(PARAM_ZONE, zone).SetParam(PARAM_MASTER_AGENT, masterAgent). + SetParam(PARAM_MASTER_AGENT_PASSWORD, agentPassword) + return localTaskService.CreateDagInstanceByTemplate(template, ctx) } @@ -64,6 +89,14 @@ func (t *AgentJoinMasterTask) Execute() error { if err := taskCtx.GetParamWithValue(PARAM_MASTER_AGENT, &masterAgent); err != nil { return errors.Wrapf(err, "Get Param %s failed", PARAM_MASTER_AGENT) } + if err := taskCtx.GetParamWithValue(PARAM_MASTER_AGENT_PASSWORD, &t.masterPassword); err != nil { + return errors.Wrapf(err, "Get Param %s failed", PARAM_MASTER_AGENT_PASSWORD) + } + // Decrypt master agent password. + masterPassword, err := secure.Decrypt(t.masterPassword) + if err != nil { + return errors.Wrap(err, "decrypt master password failed") + } zone, ok := t.GetContext().GetParam(PARAM_ZONE).(string) if !ok { return errors.New("zone is not set") @@ -89,8 +122,9 @@ func (t *AgentJoinMasterTask) Execute() error { Token: token, } t.ExecuteLog("send join rpc to master") + var masterAgentInstance meta.AgentInstance - if err := secure.SendPostRequest(&masterAgent, constant.URI_AGENT_RPC_PREFIX, param, &masterAgentInstance); err != nil { + if err := secure.SendRequestWithPassword(&masterAgent, constant.URI_AGENT_RPC_PREFIX, http.POST, masterPassword, param, &masterAgentInstance); err != nil { return errors.Wrap(err, "send post request failed") } t.ExecuteLog(fmt.Sprintf("join to master success, master agent info: %v", masterAgentInstance)) @@ -126,7 +160,7 @@ func (t *AgentBeFollowerTask) Execute() error { func AddFollowerAgent(param param.JoinMasterParam) *errors.OcsAgentError { targetToken, err := secure.Crypter.Decrypt(param.Token) if err != nil { - return errors.Occurf(errors.ErrKnown, "decrypt token of '%s:%d' failed: %v", param.JoinApiParam.AgentInfo.GetIp(), param.JoinApiParam.AgentInfo.GetPort(), err) + return errors.Occurf(errors.ErrKnown, "decrypt token of '%s' failed: %v", param.JoinApiParam.AgentInfo.String(), err) } agentInstance := meta.NewAgentInstanceByAgentInfo(¶m.JoinApiParam.AgentInfo, param.JoinApiParam.ZoneName, meta.FOLLOWER, param.Version) @@ -136,19 +170,14 @@ func AddFollowerAgent(param param.JoinMasterParam) *errors.OcsAgentError { return nil } -func UpdateFollowerAgent(agentInstance meta.Agent, param param.JoinMasterParam) *errors.OcsAgentError { - // Agent already exists. - if agentInstance.GetIdentity() != meta.FOLLOWER || agentInstance.GetVersion() != param.Version || agentInstance.GetZone() != param.JoinApiParam.ZoneName { - return errors.Occur(errors.ErrBadRequest, "agent already exists") - } - +func AddSingleToken(param param.AddTokenParam) *errors.OcsAgentError { targetToken, err := secure.Crypter.Decrypt(param.Token) if err != nil { - return errors.Occurf(errors.ErrKnown, "decrypt token of '%s:%d' failed: %v", param.JoinApiParam.AgentInfo.GetIp(), param.JoinApiParam.AgentInfo.GetPort(), err) + return errors.Occurf(errors.ErrKnown, "decrypt token of '%s' failed: %v", param.AgentInfo.String(), err) } - if err = agentService.UpdateAgent(agentInstance, param.HomePath, param.Os, param.Architecture, param.PublicKey, targetToken); err != nil { - return errors.Occurf(errors.ErrKnown, "update agent failed: %v", err) + if err = agentService.AddSingleToken(¶m.AgentInfo, targetToken); err != nil { + return errors.Occurf(errors.ErrKnown, "insert token failed: %v", err) } return nil } diff --git a/agent/executor/ob/bootstrap.go b/agent/executor/ob/bootstrap.go index ae0fcb43..e0fed06c 100644 --- a/agent/executor/ob/bootstrap.go +++ b/agent/executor/ob/bootstrap.go @@ -90,7 +90,8 @@ func (t *ClusterBoostrapTask) generateBootstrapCmd() (string, error) { if !ok { return "", fmt.Errorf("zone %s has no rs", zone) } - list = append(list, fmt.Sprintf("ZONE '%s' SERVER '%s:%d'", zone, observerInfo.Ip, observerInfo.Port)) + agent := meta.NewAgentInfo(observerInfo.Ip, observerInfo.Port) + list = append(list, fmt.Sprintf("ZONE '%s' SERVER '%s'", zone, agent.String())) } bootstrapCmd = bootstrapCmd + strings.Join(list, ", ") return bootstrapCmd, nil @@ -113,7 +114,8 @@ func (t *ClusterBoostrapTask) execBootstrap(cmd string) error { func (t *ClusterBoostrapTask) addServers() error { for zone, serverList := range t.unRS { for _, server := range serverList { - sql := fmt.Sprintf("ALTER SYSTEM ADD SERVER '%s:%d' ZONE '%s'", server.Ip, server.Port, zone) + agent := meta.NewAgentInfo(server.Ip, server.Port) + sql := fmt.Sprintf("ALTER SYSTEM ADD SERVER '%s' ZONE '%s'", agent.String(), zone) t.ExecuteInfoLogf("add server: %s", sql) if err := obclusterService.ExecuteSqlWithoutIdentityCheck(sql); err != nil { return err diff --git a/agent/executor/ob/charset.go b/agent/executor/ob/charset.go new file mode 100644 index 00000000..7fcc34b9 --- /dev/null +++ b/agent/executor/ob/charset.go @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ob + +import ( + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/repository/model/bo" + "github.com/oceanbase/obshell/agent/repository/model/oceanbase" +) + +func supportMysql(charset *oceanbase.ObCharset) bool { + return charset.Charset != "utf16" +} + +// GetObclusterCharsets retrieves all character sets supporting MYSQL and their collations from the OceanBase cluster. +func GetObclusterCharsets() ([]bo.CharsetInfo, *errors.OcsAgentError) { + charsets, err := obclusterService.GetAllCharsets() + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err) + } + collations, err := obclusterService.GetAllCollations() + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err) + } + charsetInfoMap := make(map[string]*bo.CharsetInfo, len(charsets)) + for i := range charsets { + if !supportMysql(&charsets[i]) { + continue + } + charsetInfoMap[charsets[i].Charset] = &bo.CharsetInfo{ + Name: charsets[i].Charset, + Description: charsets[i].Description, + Maxlen: charsets[i].MaxLen, + Collations: make([]bo.CollationInfo, 0), + } + } + for i := range collations { + if _, ok := charsetInfoMap[collations[i].Charset]; !ok { + continue + } + charsetInfoMap[collations[i].Charset].Collations = append(charsetInfoMap[collations[i].Charset].Collations, bo.CollationInfo{ + Name: collations[i].Collation, + IsDefault: collations[i].IsDefault == "Yes", + }) + } + charsetinfos := make([]bo.CharsetInfo, 0, len(charsetInfoMap)) + for _, charsetInfo := range charsetInfoMap { + charsetinfos = append(charsetinfos, *charsetInfo) + } + return charsetinfos, nil +} diff --git a/agent/executor/ob/cluster.go b/agent/executor/ob/cluster.go new file mode 100644 index 00000000..996b436a --- /dev/null +++ b/agent/executor/ob/cluster.go @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ob + +import ( + "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/executor/tenant" + "github.com/oceanbase/obshell/agent/meta" + "github.com/oceanbase/obshell/agent/repository/db/oceanbase" + "github.com/oceanbase/obshell/agent/repository/model/bo" +) + +// only for mysql +func GetObclusterSummary() (*bo.ClusterInfo, *errors.OcsAgentError) { + var info bo.ClusterInfo + + // Get all tenant infos + tenantOverviews, err := tenantService.GetTenantsOverViewByMode(constant.MYSQL_MODE) + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + for _, tenantOverview := range tenantOverviews { + tenantInfo, err := tenant.GetTenantInfo(tenantOverview.TenantName) + if err != nil { + return nil, err + } + info.Tenants = append(info.Tenants, *tenantInfo) + } + + // Set basic cluster info + if err := observerService.GetOBParatemerByName("cluster", &info.ClusterName); err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + if err := observerService.GetOBParatemerByName("cluster_id", &info.ClusterId); err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + isCommunityEdition, err := obclusterService.IsCommunityEdition() + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + info.IsCommunityEdition = isCommunityEdition + info.Status = oceanbase.OBStateShortMap[oceanbase.GetState()] + version, err := obclusterService.GetObVersion() + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + info.ObVersion = version + + rootServers, err := obclusterService.GetAllZoneRootServers() + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + + zones, err := obclusterService.GetAllZone() + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + + serverResourceMap, err := obclusterService.GetAllObserverResourceMap() + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + + allAgents, _ := agentService.GetAllAgentsDOFromOB() + archMap := make(map[string]string) + for _, agent := range allAgents { + archMap[meta.NewAgentInfo(agent.Ip, agent.RpcPort).String()] = agent.Architecture + } + + for _, zone := range zones { + var zoneInfo bo.Zone + zoneInfo.Name = zone.Zone + zoneInfo.IdcName = zone.Idc + zoneInfo.RegionName = zone.Region + zoneInfo.InnerStatus = zone.Status + if zoneInfo.InnerStatus == "ACTIVE" { + zoneInfo.Status = "RUNNING" + } else if zoneInfo.InnerStatus == "INACTIVE" { + zoneInfo.Status = "SERVICE_STOPPED" + } + if rootServer, ok := rootServers[zone.Zone]; ok { + zoneInfo.RootServer = rootServer.ToBO() + } + observers, err := obclusterService.GetOBServersByZone(zone.Zone) + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + + for _, server := range observers { + observerBo := server.ToBo() + observerBo.Architecture = archMap[meta.NewAgentInfo(server.SvrIp, server.SvrPort).String()] + if baseResourceStat, ok := serverResourceMap[meta.ObserverSvrInfo{ + Ip: server.SvrIp, + Port: server.SvrPort, + }]; !ok { + zoneInfo.Servers = append(zoneInfo.Servers, observerBo) + continue + } else { + observerBo.Stats.BaseResourceStats = baseResourceStat.ToBO() + observerBo.Stats.FillExtendDiskStats() + observerBo.Stats.Zone = zone.Zone + observerBo.Stats.Ip = server.SvrIp + observerBo.Stats.Port = server.SvrPort + } + zoneInfo.Servers = append(zoneInfo.Servers, observerBo) + } + info.Zones = append(info.Zones, zoneInfo) + } + + // Set cluster stats + for _, zone := range info.Zones { + for _, server := range zone.Servers { + info.Stats.Add(&server.Stats.BaseResourceStats) + } + } + + // Set tenant stats + for _, tenant := range info.Tenants { + tenantSysStatsMap, err := obclusterService.GetTenantMutilSysStat(tenant.Id, []int{SYS_STAT_CPU_USAGE_STAT_ID, SYS_STAT_MEMORY_USAGE_STAT_ID, SYS_STAT_MAX_CPU_STAT_ID, SYS_STAT_MEMORY_SIZE_STAT_ID}) + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + + var tenantResourceStat bo.TenantResourceStat + tenantResourceStat.TenantId = tenant.Id + tenantResourceStat.TenantName = tenant.Name + var cpuUsage, maxCpu, memoryUsage, memorySize float64 + if sysStat, ok := tenantSysStatsMap[SYS_STAT_CPU_USAGE_STAT_ID]; ok { + cpuUsage = float64(sysStat.Value) + } + if sysStat, ok := tenantSysStatsMap[SYS_STAT_MAX_CPU_STAT_ID]; ok { + maxCpu = float64(sysStat.Value) + } + if sysStat, ok := tenantSysStatsMap[SYS_STAT_MEMORY_USAGE_STAT_ID]; ok { + memoryUsage = float64(sysStat.Value) + } + if sysStat, ok := tenantSysStatsMap[SYS_STAT_MEMORY_SIZE_STAT_ID]; ok { + memorySize = float64(sysStat.Value) + } + tenantResourceStat.CpuUsedPercent = cpuUsage / maxCpu * 100 + tenantResourceStat.MemoryUsedPercent = memoryUsage / memorySize * 100 + tenantDataDiskUsageMap, err := tenantService.GetTenantDataDiskUsageMap() + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + tenantResourceStat.DataDiskUsage = tenantDataDiskUsageMap[tenant.Id] + info.TenantStats = append(info.TenantStats, tenantResourceStat) + } + return &info, nil +} diff --git a/agent/executor/ob/config.go b/agent/executor/ob/config.go index 2c9b53d8..4cf123e9 100644 --- a/agent/executor/ob/config.go +++ b/agent/executor/ob/config.go @@ -19,7 +19,6 @@ package ob import ( "fmt" "path/filepath" - "regexp" "strconv" "strings" @@ -135,28 +134,15 @@ func (t *UpdateOBServerConfigTask) updateZoneConfig() error { func (t *UpdateOBServerConfigTask) updateServerConfig() error { agents := make([]meta.AgentInfoInterface, 0) for _, server := range t.config.Scope.Target { - agent := ConvertAgentInfo(server) - if agent == nil { - return fmt.Errorf("invalid server: %s", server) + agent, err := meta.ConvertAddressToAgentInfo(server) + if err != nil { + return err } agents = append(agents, agent) } return observerService.UpdateServerConfig(t.config.ObServerConfig, agents, t.deleteAll) } -func ConvertAgentInfo(str string) meta.AgentInfoInterface { - re := regexp.MustCompile(`(\[?[^\[\]:]+\]?):(\d+)`) - matches := re.FindAllStringSubmatch(str, -1) - if len(matches) != 1 || len(matches[0]) != 3 { - return nil - } - port, err := strconv.Atoi(matches[0][2]) - if err != nil { - return nil - } - return meta.NewAgentInfo(matches[0][1], port) -} - func newUpdateOBClusterConfigTask() *UpdateOBClusterConfigTask { newTask := &UpdateOBClusterConfigTask{ Task: *task.NewSubTask(TASK_NAME_UPDATE_CONFIG), @@ -269,6 +255,7 @@ func (t *IntegrateObConfigTask) getAgents() error { agent := *meta.NewAgentInfo(agentDO.Ip, agentDO.Port) t.agents[agent] = agentDO } + t.ExecuteInfoLogf("agents: %v", t.agents) return nil } @@ -362,10 +349,31 @@ func (t *IntegrateObConfigTask) hasRSList() error { rsServers := strings.Split(val.Value, ";") t.ExecuteLogf("check rsList config: %s", rsServers) for _, rsServer := range rsServers { - info := strings.Split(rsServer, ":") + if rsServer == "" { + return fmt.Errorf("invalid rsList config: %s", val.Value) + } + + var info []string + if rsServer[0] == '[' { + t.ExecuteLogf("rsServer: %s is IPv6 address", rsServer) + // It means the rsServer is IPv6 address. + info = strings.Split(rsServer, "]") + if len(info) != 2 { + return fmt.Errorf("invalid rsList config: %s", rsServer) + } + + ip := info[0][1:len(info[0])] + info = strings.Split(info[1], ":") + info[0] = ip + } else { + t.ExecuteLogf("rsServer: %s is IPv4 address", rsServer) + // It means the rsServer is IPv4 address. + info = strings.Split(rsServer, ":") + } if len(info) != 3 { return fmt.Errorf("invalid rsList config: %s", rsServer) } + rpcPort, err := strconv.Atoi(info[1]) if err != nil { return fmt.Errorf("invalid rsList config: %s", rsServer) @@ -419,7 +427,7 @@ func (t *IntegrateObConfigTask) setUNRootServer() error { } func (t *IntegrateObConfigTask) getObserverConfig(agent meta.AgentInfo) (map[string]string, error) { - agentStr := fmt.Sprintf("%s:%d", agent.Ip, agent.Port) + agentStr := agent.String() t.ExecuteLogf("Integrating %s agent config", agentStr) t.ExecuteLogf("get %s agent config", agentStr) diff --git a/agent/executor/ob/convert.go b/agent/executor/ob/convert.go index a36fd7c1..ab458443 100644 --- a/agent/executor/ob/convert.go +++ b/agent/executor/ob/convert.go @@ -92,7 +92,7 @@ func (t *ConvertFollowerToClusterAgentTask) Execute() (err error) { } } for _, agent := range agents { - t.ExecuteLogf("convert agent %s:%d to cluster agent", agent.GetIp(), agent.GetPort()) + t.ExecuteLogf("convert agent %s to cluster agent", agent.String()) if err := agentService.ConvertToClusterAgent(&agent); err != nil { return err } diff --git a/agent/executor/ob/create_user.go b/agent/executor/ob/create_user.go new file mode 100644 index 00000000..7ee5a769 --- /dev/null +++ b/agent/executor/ob/create_user.go @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ob + +import ( + "github.com/oceanbase/obshell/agent/engine/task" + "github.com/oceanbase/obshell/agent/secure" +) + +// CreateDefaultUserTask creates default user, currently limited to 'proxyro'. +type CreateDefaultUserTask struct { + task.Task + encryptProxyroPassword string +} + +func newCreateDefaultUserNode(proxyroPassword string) (*task.Node, error) { + subtask := newCreateDefaultUserTask() + encryptedProxyroPassword, err := secure.Encrypt(proxyroPassword) + if err != nil { + return nil, err + } + ctx := task.NewTaskContext().SetParam(PARAM_PROXYRO_PASSWORD, encryptedProxyroPassword) + return task.NewNodeWithContext(subtask, false, ctx), nil +} + +func newCreateDefaultUserTask() *CreateDefaultUserTask { + newTask := &CreateDefaultUserTask{ + Task: *task.NewSubTask(TASK_NAME_CREATE_USER), + } + newTask.SetCanRetry().SetCanContinue().SetCanCancel() + return newTask +} + +func (t *CreateDefaultUserTask) Execute() error { + if err := t.GetContext().GetParamWithValue(PARAM_PROXYRO_PASSWORD, &t.encryptProxyroPassword); err != nil { + return err + } + + // decrypt password + proxyroPassword, err := secure.Decrypt(t.encryptProxyroPassword) + if err != nil { + return err + } + + if err := obclusterService.CreateProxyroUser(proxyroPassword); err != nil { + return err + } + return nil +} diff --git a/agent/executor/ob/enter.go b/agent/executor/ob/enter.go index a7b74f33..f758ca9e 100644 --- a/agent/executor/ob/enter.go +++ b/agent/executor/ob/enter.go @@ -26,15 +26,15 @@ import ( ) const ( + OB_VERSION_4_3_5_2 = "4.3.5.2" - // start check item - CHECK_PORT = "checkPort" - CHECK_DIR = "checkDir" - CHECK_MEM = "checkMem" - CHECK_DISK = "checkDisk" - CHECK_NET = "checkNet" - CHECK_AIO = "checkAio" - CHECK_ULIM = "checkUlimit" + SYS_STAT_MEMORY_SIZE_STAT_ID = 140002 + SYS_STAT_MEMORY_USAGE_STAT_ID = 140003 + SYS_STAT_MAX_CPU_STAT_ID = 140005 + SYS_STAT_CPU_USAGE_STAT_ID = 140006 + + PARAMETER_SCOPE_TENANT = "TENANT" + PARAMETER_SCOPE_CLUSTER = "CLUSTER" // task context key PARAM_CONFIG = "config" @@ -62,6 +62,7 @@ const ( PARAM_EXPECT_MAIN_NEXT_STAGE = "expectedMainNextStage" PARAM_URI = "uri" PARAM_HEALTH_CHECK = "healthCheck" + PARAM_PROXYRO_PASSWORD = "proxyroPassword" // scale out PARAM_EXPECT_DEPLOY_NEXT_STAGE = "expectedDeployNextStage" PARAM_EXPECT_START_NEXT_STAGE = "expectedStartNextStage" @@ -102,6 +103,7 @@ const ( PARAM_TENANT_NAME = "tenantName" PARAM_TARGET_AGENT_BUILD_VERSION = "targetAgentBuildVersion" + PARAM_TARGET_AGENT_PASSWORD = "targetAgentPassword" // for backup PARAM_NEED_BACKUP_TENANT = "needBackupTenants" @@ -125,6 +127,9 @@ const ( PARAM_RESTORE_SCN = "restoreScn" PARAM_NEED_DELETE_RP = "needDeleteRp" + PARAM_USER_NAME = "userName" + PARAM_USER_PASSWORD = "userPassword" + DATA_ALL_AGENT_DAG_MAP = "allAgentDagMap" DATA_SKIP_START_TASK = "skipStartTask" @@ -155,6 +160,8 @@ const ( TASK_NAME_MIGRATE_TABLE = "Migrate table" TASK_NAME_MODIFY_PWD = "Modify password" TASK_NAME_MIGRATE_DATA = "Migrate data" + TASK_NAME_POST_INIT_CLUSTER = "Post init cluster" + TASK_NAME_CREATE_USER = "Create user" TASK_NAME_UPDATE_AGENT = "Update all agents" TASK_NAME_INITIALIZE_DATA = "Initialize data" TASK_NAME_AGENT_SYNC = "Synchronize agent from cluster" @@ -375,10 +382,12 @@ func RegisterObInitTask() { task.RegisterTaskType(ClusterBoostrapTask{}) task.RegisterTaskType(MigrateTableTask{}) task.RegisterTaskType(ModifyPwdTask{}) + task.RegisterTaskType(CreateDefaultUserTask{}) task.RegisterTaskType(MigrateDataTask{}) task.RegisterTaskType(ConvertFollowerToClusterAgentTask{}) task.RegisterTaskType(AgentSyncTask{}) task.RegisterTaskType(ConvertMasterToClusterAgentTask{}) + task.RegisterTaskType(PostInitClusterTask{}) } func RegisterObStartTask() { diff --git a/agent/executor/ob/info.go b/agent/executor/ob/info.go index b625df28..7e370e08 100644 --- a/agent/executor/ob/info.go +++ b/agent/executor/ob/info.go @@ -217,16 +217,11 @@ func IsValidScope(s *param.Scope) (err error) { return errors.New("server scope must have target") } for _, server := range s.Target { - info := strings.Split(server, ":") - if len(info) != 2 { - return errors.Errorf("invalid server '%s'", server) - } - port, err := strconv.Atoi(info[1]) + agentInfo, err := meta.ConvertAddressToAgentInfo(server) if err != nil { - return errors.Errorf("invalid server '%s' port '%s'", server, info[1]) + return err } - agentInfo := meta.AgentInfo{Ip: info[0], Port: port} - exist, err := agentService.IsAgentExist(&agentInfo) + exist, err := agentService.IsAgentExist(agentInfo) if err != nil { return err } @@ -269,14 +264,14 @@ func GetObAgents() (agents []meta.AgentInfo, err error) { } for _, server := range serversWithRpcPort { - agents = append(agents, meta.AgentInfo{Ip: server[0], Port: meta.OCS_AGENT.GetPort()}) + agents = append(agents, *meta.NewAgentInfo(server.GetIp(), server.GetPort())) } } return } -func GetAllServerFromOBConf() (serversWithRpcPort [][2]string, err error) { +func GetAllServerFromOBConf() (serversWithRpcPort []meta.AgentInfoInterface, err error) { f := path.ObConfigPath() log.Info("get conf from ", f) file, err := os.Open(f) @@ -291,7 +286,7 @@ func GetAllServerFromOBConf() (serversWithRpcPort [][2]string, err error) { } re := regexp.MustCompile("\x00*([_a-zA-Z]+)=(.*)") - var servers, items []string + var servers []string for scanner.Scan() { line := scanner.Text() match := re.FindStringSubmatch(line) @@ -301,15 +296,11 @@ func GetAllServerFromOBConf() (serversWithRpcPort [][2]string, err error) { if match[1] == ETC_KEY_ALL_SERVER_LIST { servers = strings.Split(match[2], ",") for _, server := range servers { - items = strings.Split(server, ":") - if len(items) != 2 { - return nil, errors.Errorf("invalid server '%s'", server) - } - _, err = strconv.Atoi(items[1]) + serverInfo, err := meta.ConvertAddressToAgentInfo(server) if err != nil { - return nil, errors.Wrapf(err, "invalid server '%s' port '%s'", server, items[1]) + return nil, err } - serversWithRpcPort = append(serversWithRpcPort, [2]string{items[0], items[1]}) + serversWithRpcPort = append(serversWithRpcPort, serverInfo) } log.Infof("get servers from ob.conf %v", serversWithRpcPort) return diff --git a/agent/executor/ob/init.go b/agent/executor/ob/init.go index a517f660..b8727fa2 100644 --- a/agent/executor/ob/init.go +++ b/agent/executor/ob/init.go @@ -20,6 +20,7 @@ import ( "github.com/oceanbase/obshell/agent/constant" "github.com/oceanbase/obshell/agent/engine/task" "github.com/oceanbase/obshell/agent/executor/script" + "github.com/oceanbase/obshell/agent/lib/binary" "github.com/oceanbase/obshell/param" ) @@ -36,12 +37,24 @@ func CreateInitDag(param param.ObInitParam) (*task.DagDetailDTO, error) { AddTask(newStartObServerTask(), true). AddTask(newClusterBoostrapTask(), false). AddTask(newMigrateTableTask(), false). - AddTask(newModifyPwdTask(), false). - AddTask(newMigrateDataTask(), false). + AddTask(newModifyPwdTask(), false) + if param.CreateProxyroUser { + createUserNode, err := newCreateDefaultUserNode(param.ProxyroPassword) + if err != nil { + return nil, err + } + builder.AddNode(createUserNode) + } + builder.AddTask(newMigrateDataTask(), false). AddTemplate(newConvertClusterTemplate()) if param.ImportScript { builder.AddNode(script.NewImportScriptForTenantNode(false)) } + obVersion, isCommunityEdition, _ := binary.GetMyOBVersion() // ignore the error + if obVersion > OB_VERSION_4_3_5_2 && isCommunityEdition { + builder.AddTask(newPostInitClusterTask(), false) + } + template := builder.AddTask(newAgentSyncTask(), true).Build() ctx := task.NewTaskContext(). @@ -54,3 +67,28 @@ func CreateInitDag(param param.ObInitParam) (*task.DagDetailDTO, error) { } return task.NewDagDetailDTO(dag), nil } + +type PostInitClusterTask struct { + task.Task +} + +func newPostInitClusterTask() *PostInitClusterTask { + newTask := &PostInitClusterTask{ + Task: *task.NewSubTask(TASK_NAME_POST_INIT_CLUSTER), + } + newTask.SetCanCancel().SetCanContinue().SetCanRetry().SetCanRollback() + return newTask +} + +func (t *PostInitClusterTask) Execute() error { + t.ExecuteLog("post init cluster") + // Set parameter 'global_index_auto_split_policy' to 'ALL' + // Ignore the error, because it won't affect the cluster initialization + obclusterService.SetParameter( + param.SetParameterParam{ + Name: constant.PARAMETER_GLOBAL_INDEX_AUTO_SPLIT_POLICY, + Value: "ALL", + }, + ) + return nil +} diff --git a/agent/executor/ob/minor_freeze.go b/agent/executor/ob/minor_freeze.go index bafdb0ea..992cab3a 100644 --- a/agent/executor/ob/minor_freeze.go +++ b/agent/executor/ob/minor_freeze.go @@ -17,8 +17,6 @@ package ob import ( - "strconv" - "strings" "time" "github.com/oceanbase/obshell/agent/engine/task" @@ -62,10 +60,11 @@ func (t *MinorFreezeTask) GetAllObServer() (servers []oceanbase.OBServer, err er case SCOPE_SERVER: for _, server := range t.scope.Target { - info := strings.Split(server, ":") - ip := info[0] - port, _ := strconv.Atoi(info[1]) - server, err := obclusterService.GetOBServerByAgentInfo(meta.AgentInfo{Ip: ip, Port: port}) + serverInfo, err := meta.ConvertAddressToAgentInfo(server) + if err != nil { + return nil, errors.Wrap(err, "convert address to agent info failed") + } + server, err := obclusterService.GetOBServerByAgentInfo(*serverInfo) if err != nil { return nil, errors.Wrap(err, "get server by agent info failed") } @@ -123,11 +122,11 @@ func (t *MinorFreezeTask) isMinorFreezeOver(servers []oceanbase.OBServer, oldChe // checkpoint_scn is 0, means there is no ls in this server continue } else if checkpointScn > oldCheckpointScn[server] { - t.ExecuteLogf("[server: %s:%d]smallest checkpoint_scn %+v bigger than expired timestamp %+v, check pass ", server.SvrIp, server.SvrPort, checkpointScn, oldCheckpointScn[server]) + t.ExecuteLogf("[server: %s]smallest checkpoint_scn %+v bigger than expired timestamp %+v, check pass ", meta.NewAgentInfo(server.SvrIp, server.SvrPort).String(), checkpointScn, oldCheckpointScn[server]) checkedServer[server] = true continue } else { - t.ExecuteLogf("[server: %s:%d]smallest checkpoint_scn: %+v smaller than expired timestamp %+v, waiting...", server.SvrIp, server.SvrPort, checkpointScn, oldCheckpointScn[server]) + t.ExecuteLogf("[server: %s]smallest checkpoint_scn: %+v smaller than expired timestamp %+v, waiting...", meta.NewAgentInfo(server.SvrIp, server.SvrPort).String(), checkpointScn, oldCheckpointScn[server]) return false, nil } } diff --git a/agent/executor/ob/parameter.go b/agent/executor/ob/parameter.go new file mode 100644 index 00000000..78354c0e --- /dev/null +++ b/agent/executor/ob/parameter.go @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ob + +import ( + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/repository/model/bo" + "github.com/oceanbase/obshell/param" + "github.com/oceanbase/obshell/utils" +) + +func GetAllParameters() ([]bo.ClusterParameter, *errors.OcsAgentError) { + obParameters, err := obclusterService.GetAllUnhiddenParameters() + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + + tenantIdToNameMap, err := tenantService.GetAllNotMetaTenantIdToNameMap() + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + + parametersMap := make(map[string]*bo.ClusterParameter) + for _, obParameter := range obParameters { + if _, exists := parametersMap[obParameter.Name]; !exists { + parametersMap[obParameter.Name] = &bo.ClusterParameter{ + Name: obParameter.Name, + Scope: obParameter.Scope, + EditLevel: obParameter.EditLevel, + DefaultValue: obParameter.DefaultValue, + Section: obParameter.Section, + DataType: obParameter.DataType, + Info: obParameter.Info, + ServerValue: make([]bo.ObParameterValue, 0), + } + } + + var tenantName string + if obParameter.Scope == PARAMETER_SCOPE_TENANT { + var ok bool + if tenantName, ok = tenantIdToNameMap[obParameter.TenantId]; !ok { + continue + } + } + + // Set server value + parametersMap[obParameter.Name].ServerValue = append(parametersMap[obParameter.Name].ServerValue, bo.ObParameterValue{ + SvrIp: obParameter.SvrIp, + SvrPort: obParameter.SvrPort, + Zone: obParameter.Zone, + TenantId: obParameter.TenantId, + TenantName: tenantName, + Value: obParameter.Value, + }) + + if !utils.ContainsString(parametersMap[obParameter.Name].Values, obParameter.Value) { + parametersMap[obParameter.Name].Values = append(parametersMap[obParameter.Name].Values, obParameter.Value) + } + parametersMap[obParameter.Name].IsSingleValue = len(parametersMap[obParameter.Name].Values) == 1 + + // Set tenant value + if obParameter.Scope == PARAMETER_SCOPE_TENANT { + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + if len(parametersMap[obParameter.Name].TenantValue) == 0 { + parametersMap[obParameter.Name].TenantValue = make([]bo.TenantParameterValue, 0) + } + parametersMap[obParameter.Name].TenantValue = append(parametersMap[obParameter.Name].TenantValue, bo.TenantParameterValue{ + TenantId: obParameter.TenantId, + TenantName: tenantName, + Value: obParameter.Value, + }) + } + } + + res := make([]bo.ClusterParameter, 0, len(parametersMap)) + for _, parameter := range parametersMap { + res = append(res, *parameter) + } + + return res, nil + +} + +func SetObclusterParameters(params []param.SetSingleObclusterParameterParam) *errors.OcsAgentError { + if len(params) == 0 { + return nil + } + + for _, param := range params { + if err := checkSetSingleObclusterParameterParam(param); err != nil { + return errors.Occur(errors.ErrBadRequest, err.Error()) + } + } + + for _, param := range params { + setParameterParams := buildSetParameterParam(param) + for _, setParameterParam := range setParameterParams { + if err := obclusterService.SetParameter(setParameterParam); err != nil { + return errors.Occur(errors.ErrBadRequest, err.Error()) + } + } + } + + return nil +} + +func buildSetParameterParam(setSingleObclusterParameterParam param.SetSingleObclusterParameterParam) []param.SetParameterParam { + setParameterParams := make([]param.SetParameterParam, 0) + if setSingleObclusterParameterParam.Scope == PARAMETER_SCOPE_CLUSTER { + if len(setSingleObclusterParameterParam.Zones) != 0 { + for _, zone := range setSingleObclusterParameterParam.Zones { + setParameterParams = append(setParameterParams, param.SetParameterParam{ + Name: setSingleObclusterParameterParam.Name, + Value: setSingleObclusterParameterParam.Value, + Zone: zone, + }) + } + } else if len(setSingleObclusterParameterParam.Servers) != 0 { + for _, server := range setSingleObclusterParameterParam.Servers { + setParameterParams = append(setParameterParams, param.SetParameterParam{ + Name: setSingleObclusterParameterParam.Name, + Value: setSingleObclusterParameterParam.Value, + Server: server, + }) + } + } else { + setParameterParams = append(setParameterParams, param.SetParameterParam{ + Name: setSingleObclusterParameterParam.Name, + Value: setSingleObclusterParameterParam.Value, + }) + } + } else if setSingleObclusterParameterParam.Scope == PARAMETER_SCOPE_TENANT { + if setSingleObclusterParameterParam.AllUserTenant { + setParameterParams = append(setParameterParams, param.SetParameterParam{ + Name: setSingleObclusterParameterParam.Name, + Value: setSingleObclusterParameterParam.Value, + Tenant: "ALL_USER", + }) + } else if len(setSingleObclusterParameterParam.Tenants) != 0 { + for _, tenant := range setSingleObclusterParameterParam.Tenants { + setParameterParams = append(setParameterParams, param.SetParameterParam{ + Name: setSingleObclusterParameterParam.Name, + Value: setSingleObclusterParameterParam.Value, + Tenant: tenant, + }) + } + } else { + setParameterParams = append(setParameterParams, param.SetParameterParam{ + Name: setSingleObclusterParameterParam.Name, + Value: setSingleObclusterParameterParam.Value, + }) + } + } + return setParameterParams +} + +func checkSetSingleObclusterParameterParam(param param.SetSingleObclusterParameterParam) *errors.OcsAgentError { + if param.Scope != PARAMETER_SCOPE_CLUSTER && param.Scope != PARAMETER_SCOPE_TENANT { + return errors.Occur(errors.ErrIllegalArgument, "parameter scope is invalid") + } + if len(param.Zones) != 0 && len(param.Servers) != 0 { + return errors.Occur(errors.ErrIllegalArgument, "parameter zones and servers cannot be set at the same time") + } + if param.Scope == PARAMETER_SCOPE_TENANT { + if len(param.Tenants) != 0 && param.AllUserTenant { + return errors.Occur(errors.ErrIllegalArgument, "parameter tenants and all_user_tenant cannot be set at the same time") + } + // if len(param.Tenants) == 0 && !param.AllUserTenant, set for sys tenant. + } else if param.Scope == PARAMETER_SCOPE_CLUSTER { + if len(param.Tenants) != 0 || param.AllUserTenant { + return errors.Occurf(errors.ErrIllegalArgument, "parameter tenants and all_user_tenant cannot be set when scope is %s", PARAMETER_SCOPE_CLUSTER) + } + } + return nil +} diff --git a/agent/executor/ob/scale_out.go b/agent/executor/ob/scale_out.go index 76f123b7..e4b39e73 100644 --- a/agent/executor/ob/scale_out.go +++ b/agent/executor/ob/scale_out.go @@ -75,7 +75,7 @@ func HandleClusterScaleOut(param param.ClusterScaleOutParam) (*task.DagDetailDTO } // check ob version is consistent - if obVersion, err := binary.GetMyOBVersion(); err != nil { + if obVersion, _, err := binary.GetMyOBVersion(); err != nil { return nil, errors.Occurf(errors.ErrUnexpected, "get ob version failed: %s", err.Error()) } else if obVersion != agent.OBVersion { return nil, errors.Occurf(errors.ErrBadRequest, "ob version is not consistent between %s(%s) and %s(%s)", @@ -104,11 +104,23 @@ func HandleClusterScaleOut(param param.ClusterScaleOutParam) (*task.DagDetailDTO return nil, errors.Occur(errors.ErrUnexpected, err.Error()) } + var rpcPort int + rpcPortStr, ok := param.ObConfigs[constant.CONFIG_RPC_PORT] + if ok { + var err error + if rpcPort, err = strconv.Atoi(rpcPortStr); err != nil { + return nil, errors.Occur(errors.ErrIllegalArgument, "rpc_port is not a number") + } + } else { + rpcPort = constant.DEFAULT_RPC_PORT + } + srvInfo := meta.NewAgentInfo(param.AgentInfo.Ip, rpcPort) + // Check the server is not already in the cluster. - if exist, err := obclusterService.IsServerExist(param.AgentInfo.Ip, param.ObConfigs[constant.CONFIG_RPC_PORT]); err != nil { + if exist, err := obclusterService.IsServerExist(*srvInfo); err != nil { return nil, errors.Occur(errors.ErrUnexpected, err.Error()) } else if exist { - return nil, errors.Occurf(errors.ErrBadRequest, "server %s:%s already exists in the cluster", param.AgentInfo.Ip, param.ObConfigs[constant.CONFIG_RPC_PORT]) + return nil, errors.Occurf(errors.ErrBadRequest, "server %s already exists in the cluster", srvInfo.String()) } // Create Cluster Scale Out Dag @@ -157,8 +169,14 @@ func CreateClusterScaleOutDag(param param.ClusterScaleOutParam, targetVersion st if err != nil { return nil, errors.Wrap(err, "check zone exist failed") } + // get target agent pk + encryptAgentPassword, err := secure.EncryptForAgent(param.TargetAgentPassword, ¶m.AgentInfo) + if err != nil { + return nil, errors.Wrap(err, "encrypt agent password failed") + } + template := buildClusterScaleOutTaskTemplate(param, !isZoneExist) - context := buildClusterScaleOutDagContext(param, !isZoneExist, targetVersion) + context := buildClusterScaleOutDagContext(param, !isZoneExist, targetVersion, encryptAgentPassword) dag, err := clusterTaskService.CreateDagInstanceByTemplate(template, context) if err != nil { return nil, errors.Wrap(err, "create dag instance failed") @@ -233,13 +251,14 @@ func buildLocalScaleOutTaskTemplate(param param.LocalScaleOutParam) *task.Templa Build() } -func buildClusterScaleOutDagContext(param param.ClusterScaleOutParam, isNewZone bool, targetVersion string) *task.TaskContext { +func buildClusterScaleOutDagContext(param param.ClusterScaleOutParam, isNewZone bool, targetVersion string, targetAgentPassword string) *task.TaskContext { context := task.NewTaskContext(). SetParam(PARAM_ZONE, param.Zone). SetParam(PARAM_IS_NEW_ZONE, isNewZone). SetParam(PARAM_AGENT_INFO, param.AgentInfo). SetParam(PARAM_CONFIG, param.ObConfigs). - SetParam(PARAM_TARGET_AGENT_VERSION, targetVersion) + SetParam(PARAM_TARGET_AGENT_VERSION, targetVersion). + SetParam(PARAM_TARGET_AGENT_PASSWORD, targetAgentPassword) return context } @@ -726,6 +745,7 @@ func (t *IntegrateSingleObConfigTask) Execute() error { type CreateLocalScaleOutDagTask struct { scaleCoordinateTask + targetAgentPassword string } func newCreateLocalScaleOutDagTask() *CreateLocalScaleOutDagTask { @@ -741,6 +761,9 @@ func (t *CreateLocalScaleOutDagTask) Execute() error { if err := t.GetContext().GetParamWithValue(PARAM_AGENT_INFO, &agentInfo); err != nil { return errors.Wrap(err, "get agent info failed") } + if err := t.GetContext().GetParamWithValue(PARAM_TARGET_AGENT_PASSWORD, &t.targetAgentPassword); err != nil { + return errors.Wrap(err, "get target agent password failed") + } // Send rpc to target agent. param, err := t.buildLocalScaleOutParam() if err != nil { @@ -752,7 +775,7 @@ func (t *CreateLocalScaleOutDagTask) Execute() error { } var resp LocalScaleOutResp - if err := secure.SendPostRequest(&agentInfo, constant.URI_OB_RPC_PREFIX+constant.URI_SCALE_OUT, param, &resp); err != nil { + if err := secure.SendRequestWithPassword(&agentInfo, constant.URI_OB_RPC_PREFIX+constant.URI_SCALE_OUT, http.POST, t.targetAgentPassword, param, &resp); err != nil { return errors.Wrap(err, "send scale out rpc to target agent failed") } t.ExecuteLogf("create local scale out dag success, genericID:%s", resp.GenericID) @@ -1207,9 +1230,15 @@ func (t *AddServerTask) Execute() error { return errors.New("get zone failed") } - err := obclusterService.AddServer(agentInfo.Ip, configs[constant.CONFIG_RPC_PORT], zone) + port, err := strconv.Atoi(configs[constant.CONFIG_RPC_PORT]) + if err != nil { + return errors.Wrap(err, "convert port to integer failed") + } + + serverInfo := meta.NewAgentInfo(agentInfo.Ip, port) + err = obclusterService.AddServer(*serverInfo, zone) if err != nil { - return errors.Errorf("add server %s:%s failed", agentInfo.Ip, configs[constant.CONFIG_RPC_PORT]) + return errors.Errorf("add server %s failed", serverInfo.String()) } t.GetContext().SetParam(PARAM_ADD_SERVER_SUCCEED, true) @@ -1248,17 +1277,23 @@ func (t *AddServerTask) Rollback() error { return errors.New("get zone failed") } + port, err := strconv.Atoi(configs[constant.CONFIG_RPC_PORT]) + if err != nil { + return errors.Wrap(err, "convert rpc port to integer failed") + } + serverInfo := meta.NewAgentInfo(agentInfo.Ip, port) + // Check whether addserver task execute successfully. - exist, err := obclusterService.IsServerExistWithZone(agentInfo.Ip, configs[constant.CONFIG_RPC_PORT], zone) + exist, err := obclusterService.IsServerExistWithZone(*serverInfo, zone) if err != nil { - return errors.Errorf("check server %s:%s exist failed", agentInfo.Ip, configs[constant.CONFIG_RPC_PORT]) + return errors.Errorf("check server %s exist failed", agentInfo.String()) } if !exist { return nil } - if err = obclusterService.DeleteServerInZone(agentInfo.Ip, configs[constant.CONFIG_RPC_PORT], zone); err != nil { - return errors.Errorf("delete server %s:%s failed", agentInfo.Ip, configs[constant.CONFIG_RPC_PORT]) + if err = obclusterService.DeleteServerInZone(*serverInfo, zone); err != nil { + return errors.Errorf("delete server %s failed", serverInfo.String()) } return nil } diff --git a/agent/executor/ob/start.go b/agent/executor/ob/start.go index 85803921..b38304a4 100644 --- a/agent/executor/ob/start.go +++ b/agent/executor/ob/start.go @@ -248,6 +248,6 @@ func sendGetDagDetailRequest(id string) (*task.DagDetailDTO, error) { } func getDagGenericIDBySubTaskId(id int64) (string, error) { - dagID, err := localTaskService.GetDagIDBySubTaskId(id) - return task.ConvertLocalIDToGenericID(dagID), err + dag, err := localTaskService.GetDagBySubTaskId(id) + return task.ConvertLocalIDToGenericID(dag.GetID(), dag.GetDagType()), err } diff --git a/agent/executor/ob/start_obsvr.go b/agent/executor/ob/start_obsvr.go index aa44f492..71a24328 100644 --- a/agent/executor/ob/start_obsvr.go +++ b/agent/executor/ob/start_obsvr.go @@ -126,7 +126,11 @@ func (t *StartObserverTask) observerHealthCheck(mysqlPort int) error { for retryCount := 1; retryCount <= maxRetries; retryCount++ { time.Sleep(retryInterval) - t.ExecuteLogf("observer health check, retry [%d/%d]", retryCount, maxRetries) + if retryCount%10 == 0 { + t.TimeoutCheck() + } else { + t.ExecuteLogf("observer health check, retry [%d/%d]", retryCount, maxRetries) + } // Check if the observer process exists if exist, err := process.CheckObserverProcess(); !exist || err != nil { @@ -275,6 +279,7 @@ func fillStartConfig(config map[string]string) { func generateStartOpitonCmd(config map[string]string) string { cmd := "" + agentIp := config[constant.CONFIG_LOCAL_IP] for name, value := range startOptionsMap { if val, ok := config[name]; ok { if name == constant.CONFIG_RS_LIST { @@ -285,6 +290,10 @@ func generateStartOpitonCmd(config map[string]string) string { delete(config, name) } } + + if meta.NewAgentInfo(agentIp, 0).IsIPv6() { + cmd += "--ipv6 " + } return cmd } @@ -495,14 +504,15 @@ func (t *CheckObserverForStartTask) checkObsvrProcConfig() error { func (t *AlterStartServerTask) Execute() error { t.ExecuteInfoLog("exec start server sql") - conf, err := observerService.GetObConfigByName(constant.CONFIG_RPC_PORT) - if err != nil { + var rpcPort int + if err := observerService.GetObConfigValueByName(constant.CONFIG_RPC_PORT, &rpcPort); err != nil { return errors.Wrap(err, "get rpc port failed") } if err := getOceanbaseInstance(); err != nil { return err } - sql := fmt.Sprintf("alter system start server '%s:%s'", meta.OCS_AGENT.GetIp(), conf.Value) + + sql := fmt.Sprintf("alter system start server '%s'", meta.NewAgentInfo(meta.OCS_AGENT.GetIp(), rpcPort).String()) log.Info(sql) if err := obclusterService.ExecuteSql(sql); err != nil { return errors.Wrap(err, "alter start server failed") diff --git a/agent/executor/ob/stop.go b/agent/executor/ob/stop.go index 893b2d3a..5509697c 100644 --- a/agent/executor/ob/stop.go +++ b/agent/executor/ob/stop.go @@ -18,8 +18,6 @@ package ob import ( "fmt" - "strconv" - "strings" log "github.com/sirupsen/logrus" @@ -239,12 +237,14 @@ func (t *ExecStopSqlTask) stopServer() (err error) { } for _, server := range t.scope.Target { t.ExecuteLogf("Stop %s", server) - info := strings.Split(server, ":") - ip := info[0] - port, _ := strconv.Atoi(info[1]) + agentInfo, err := meta.ConvertAddressToAgentInfo(server) + if err != nil { + return errors.Errorf("convert server '%s' to agent info failed: %v", server, err) + } for _, agent := range agents { - if ip == agent.Ip && port == agent.Port { - sql := fmt.Sprintf("alter system stop server '%s:%d'", ip, agent.RpcPort) + if agentInfo.Ip == agent.Ip && agentInfo.Port == agent.Port { + serverInfo := meta.NewAgentInfo(agent.Ip, agent.RpcPort) + sql := fmt.Sprintf("alter system stop server '%s'", serverInfo.String()) log.Info(sql) if err = obclusterService.ExecuteSql(sql); err != nil { return err diff --git a/agent/executor/ob/stop_obsvr.go b/agent/executor/ob/stop_obsvr.go index 71731569..f7a0c9fe 100644 --- a/agent/executor/ob/stop_obsvr.go +++ b/agent/executor/ob/stop_obsvr.go @@ -19,8 +19,6 @@ package ob import ( "fmt" "os/exec" - "strconv" - "strings" "time" log "github.com/sirupsen/logrus" @@ -251,15 +249,13 @@ func GenerateTargetAgentList(scope param.Scope) ([]meta.AgentInfo, error) { } case SCOPE_SERVER: for _, server := range scope.Target { - var info meta.AgentInfo - info.Ip = server[0:strings.LastIndex(server, ":")] - info.Port, err = strconv.Atoi(server[strings.LastIndex(server, ":")+1:]) + info, err := meta.ConvertAddressToAgentInfo(server) if err != nil { log.WithError(err).Errorf("parse server '%s' failed", server) return nil, err } - targetAgents = append(targetAgents, info) + targetAgents = append(targetAgents, *info) } } return targetAgents, nil diff --git a/agent/executor/ob/unit_config_limit.go b/agent/executor/ob/unit_config_limit.go new file mode 100644 index 00000000..fe9facc5 --- /dev/null +++ b/agent/executor/ob/unit_config_limit.go @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ob + +import ( + "strconv" + + log "github.com/sirupsen/logrus" + + "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/lib/parse" + "github.com/oceanbase/obshell/param" +) + +func GetClusterUnitSpecLimit() *param.ClusterUnitConfigLimit { + minMemory, err := obclusterService.GetParameterByName(constant.PARAMETER_MIN_FULL_RESOURCE_POOL_MEMORY) + if err != nil { + log.Warnf("get %s failed, err: %s", constant.PARAMETER_MIN_FULL_RESOURCE_POOL_MEMORY, err.Error()) + return nil + } + var unitSpecLimit param.ClusterUnitConfigLimit + if minMemory != nil { + minMemoryValue, err := strconv.Atoi(minMemory.Value) + if err != nil { + log.Warnf("convert %s to int failed, err: %s", minMemory.Value, err.Error()) + return nil + } + unitSpecLimit.MinMemory = float64(minMemoryValue) / parse.GB + } + unitSpecLimit.MinCpu = 1 + return &unitSpecLimit +} diff --git a/agent/executor/ob/update_agents.go b/agent/executor/ob/update_agents.go index 3ecf3b86..94dc57fd 100644 --- a/agent/executor/ob/update_agents.go +++ b/agent/executor/ob/update_agents.go @@ -49,7 +49,7 @@ func (t *UpdateAllAgentsTask) Execute() error { } for _, agent := range agents { - t.ExecuteLogf("convert agent %s:%d to cluster agent", agent.GetIp(), agent.GetPort()) + t.ExecuteLogf("convert agent %s to cluster agent", agent.String()) if err := agentService.ConvertToClusterAgent(&agent); err != nil { return err } diff --git a/agent/executor/ob/upgrade_agent_check.go b/agent/executor/ob/upgrade_agent_check.go index 7f5d4d69..8a4355cb 100644 --- a/agent/executor/ob/upgrade_agent_check.go +++ b/agent/executor/ob/upgrade_agent_check.go @@ -25,10 +25,13 @@ import ( log "github.com/sirupsen/logrus" "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/engine/coordinator" "github.com/oceanbase/obshell/agent/engine/task" "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/lib/http" "github.com/oceanbase/obshell/agent/lib/pkg" "github.com/oceanbase/obshell/agent/meta" + "github.com/oceanbase/obshell/agent/secure" "github.com/oceanbase/obshell/param" "github.com/oceanbase/obshell/utils" ) @@ -58,6 +61,30 @@ func preCheckForAgentUpgrade(param param.UpgradeCheckParam) (agentErr *errors.Oc if !meta.OCS_AGENT.IsClusterAgent() { return errors.Occur(errors.ErrObclusterNotFound, "Cannot be upgraded. Please confirm if the OBcluster has been initialized and is maintained by obshell.") } + allAgents, err := agentService.GetAllAgentsInfoFromOB() + if err != nil { + return errors.Occur(errors.ErrUnexpected, "Failed to query all agents from ob") + } + agentInfo := coordinator.OCS_COORDINATOR.Maintainer + agentsStatus := make(map[string]http.AgentStatus) + resErr := secure.SendGetRequest(agentInfo, "/api/v1/agents/status", nil, &agentsStatus) + if resErr != nil { + return errors.Occur(errors.ErrUnexpected, "Failed to query all agents status") + } + unavailableAgents := make([]string, 0) + for agent, agentStatus := range agentsStatus { + if agentStatus.State != 2 { + unavailableAgents = append(unavailableAgents, agent) + } + } + for _, agent := range allAgents { + if _, ok := agentsStatus[agent.String()]; !ok { + unavailableAgents = append(unavailableAgents, agent.String()) + } + } + if len(unavailableAgents) > 0 { + return errors.Occur(errors.ErrUnexpected, fmt.Sprintf("Found agent %s not running", strings.Join(unavailableAgents, ","))) + } if err := checkUpgradeDir(¶m.UpgradeDir); err != nil { return errors.Occur(errors.ErrIllegalArgument, err) } @@ -71,7 +98,7 @@ func preCheckForAgentUpgrade(param param.UpgradeCheckParam) (agentErr *errors.Oc } func checkTargetVersionSupport(version, release string) error { - buildNumber, _, err := splitRelease(release) + buildNumber, _, err := pkg.SplitRelease(release) if err != nil { return err } @@ -90,7 +117,7 @@ func findTargetPkg(version, release string) error { return err } var errs []error - buildNumber, distribution, _ := splitRelease(release) + buildNumber, distribution, _ := pkg.SplitRelease(release) for _, arch := range archList { _, err := obclusterService.GetUpgradePkgInfoByVersionAndRelease(constant.PKG_OBSHELL, version, buildNumber, distribution, arch) if err != nil { @@ -106,7 +133,7 @@ func findTargetPkg(version, release string) error { func buildAgentUpgradeCheckTaskContext(param param.UpgradeCheckParam, agents []meta.AgentInfo) *task.TaskContext { ctx := task.NewTaskContext() - buildNumber, distribution, _ := splitRelease(param.Release) + buildNumber, distribution, _ := pkg.SplitRelease(param.Release) taskTime := strconv.Itoa(int(time.Now().UnixMilli())) ctx.SetParam(PARAM_ALL_AGENTS, agents). SetParam(task.EXECUTE_AGENTS, agents). diff --git a/agent/executor/ob/upgrade_ob.go b/agent/executor/ob/upgrade_ob.go index eb0a7913..5998e3b1 100644 --- a/agent/executor/ob/upgrade_ob.go +++ b/agent/executor/ob/upgrade_ob.go @@ -24,10 +24,14 @@ import ( log "github.com/sirupsen/logrus" + "github.com/oceanbase/obshell/agent/engine/coordinator" "github.com/oceanbase/obshell/agent/engine/task" "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/lib/http" + "github.com/oceanbase/obshell/agent/lib/pkg" "github.com/oceanbase/obshell/agent/meta" "github.com/oceanbase/obshell/agent/repository/model/oceanbase" + "github.com/oceanbase/obshell/agent/secure" "github.com/oceanbase/obshell/param" ) @@ -74,7 +78,7 @@ func CheckAndUpgradeOb(param param.ObUpgradeParam) (*task.DagDetailDTO, *errors. func buildCheckAndUpgradeObTaskContext(p *obUpgradeParams) *task.TaskContext { ctx := task.NewTaskContext() - buildNumber, distribution, _ := splitRelease(p.RequestParam.Release) + buildNumber, distribution, _ := pkg.SplitRelease(p.RequestParam.Release) taskTime := strconv.Itoa(int(time.Now().UnixMilli())) ctx.SetParam(PARAM_ALL_AGENTS, p.agents). SetParam(PARAM_UPGRADE_DIR, p.RequestParam.UpgradeDir). @@ -250,7 +254,37 @@ func preCheckForObUpgrade(param param.ObUpgradeParam) (p *obUpgradeParams, err * if !meta.OCS_AGENT.IsClusterAgent() { return nil, errors.Occur(errors.ErrObclusterNotFound, "Cannot be upgraded. Please execute `init` first.") } - + allAgents, agentErr := agentService.GetAllAgentsInfoFromOB() + if agentErr != nil { + return nil, errors.Occur(errors.ErrUnexpected, "Failed to query all agents from ob") + } + agentInfo := coordinator.OCS_COORDINATOR.Maintainer + agentsStatus := make(map[string]http.AgentStatus) + resErr := secure.SendGetRequest(agentInfo, "/api/v1/agents/status", nil, &agentsStatus) + if resErr != nil { + return nil, errors.Occur(errors.ErrUnexpected, "Failed to query all agents status") + } + unavailableAgents := make([]string, 0) + unavailableObservers := make([]string, 0) + for agent, agentStatus := range agentsStatus { + if agentStatus.State != 2 { + unavailableAgents = append(unavailableAgents, agent) + } + if agentStatus.OBState != 3 { + unavailableObservers = append(unavailableObservers, fmt.Sprintf("%s:%d", agentStatus.Agent.GetIp(), agentStatus.SqlPort)) + } + } + for _, agent := range allAgents { + if _, ok := agentsStatus[agent.String()]; !ok { + unavailableAgents = append(unavailableAgents, agent.String()) + } + } + if len(unavailableAgents) > 0 { + return nil, errors.Occur(errors.ErrUnexpected, fmt.Sprintf("Found agent %s not running", strings.Join(unavailableAgents, ","))) + } + if len(unavailableObservers) > 0 { + return nil, errors.Occur(errors.ErrUnexpected, fmt.Sprintf("Found observer %s not running", strings.Join(unavailableObservers, ","))) + } currentBuildVersion, e := obclusterService.GetObBuildVersion() if e != nil { return nil, errors.Occur(errors.ErrUnexpected, e) diff --git a/agent/executor/ob/upgrade_ob_check.go b/agent/executor/ob/upgrade_ob_check.go index f37c7168..7144c69f 100644 --- a/agent/executor/ob/upgrade_ob_check.go +++ b/agent/executor/ob/upgrade_ob_check.go @@ -68,7 +68,7 @@ func ObUpgradeCheck(param param.UpgradeCheckParam) (*task.DagDetailDTO, *errors. func buildObUpgradeCheckTaskContext(param param.UpgradeCheckParam, upgradeRoute []RouteNode, agents []meta.AgentInfo) *task.TaskContext { ctx := task.NewTaskContext() - buildNumer, distribution, _ := splitRelease(param.Release) + buildNumer, distribution, _ := pkg.SplitRelease(param.Release) taskTime := strconv.Itoa(int(time.Now().UnixMilli())) ctx.SetParam(task.EXECUTE_AGENTS, agents). SetParam(PARAM_ALL_AGENTS, agents). @@ -133,26 +133,12 @@ func preCheckForObUpgradeCheck(param param.UpgradeCheckParam) (upgradeRoute []Ro return upgradeRoute, nil } -func splitRelease(release string) (buildNumber, distribution string, err error) { - releaseSplit := strings.Split(release, ".") - if len(releaseSplit) < 2 { - return "", "", fmt.Errorf("release format %s is illegal", release) - } - buildNumber = releaseSplit[0] - distribution = releaseSplit[len(releaseSplit)-1] - return -} - -func checkForAllRequiredPkgs(targetVersion, targetRelease string) ([]RouteNode, error) { +func getTargetObUpgradeDepYaml(targetVersion string, targetRelease string) ([]RouteNode, error) { // Param 'targetRelease' is like '***.**.el7'. - targetBuildNumber, targetDistribution, err := splitRelease(targetRelease) + targetBuildNumber, _, err := pkg.SplitRelease(targetRelease) if err != nil { return nil, err } - targetBV := fmt.Sprintf("%s-%s", targetVersion, targetBuildNumber) - if err = checkTargetOBVersionSupport(targetBV); err != nil { - return nil, err - } log.Info("get target pkg info") pkgInfo, err := obclusterService.GetUpgradePkgInfoByVersionAndReleaseDist(constant.PKG_OCEANBASE_CE, targetVersion, targetRelease, global.Architecture) @@ -168,6 +154,25 @@ func checkForAllRequiredPkgs(targetVersion, targetRelease string) ([]RouteNode, upgradeRoute[len(upgradeRoute)-1].Release = targetBuildNumber upgradeRoute[len(upgradeRoute)-1].BuildVersion = fmt.Sprintf("%s-%s", targetVersion, targetBuildNumber) log.Infof("upgrade route: %v", upgradeRoute) + return upgradeRoute, nil +} + +func checkForAllRequiredPkgs(targetVersion, targetRelease string) ([]RouteNode, error) { + // Param 'targetRelease' is like '***.**.el7'. + targetBuildNumber, targetDistribution, err := pkg.SplitRelease(targetRelease) + if err != nil { + return nil, err + } + + targetBV := fmt.Sprintf("%s-%s", targetVersion, targetBuildNumber) + if err = checkTargetOBVersionSupport(targetBV); err != nil { + return nil, err + } + + upgradeRoute, err := getTargetObUpgradeDepYaml(targetVersion, targetRelease) + if err != nil { + return nil, err + } log.Info("check for all required pkgs") if err = checkForAllRequiredPkgsExist(upgradeRoute, targetDistribution); err != nil { diff --git a/agent/executor/ob/upgrade_pkg_info.go b/agent/executor/ob/upgrade_pkg_info.go new file mode 100644 index 00000000..b194d31d --- /dev/null +++ b/agent/executor/ob/upgrade_pkg_info.go @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ob + +import ( + "fmt" + + log "github.com/sirupsen/logrus" + + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/repository/model/bo" +) + +func GetAllUpgradePkgInfos() ([]bo.UpgradePkgInfo, *errors.OcsAgentError) { + upgradePkgInfos, err := obclusterService.GetAllUpgradePkgInfos() + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err) + } + log.Infof("Get all upgrade pkg infos: %v", upgradePkgInfos) + infos := make([]bo.UpgradePkgInfo, 0) + onlyMap := make(map[string]bool) + for i := len(upgradePkgInfos) - 1; i >= 0; i-- { + onlyFlag := fmt.Sprintf("%s-%s-%s.%s", upgradePkgInfos[i].Name, upgradePkgInfos[i].Version, upgradePkgInfos[i].ReleaseDistribution, upgradePkgInfos[i].Architecture) + if _, ok := onlyMap[onlyFlag]; !ok { + infos = append(infos, upgradePkgInfos[i].ToBO()) + onlyMap[onlyFlag] = true + } + } + + return infos, nil +} + +func GetObPackageUpgradeDepYaml(version string, release string) ([]RouteNode, *errors.OcsAgentError) { + upgradeRoute, err := getTargetObUpgradeDepYaml(version, release) + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err) + } + if upgradeRoute == nil { + return nil, errors.Occur(errors.ErrUnexpected, "No upgrade route found") + } + return upgradeRoute[1:], nil +} diff --git a/agent/executor/ob/upgrade_pkg_install.go b/agent/executor/ob/upgrade_pkg_install.go index b77c23cd..022b13b3 100644 --- a/agent/executor/ob/upgrade_pkg_install.go +++ b/agent/executor/ob/upgrade_pkg_install.go @@ -18,20 +18,16 @@ package ob import ( "fmt" - "io" "os" "os/exec" "path" - "path/filepath" - "github.com/cavaliergopher/cpio" - "github.com/cavaliergopher/rpm" log "github.com/sirupsen/logrus" - "github.com/ulikunitz/xz" "github.com/oceanbase/obshell/agent/constant" "github.com/oceanbase/obshell/agent/engine/task" "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/lib/pkg" "github.com/oceanbase/obshell/agent/lib/system" ) @@ -108,7 +104,7 @@ func (t *InstallAllRequiredPkgsTask) installAllRequiredPkgs() (err error) { continue } t.ExecuteLogf("Unpack '%s'", rpmPkgInfo.RpmPkgPath) - if err = InstallRpmPkgInPlace(rpmPkgInfo.RpmPkgPath); err != nil { + if err = pkg.InstallRpmPkgInPlace(rpmPkgInfo.RpmPkgPath); err != nil { success = false t.ExecuteErrorLog(err) continue @@ -156,92 +152,6 @@ func (t *InstallAllRequiredPkgsTask) getAgentVersion(rpmPkgInfo *rpmPacakgeInsta return nil } -func InstallRpmPkgInPlace(path string) (err error) { - log.Infof("InstallRpmPkg: %s", path) - f, err := os.Open(path) - if err != nil { - return - } - defer f.Close() - - pkg, err := rpm.Read(f) - if err != nil { - return - } - if err = checkCompressAndFormat(pkg); err != nil { - return - } - - xzReader, err := xz.NewReader(f) - if err != nil { - return - } - installPath := filepath.Dir(path) - cpioReader := cpio.NewReader(xzReader) - - for { - hdr, err := cpioReader.Next() - if err == io.EOF { - break - } - if err != nil { - return err - } - - m := hdr.Mode - if m.IsDir() { - dest := filepath.Join(installPath, hdr.Name) - log.Infof("%s is a directory, creating %s", hdr.Name, dest) - if err := os.MkdirAll(dest, 0755); err != nil { - return errors.Wrapf(err, "mkdir failed %s", hdr.Name) - } - - } else if m.IsRegular() { - if err := handleRegularFile(hdr, cpioReader, installPath); err != nil { - return err - } - - } else if hdr.Linkname != "" { - if err := handleSymlink(hdr, installPath); err != nil { - return err - } - } else { - log.Infof("Skipping unsupported file %s type: %v", hdr.Name, m) - } - } - - return nil -} - -func handleRegularFile(hdr *cpio.Header, cpioReader *cpio.Reader, installPath string) error { - dest := filepath.Join(installPath, hdr.Name) - if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil { - log.WithError(err).Error("mkdir failed") - return err - } - - outFile, err := os.Create(dest) - if err != nil { - return err - } - defer outFile.Close() - - log.Infof("Extracting %s", hdr.Name) - if _, err := io.Copy(outFile, cpioReader); err != nil { - return err - } - return nil -} - -func handleSymlink(hdr *cpio.Header, installPath string) error { - dest := filepath.Join(installPath, hdr.Name) - if err := os.Symlink(hdr.Linkname, dest); err != nil { - return errors.Wrapf(err, "create symlink failed %s -> %s", dest, hdr.Linkname) - } - log.Infof("Creating symlink %s -> %s", dest, hdr.Linkname) - return nil -} - func (t *InstallAllRequiredPkgsTask) checkObserverBinAvailable(pkgInfo rpmPacakgeInstallInfo) (err error) { t.ExecuteLog("Check if the observer binary is available.") observerBinPath := path.Join(pkgInfo.RpmPkgHomepath, constant.DIR_BIN, constant.PROC_OBSERVER) diff --git a/agent/executor/ob/upgrade_pkg_upload.go b/agent/executor/ob/upgrade_pkg_upload.go index fb1051eb..7a82db8e 100644 --- a/agent/executor/ob/upgrade_pkg_upload.go +++ b/agent/executor/ob/upgrade_pkg_upload.go @@ -144,7 +144,7 @@ func (r *upgradeRpmPkgInfo) fileCheck() (err error) { func (r *upgradeRpmPkgInfo) checkVersion() (err error) { log.Info("version is ", r.version) - r.release, r.distribution, err = splitRelease(r.rpmPkg.Release()) + r.release, r.distribution, err = pkg.SplitRelease(r.rpmPkg.Release()) if err != nil { return } @@ -198,19 +198,9 @@ func (r *upgradeRpmPkgInfo) findAllExpectedFiles(expected []string) (err error) return nil } -func checkCompressAndFormat(pkg *rpm.Package) error { - if pkg.PayloadCompression() != "xz" { - return fmt.Errorf("unsupported compression '%s', the supported compression is 'xz'", pkg.PayloadCompression()) - } - if pkg.PayloadFormat() != "cpio" { - return fmt.Errorf("unsupported payload format '%s', the supported payload format is 'cpio'", pkg.PayloadFormat()) - } - return nil -} - func (r *upgradeRpmPkgInfo) GetUpgradeDepYml() (err error) { log.Info("start to get upgrade dep yml") - if err = checkCompressAndFormat(r.rpmPkg); err != nil { + if err = pkg.CheckCompressAndFormat(r.rpmPkg); err != nil { return } xzReader, err := xz.NewReader(r.rpmFile) diff --git a/agent/executor/ob/upgrade_route.go b/agent/executor/ob/upgrade_route.go index be5256bb..6f4037c1 100644 --- a/agent/executor/ob/upgrade_route.go +++ b/agent/executor/ob/upgrade_route.go @@ -56,11 +56,11 @@ type UpgradeRoute struct { } type RouteNode struct { - Version string - Release string - BuildVersion string - RequireFromBinary bool - DeprecatedInfo []string + Version string `json:"version"` + Release string `json:"release"` + BuildVersion string `json:"build_version"` + RequireFromBinary bool `json:"require_from_binary"` + DeprecatedInfo []string `json:"deprecated_info"` } type Repository struct { diff --git a/agent/executor/obproxy/add.go b/agent/executor/obproxy/add.go new file mode 100644 index 00000000..8e7e516e --- /dev/null +++ b/agent/executor/obproxy/add.go @@ -0,0 +1,579 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package obproxy + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" + "syscall" + "time" + + "github.com/oceanbase/obshell/agent/config" + "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/engine/task" + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/lib/process" + "github.com/oceanbase/obshell/agent/meta" + obproxydb "github.com/oceanbase/obshell/agent/repository/db/obproxy" + "github.com/oceanbase/obshell/agent/repository/db/oceanbase" + "github.com/oceanbase/obshell/agent/secure" + "github.com/oceanbase/obshell/param" + "github.com/oceanbase/obshell/utils" + log "github.com/sirupsen/logrus" + "gorm.io/gorm" +) + +type addObproxyOptions struct { + appName string + homePath string + version string + clusterName string // only for "RS_LIST" mode + encryptedSysPwd string + encryptedProxyroPassword string + parameters map[string]string + sqlPort int + exportPort int +} + +func buildAddObproxyOptions(param *param.AddObproxyParam) (*addObproxyOptions, error) { + version, err := getObproxyVersion(param.HomePath) + if err != nil { + return nil, err + } + + options := addObproxyOptions{ + appName: param.Name, + homePath: param.HomePath, + version: version, + parameters: make(map[string]string), + } + + for k, v := range param.Parameters { + options.parameters[k] = v + } + + options.encryptedSysPwd, err = secure.Encrypt(param.ObproxySysPassword) + if err != nil { + return nil, err + } + + options.encryptedProxyroPassword, err = secure.Encrypt(param.ProxyroPassword) + if err != nil { + return nil, err + } + return &options, nil +} + +func AddObproxy(param param.AddObproxyParam) (*task.DagDetailDTO, *errors.OcsAgentError) { + if meta.IsObproxyAgent() { + return nil, errors.Occur(errors.ErrBadRequest, "agent has already managed obproxy") + } + + if err := checkObproxyHomePath(param.HomePath); err != nil { + return nil, errors.Occurf(errors.ErrBadRequest, "invalid obproxy home path: %s", err) + } + + options, err := buildAddObproxyOptions(¶m) + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err) + } + + if err := checkAndFillObproxyPort(¶m, options); err != nil { + return nil, err + } + + // Check obproxy version + if err := checkAndFillObproxyVersion(¶m, options); err != nil { + return nil, err + } + + if err := checkAndFillWorkMode(¶m, options); err != nil { + return nil, err + } + + if rsList, ok := options.parameters[constant.OBPROXY_CONFIG_RS_LIST]; ok && rsList != "" { + if clusterName, err := checkProxyroPasswordAndGetClusterName(rsList, param.ProxyroPassword); err != nil { + return nil, errors.Occur(errors.ErrBadRequest, err) + } else { + options.clusterName = clusterName + log.Infof("cluster name: %s", clusterName) + } + } + + ctx := buildAddObproxyContext(options) + template := buildAddObproxyTemplate(options) + dag, err := localTaskService.CreateDagInstanceByTemplate(template, ctx) + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err) + } + return task.NewDagDetailDTO(dag), nil +} + +func checkAndFillWorkMode(param *param.AddObproxyParam, options *addObproxyOptions) *errors.OcsAgentError { + // Check work mode. + if param.RsList != nil && param.ConfigUrl != nil { + return errors.Occur(errors.ErrBadRequest, "rs_list and config_url can not be specified at the same time") + } + + if param.RsList != nil { + options.parameters[constant.OBPROXY_CONFIG_RS_LIST] = *param.RsList + options.parameters[constant.OBPROXY_CONFIG_CONFIG_SERVER_URL] = "" + } else if param.ConfigUrl != nil { + options.parameters[constant.OBPROXY_CONFIG_CONFIG_SERVER_URL] = *param.ConfigUrl + } else { + if !meta.OCS_AGENT.IsClusterAgent() { + return errors.Occur(errors.ErrBadRequest, "rs_list or config_url must be specified when agent is not cluster agent") + } else { + // Use the rs_list of current ob cluster. + rsListStr, err := obclusterService.GetRsListStr() + if err != nil { + // The observer may be inactive. + return errors.Occur(errors.ErrUnexpected, err) + } + + options.parameters[constant.OBPROXY_CONFIG_RS_LIST] = convertToRootServerList(rsListStr) + options.parameters[constant.OBPROXY_CONFIG_CONFIG_SERVER_URL] = "" + } + } + return nil +} + +func checkObproxyHomePath(homePath string) error { + if err := utils.CheckDirExists(homePath); err != nil { + return err + } + + err := syscall.Access(homePath, syscall.O_RDWR) + if err != nil { + return errors.Errorf("no read/write permission for directory '%s'", homePath) + } + + // Check obproxy is installed. + if err := utils.CheckDirExists(filepath.Join(homePath, constant.OBPROXY_DIR_BIN)); err != nil { + return err + } + if err := utils.CheckDirExists(filepath.Join(homePath, constant.OBPROXY_DIR_LIB)); err != nil { + return err + } + + // Check if obproxy has run in the home path. + entrys, err := os.ReadDir(filepath.Join(homePath, constant.OBPROXY_DIR_ETC)) + if err != nil { + if !os.IsNotExist(err) { + return err + } + } + if len(entrys) != 0 { + return errors.New("obproxy etc directory is not empty") + } + + return nil +} + +// checkObproxyVersion checks the version of obproxy located at the given homePath. +// If the version is lower than the minimum supported version (4.0.0), it returns an error. +func checkAndFillObproxyVersion(param *param.AddObproxyParam, options *addObproxyOptions) *errors.OcsAgentError { + version, err := getObproxyVersion(param.HomePath) + if err != nil { + return errors.Occur(errors.ErrBadRequest, "get obproxy version failed: %v", err) + } + if version < constant.OBPROXY_MIN_VERSION_SUPPORT { + return errors.Occurf(errors.ErrBadRequest, "obproxy version %s is lower than the minimum supported version %s", version, constant.OBPROXY_MIN_VERSION_SUPPORT) + } + options.version = version + return nil +} + +func checkProxyroPasswordAndGetClusterName(rsListStr string, password string) (clusterName string, err error) { + rsList := strings.Split(rsListStr, ";") + dsConfig := config.NewObDataSourceConfig(). + SetTryTimes(1). + SetDBName(constant.DB_OCEANBASE). + SetTimeout(10). + SetPassword(password). + SetUsername(constant.SYS_USER_PROXYRO) + var tempDb *gorm.DB + defer func() { + if tempDb != nil { + oceanbaseDB, _ := tempDb.DB() + oceanbaseDB.Close() + } + }() + for _, rs := range rsList { + observerInfo := meta.NewAgentInfoByString(rs) + if observerInfo == nil { + err = errors.Errorf("invalid observer info: %s", rs) + continue + } + dsConfig.SetIp(observerInfo.GetIp()).SetPort(observerInfo.GetPort()) + tempDb, err = oceanbase.LoadTempOceanbaseInstance(dsConfig) + if err != nil { + continue + } + clusterName, err = obproxyService.GetObclusterName(tempDb) + if err != nil { + continue + } + + return clusterName, nil + } + return "", err +} + +func checkAndFillObproxyPort(param *param.AddObproxyParam, options *addObproxyOptions) *errors.OcsAgentError { + if param.SqlPort != nil { + options.parameters[constant.OBPROXY_CONFIG_LISTEN_PORT] = strconv.Itoa(*param.SqlPort) + } else if options.parameters[constant.OBPROXY_CONFIG_LISTEN_PORT] == "" { + options.parameters[constant.OBPROXY_CONFIG_LISTEN_PORT] = strconv.Itoa(constant.OBPROXY_DEFAULT_SQL_PORT) + } + if param.RpcPort != nil { + options.parameters[constant.OBPROXY_CONFIG_RPC_LISTEN_PORT] = strconv.Itoa(*param.RpcPort) + } else if options.parameters[constant.OBPROXY_CONFIG_RPC_LISTEN_PORT] == "" { + options.parameters[constant.OBPROXY_CONFIG_RPC_LISTEN_PORT] = strconv.Itoa(constant.OBPROXY_DEFAULT_RPC_PORT) + } + if param.ExporterPort != nil { + options.parameters[constant.OBPROXY_CONFIG_PROMETHUES_LISTEN_PORT] = strconv.Itoa(*param.ExporterPort) + } else if options.parameters[constant.OBPROXY_CONFIG_PROMETHUES_LISTEN_PORT] == "" { + options.parameters[constant.OBPROXY_CONFIG_PROMETHUES_LISTEN_PORT] = strconv.Itoa(constant.OBPROXY_DEFAULT_EXPORTER_PORT) + } + + // Check port is valid. + var ports = []string{constant.OBPROXY_CONFIG_LISTEN_PORT, constant.OBPROXY_CONFIG_PROMETHUES_LISTEN_PORT, constant.OBPROXY_CONFIG_RPC_LISTEN_PORT} + for _, port := range ports { + if _, err := strconv.Atoi(options.parameters[port]); err != nil { + return errors.Occur(errors.ErrBadRequest, "invalid port: %s", options.parameters[port]) + } + } + options.sqlPort, _ = strconv.Atoi(options.parameters[constant.OBPROXY_CONFIG_LISTEN_PORT]) + options.exportPort, _ = strconv.Atoi(options.parameters[constant.OBPROXY_CONFIG_PROMETHUES_LISTEN_PORT]) + return nil +} + +func buildAddObproxyContext(options *addObproxyOptions) *task.TaskContext { + ctx := task.NewTaskContext(). + SetParam(PARAM_OBPROXY_HOME_PATH, options.homePath). + SetParam(PARAM_OBPROXY_SQL_PORT, options.sqlPort). + SetParam(PARAM_OBPROXY_EXPORTER_PORT, options.exportPort). + SetParam(PARAM_OBPROXY_APP_NAME, options.appName). + SetParam(PARAM_OBPROXY_VERSION, options.version). + SetParam(PARAM_OBPROXY_CLUSTER_NAME, options.clusterName). + SetParam(PARAM_OBPROXY_SYS_PASSWORD, options.encryptedSysPwd) + return ctx +} + +func buildAddObproxyTemplate(options *addObproxyOptions) *task.Template { + templateBuilder := task.NewTemplateBuilder(DAG_ADD_OBPROXY). + SetType(task.DAG_OBPROXY). + AddNode(newPrepareForObproxyAgentNode(false)). + AddNode(newStartObproxyNode(options.parameters)). + AddNode(NewSetObproxyUserPasswordForObNode(options.encryptedProxyroPassword)). + AddTask(newPersistObproxyInfoTask(), false). + SetMaintenance(task.ObproxyMaintenance()) + return templateBuilder.Build() +} + +func convertToRootServerList(rsListStr string) string { + var result []string + entries := strings.Split(rsListStr, ";") + for _, entry := range entries { + parts := strings.Split(entry, ":") + if len(parts) == 3 { + result = append(result, fmt.Sprintf("%s:%s", parts[0], parts[2])) + } + } + return strings.Join(result, ";") +} + +type StartObproxyTask struct { + task.Task + homePath string + sqlPort int + parameters map[string]string + appName string + optionsStr string + clusterName string + obproxySysPassword string + encryptedSysPwd string + + startWithOption bool +} + +func newStartObproxyNode(parameters map[string]string) *task.Node { + newTask := newStartObproxyTask() + ctx := task.NewTaskContext().SetParam(PARAM_OBPROXY_START_PARAMS, parameters).SetParam(PARAM_OBPROXY_START_WITH_OPTIONS, true) + return task.NewNodeWithContext(newTask, false, ctx) +} + +func newStartObproxyWithoutOptionsNode() *task.Node { + newTask := newStartObproxyTask() + ctx := task.NewTaskContext().SetParam(PARAM_OBPROXY_START_WITH_OPTIONS, false) + return task.NewNodeWithContext(newTask, false, ctx) +} + +func newStartObproxyTask() *StartObproxyTask { + newTask := &StartObproxyTask{ + Task: *task.NewSubTask(TASK_START_OBPROXY), + } + newTask.SetCanContinue(). + SetCanRetry(). + SetCanRollback(). + SetCanCancel(). + SetCanPass() + return newTask +} + +func (t *StartObproxyTask) Execute() error { + var err error + if err = t.GetContext().GetParamWithValue(PARAM_OBPROXY_HOME_PATH, &t.homePath); err != nil { + return err + } + if err = t.GetContext().GetParamWithValue(PARAM_OBPROXY_START_WITH_OPTIONS, &t.startWithOption); err != nil { + return err + } + + var startCmd string + if !t.startWithOption { + startCmd = t.buildAtartObproxyWithoutOptionsCmd(t.homePath) + } else { + if err := t.GetContext().GetParamWithValue(PARAM_OBPROXY_START_PARAMS, &t.parameters); err != nil { + return err + } + if err := t.GetContext().GetParamWithValue(PARAM_OBPROXY_APP_NAME, &t.appName); err != nil { + return err + } + if err := t.GetContext().GetParamWithValue(PARAM_OBPROXY_CLUSTER_NAME, &t.clusterName); err != nil { + return err + } + if err := t.GetContext().GetParamWithValue(PARAM_OBPROXY_SYS_PASSWORD, &t.encryptedSysPwd); err != nil { + return err + } + if err := t.GetContext().GetParamWithValue(PARAM_OBPROXY_SQL_PORT, &t.sqlPort); err != nil { + return err + } + t.obproxySysPassword, err = secure.Decrypt(t.encryptedSysPwd) + if err != nil { + return errors.Errorf("decrypt obproxy sys password failed: %v", err) + } + + if err := t.buildStartOptionStr(); err != nil { + return err + } + + startCmd = fmt.Sprintf("cd %s; ./bin/obproxy -o %s", t.homePath, t.optionsStr) + if t.appName != "" { + startCmd = fmt.Sprintf("%s -n %s", startCmd, t.appName) + } + if t.clusterName != "" { + startCmd = fmt.Sprintf("%s -c %s", startCmd, t.clusterName) + } + } + t.ExecuteLogf("start obproxy cmd: %s", startCmd) + if output, err := exec.Command("/bin/bash", "-c", startCmd).CombinedOutput(); err != nil { + return errors.Errorf("failed to start obproxy: %v, output: %s", err, string(output)) + } + + if err := t.healthCheck(); err != nil { + return errors.Wrap(err, "obproxy start failed") + } + + if pid, err := process.FindPIDByPort(uint32(t.sqlPort)); err != nil { + return errors.Errorf("get obproxy pid failed: %v", err) + } else if err := process.WritePidForce(filepath.Join(t.homePath, constant.OBPROXY_DIR_RUN, "obproxy.pid"), int(pid)); err != nil { + return errors.Errorf("write obproxy pid failed: %v", err) + } + return nil +} + +func (t *StartObproxyTask) buildStartOptionStr() error { + parameters := t.parameters + // Add single quotes to rs_list. + if rsList, ok := parameters[constant.OBPROXY_CONFIG_RS_LIST]; ok && !strings.HasPrefix(rsList, "'") && !strings.HasSuffix(rsList, "'") { + parameters[constant.OBPROXY_CONFIG_RS_LIST] = fmt.Sprintf("'%s'", rsList) + } + + if t.obproxySysPassword != "" { + parameters[constant.OBPROXY_CONFIG_OBPROXY_SYS_PASSWORD] = utils.Sha1(t.obproxySysPassword) + } else { + // If obproxy sys password is empty, do not need to sha1 it. + parameters[constant.OBPROXY_CONFIG_OBPROXY_SYS_PASSWORD] = "" + } + + optionStrs := make([]string, 0, len(parameters)) + for k, v := range parameters { + optionStrs = append(optionStrs, fmt.Sprintf("%s=%s", k, v)) + } + t.optionsStr = strings.Join(optionStrs, ",") + return nil +} + +func (t *StartObproxyTask) buildAtartObproxyWithoutOptionsCmd(homePath string) string { + return fmt.Sprintf("cd %s; ./bin/obproxy", homePath) +} + +func (t *StartObproxyTask) healthCheck() error { + // Try to connect to obproxy to confirm that it has started. + if t.sqlPort == 0 { + t.sqlPort = meta.OBPROXY_SQL_PORT + } + if t.obproxySysPassword == "" { + t.obproxySysPassword = meta.OBPROXY_SYS_PWD + } + t.ExecuteLog("start obproxy health check") + dsConfig := config.NewObproxyDataSourceConfig().SetPort(t.sqlPort).SetPassword(t.obproxySysPassword) + for retryCount := 1; retryCount <= obproxydb.WAIT_OBPROXY_CONNECTED_MAX_TIMES; retryCount++ { + time.Sleep(obproxydb.WAIT_OBPROXY_CONNECTED_MAX_INTERVAL) + if err := obproxydb.LoadObproxyInstanceForHealthCheck(dsConfig); err != nil { + t.ExecuteWarnLogf("obproxy health check failed: %v", err) + if strings.Contains(err.Error(), "connection refused") { + return err + } + continue + } + if err := obproxyService.UpdateSqlPort(t.sqlPort); err != nil { + return errors.Errorf("update obproxy sql port failed: %v", err) + } + if err := obproxyService.UpdateObproxySysPassword(t.obproxySysPassword); err != nil { + return errors.Errorf("update obproxy sys password failed: %v", err) + } + return nil + } + + return errors.New("obproxy health check timeout") +} + +type PersistObproxyInfoTask struct { + task.Task + homePath string + sqlPort int + encryptedSysPwd string + encryptedProxyroPassword string +} + +func newPersistObproxyInfoTask() *PersistObproxyInfoTask { + newTask := &PersistObproxyInfoTask{ + Task: *task.NewSubTask(TASK_PERSIST_OBPROXY_INFP), + } + newTask.SetCanContinue(). + SetCanRetry(). + SetCanCancel(). + SetCanPass() + return newTask +} + +func (t *PersistObproxyInfoTask) Execute() error { + if err := t.GetContext().GetParamWithValue(PARAM_OBPROXY_HOME_PATH, &t.homePath); err != nil { + return err + } + if err := t.GetContext().GetParamWithValue(PARAM_OBPROXY_SQL_PORT, &t.sqlPort); err != nil { + return err + } + if err := t.GetContext().GetParamWithValue(PARAM_OBPROXY_SYS_PASSWORD, &t.encryptedSysPwd); err != nil { + return err + } + if err := t.GetContext().GetParamWithValue(PARAM_OBPROXY_PROXYRO_PASSWORD, &t.encryptedProxyroPassword); err != nil { + return err + } + if err := agentService.AddObproxy(t.homePath, t.sqlPort, t.encryptedSysPwd, t.encryptedProxyroPassword); err != nil { + return err + } + + return nil +} + +type PrepareForAddObproxyTask struct { + task.Task + expectObproxyAgent bool + homePath string +} + +// PrepareForAddObproxyNode will check if the agent is an obproxy agent. +func newPrepareForObproxyAgentNode(expectObproxyAgent bool) *task.Node { + newTask := &PrepareForAddObproxyTask{ + Task: *task.NewSubTask(TASK_CHECK_OBPROXY_STATUS), + } + newTask.SetCanContinue(). + SetCanRetry(). + SetCanCancel(). + SetCanPass() + + ctx := task.NewTaskContext().SetParam(task.FAILURE_EXIT_MAINTENANCE, true).SetParam(PARAM_EXPECT_OBPROXY_AGENT, expectObproxyAgent) + return task.NewNodeWithContext(newTask, false, ctx) +} + +func (t *PrepareForAddObproxyTask) Execute() error { + // Double check if the agent identify. + if err := t.GetContext().GetParamWithValue(PARAM_EXPECT_OBPROXY_AGENT, &t.expectObproxyAgent); err != nil { + return err + } + if err := t.GetContext().GetParamWithValue(PARAM_OBPROXY_HOME_PATH, &t.homePath); err != nil { + return err + } + if t.expectObproxyAgent && !meta.IsObproxyAgent() { + return errors.Errorf("This is not an obproxy agent") + } + if !t.expectObproxyAgent { + if meta.IsObproxyAgent() { + return errors.Errorf("agent has already managed obproxy") + } + // Create obproxy run path + runPath := filepath.Join(t.homePath, constant.OBPROXY_DIR_RUN) + if err := os.MkdirAll(runPath, 0755); err != nil { + return errors.Errorf("create obproxy run path failed: %v", err) + } + } + return nil +} + +// Only support set global proxyro password currently +type SetObproxyUserPasswordForObTask struct { + task.Task + encryptedProxyroPassword string +} + +func NewSetObproxyUserPasswordForObNode(encryptedProxyroPassword string) *task.Node { + newTask := &SetObproxyUserPasswordForObTask{ + Task: *task.NewSubTask(TASK_SET_OBPROXY_USER_PASSWORD), + } + newTask.SetCanContinue(). + SetCanRetry(). + SetCanCancel(). + SetCanPass() + ctx := task.NewTaskContext().SetParam(PARAM_OBPROXY_PROXYRO_PASSWORD, encryptedProxyroPassword) + return task.NewNodeWithContext(newTask, false, ctx) +} + +func (t *SetObproxyUserPasswordForObTask) Execute() error { + if t.GetContext().GetParamWithValue(PARAM_OBPROXY_PROXYRO_PASSWORD, &t.encryptedProxyroPassword) != nil { + return errors.Errorf("get obproxy user password failed") + } + + // Decrypt proxyro password. + proxyroPassword, err := secure.Decrypt(t.encryptedProxyroPassword) + if err != nil { + return errors.Errorf("decrypt proxyro password failed: %v", err) + } + t.ExecuteLog("set obproxy user password") + + if err := obproxyService.SetProxyroPassword(proxyroPassword); err != nil { + return errors.Errorf("set obproxy user password failed: %v", err) + } + return nil +} diff --git a/agent/executor/obproxy/delete.go b/agent/executor/obproxy/delete.go new file mode 100644 index 00000000..e40261cf --- /dev/null +++ b/agent/executor/obproxy/delete.go @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package obproxy + +import ( + "os" + "path/filepath" + + "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/engine/task" + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/meta" +) + +func DeleteObproxy() (*task.DagDetailDTO, *errors.OcsAgentError) { + if !meta.IsObproxyAgent() { + return nil, nil + } + + templateBuilder := task.NewTemplateBuilder(DAG_DELETE_OBPROXY). + SetMaintenance(task.ObproxyMaintenance()). + SetType(task.DAG_OBPROXY). + AddNode(newPrepareForObproxyAgentNode(true)). + AddTask(newStopObproxyTask(), false). + AddTask(newDeleteObproxyTask(), false). + AddTask(newCleanObproxyDirTask(), false) + + context := task.NewTaskContext().SetParam(PARAM_OBPROXY_HOME_PATH, meta.OBPROXY_HOME_PATH) + dag, err := localTaskService.CreateDagInstanceByTemplate(templateBuilder.Build(), context) + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err) + } + return task.NewDagDetailDTO(dag), nil +} + +// DeleteObproxyTask will delete the obproxy home path +type DeleteObproxyTask struct { + task.Task +} + +func newDeleteObproxyTask() *DeleteObproxyTask { + newTask := &DeleteObproxyTask{ + Task: *task.NewSubTask(TASK_DELETE_OBPROXY), + } + newTask.SetCanContinue(). + SetCanRetry(). + SetCanCancel(). + SetCanPass() + return newTask +} + +func (t *DeleteObproxyTask) Execute() (err error) { + if err := agentService.DeleteObproxy(); err != nil { + return err + } + return nil +} + +type CleanObproxyDirTask struct { + task.Task + obproxyHomePath string +} + +func newCleanObproxyDirTask() *CleanObproxyDirTask { + newTask := &CleanObproxyDirTask{ + Task: *task.NewSubTask(TASK_CLEAN_OBPROXY_DIR), + } + newTask.SetCanContinue(). + SetCanRetry(). + SetCanCancel(). + SetCanPass() + return newTask +} + +func (t *CleanObproxyDirTask) Execute() (err error) { + if err := t.GetContext().GetParamWithValue(PARAM_OBPROXY_HOME_PATH, &t.obproxyHomePath); err != nil { + return err + } + deleteFiles := []string{constant.OBPROXY_DIR_ETC, constant.OBPROXY_DIR_LOG, constant.OBPROXY_DIR_RUN, + constant.OBPROXY_DIR_BIN, constant.OBPROXY_DIR_LIB} + for _, file := range deleteFiles { + if err := os.RemoveAll(filepath.Join(t.obproxyHomePath, file)); err != nil { + return errors.Occur(errors.ErrUnexpected, err) + } + } + return nil +} diff --git a/agent/executor/obproxy/enter.go b/agent/executor/obproxy/enter.go new file mode 100644 index 00000000..4f73624f --- /dev/null +++ b/agent/executor/obproxy/enter.go @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package obproxy + +import ( + "github.com/oceanbase/obshell/agent/engine/task" + agentservice "github.com/oceanbase/obshell/agent/service/agent" + obclusterservice "github.com/oceanbase/obshell/agent/service/obcluster" + obproxyservice "github.com/oceanbase/obshell/agent/service/obproxy" + taskservice "github.com/oceanbase/obshell/agent/service/task" +) + +var obproxyService = obproxyservice.ObproxyService{} +var obclusterService = obclusterservice.ObclusterService{} +var localTaskService = taskservice.NewLocalTaskService() +var agentService = agentservice.AgentService{} + +const ( + WORK_MODE_RS_LIST = "rsList" + WORK_MODE_CONFIG_URL = "configUrl" +) + +var ( + // task name for obproxy + DAG_ADD_OBPROXY = "Add obproxy" + DAG_START_OBPROXY = "Start obproxy" + DAG_STOP_OBPROXY = "Stop obproxy" + DAG_UPGRADE_OBPROXY = "Upgrade obproxy" + DAG_DELETE_OBPROXY = "Delete obproxy" + + TASK_START_OBPROXY = "Start obproxy" + TASK_START_OBPROXYD = "Start obproxyd" + TASK_SET_OBPROXY_SYS_PASSWORD = "Set obproxy sys password" + TASK_SET_OBPROXY_USER_PASSWORD = "Set proxyro password for connect" + TASK_PERSIST_OBPROXY_INFP = "Persist obproxy info" + TASK_STOP_OBPROXY = "Stop obproxy" + TASK_CHECK_OBPROXY_STATUS = "Check obproxy status" + TASK_CHECK_PROXYRO_PASSWORD = "Check proxyro password" + TASK_DELETE_OBPROXY = "Delete obproxy" + TASK_CLEAN_OBPROXY_DIR = "Clean obproxy dir" + + TASK_COPY_CONFIG_DB_FILE = "Copy obproxy config db file" + TASK_HOT_RESTART_OBPROXY = "Hot restart obproxy" + TASK_WAIT_HOT_RESTART_OBPROXY_FINISH = "Wait hot restart obproxy finish" + TASK_RECORD_OBPROXY_INFO = "Record obproxy info" + TASK_REINSTALL_OBPROXY_BIN = "Reinstall obproxy bin" + TASK_DOWNLOAD_RPM_FROM_SQLITE = "Download obproxy pkg from sqlite" + TASK_CHECK_OBPROXY_PKG = "Check obproxy pkg" + TASK_INSTALL_ALL_REQUIRED_PKGS = "Install all required pkgs" + TASK_BACKUP_FOR_UPGRADE = "Backup for upgrade" + TASK_REMOVE_UPGRADE_DIR = "Remove upgrade dir" + TASK_CREATE_UPGRADE_DIR = "Create upgrade dir" + + PARAM_ADD_OBPROXY_OPTION = "addObproxyOption" + PARAM_OBPROXY_HOME_PATH = "homePath" + PARAM_OBPROXY_SQL_PORT = "sqlPort" + PARAM_OBPROXY_EXPORTER_PORT = "exporterPort" + PARAM_OBPROXY_VERSION = "version" + PARAM_OBPROXY_START_PARAMS = "startParams" + PARAM_OBPROXY_START_WITH_OPTIONS = "startWithOptions" + PARAM_OBPROXY_APP_NAME = "appName" + PARAM_OBPROXY_WORK_MODE = "workMode" + PARAM_OBPROXY_RS_LIST = "rsList" + PARAM_OBPROXY_CONFIG_URL = "configUrl" + PARAM_OBPROXY_SYS_PASSWORD = "obproxySysPassword" + PARAM_OBPROXY_PROXYRO_PASSWORD = "proxyroPassword" + PARAM_OBPROXY_CLUSTER_NAME = "clusterName" + PARAM_PERSIST_OBPROXY_INFO_PARAM = "persistObproxyInfoParam" + PARAM_EXPECT_OBPROXY_AGENT = "expectObproxyAgent" + + PARAM_HOT_UPGRADE_ROLLBACK_TIMEOUT = "hotUpgradeRollbackTimeout" + PARAM_HOT_UPGRADE_EXIT_TIMEOUT = "hotUpgradeExitTimeout" + PARAM_OLD_OBPROXY_PID = "oldObproxyPid" + + // for upgrade + PARAM_VERSION = "version" + PARAM_BUILD_NUMBER = "buildNumber" + PARAM_DISTRIBUTION = "distribution" + PARAM_RELEASE_DISTRIBUTION = "releaseDistribution" + PARAM_UPGRADE_DIR = "upgradeDir" + PARAM_TASK_TIME = "taskTime" + PARAM_ONLY_FOR_AGENT = "onlyForAgent" + PARAM_SCRIPT_FILE = "scriptFile" + PARAM_OBPROXY_RPM_PKG_PATH = "obproxyRpmPkgPath" + PARAM_CREATE_UPGRADE_DIR_FLAG = "createUpgradeDirFlag" + + // stop obproxy or obproxyd retry times + STOP_PROCESS_MAX_RETRY_TIME = 15 + STOP_PROCESS_RETRY_INTERVAL = 5 +) + +func RegisterTaskType() { + task.RegisterTaskType(StartObproxyTask{}) + task.RegisterTaskType(SetObproxyUserPasswordForObTask{}) + task.RegisterTaskType(PersistObproxyInfoTask{}) + task.RegisterTaskType(StopObproxyTask{}) + task.RegisterTaskType(PrepareForAddObproxyTask{}) + + task.RegisterTaskType(StopObproxyTask{}) + + task.RegisterTaskType(CopyConfigDbFileTask{}) + task.RegisterTaskType(HotRestartObproxyTask{}) + task.RegisterTaskType(WaitHotRestartObproxyFinishTask{}) + task.RegisterTaskType(RecordObproxyInfoTask{}) + task.RegisterTaskType(ReinstallObproxyBinTask{}) + task.RegisterTaskType(GetObproxyPkgTask{}) + task.RegisterTaskType(CheckObproxyPkgTask{}) + task.RegisterTaskType(BackupObproxyForUpgradeTask{}) + task.RegisterTaskType(RemoveUpgradeObproxyDirTask{}) + task.RegisterTaskType(CreateObproxyUpgradeDirTask{}) + + task.RegisterTaskType(CleanObproxyDirTask{}) + task.RegisterTaskType(DeleteObproxyTask{}) +} diff --git a/agent/executor/obproxy/package.go b/agent/executor/obproxy/package.go new file mode 100644 index 00000000..f35a81d7 --- /dev/null +++ b/agent/executor/obproxy/package.go @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package obproxy + +import ( + "fmt" + "io" + "os" + "path/filepath" + + "github.com/cavaliergopher/cpio" + "github.com/cavaliergopher/rpm" + "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/engine/task" + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/global" + "github.com/oceanbase/obshell/agent/lib/path" + "github.com/oceanbase/obshell/agent/lib/pkg" + "github.com/oceanbase/obshell/agent/lib/system" + "github.com/ulikunitz/xz" + + "github.com/oceanbase/obshell/agent/repository/model/sqlite" + log "github.com/sirupsen/logrus" +) + +var ( + confficient = 1.1 +) + +type GetObproxyPkgTask struct { + task.Task + targetBuildNumber string + targetVersion string + distribution string + upgradeDir string + + upgradePkgInfo sqlite.UpgradePkgInfo +} + +func newGetObproxyPkgTask() *GetObproxyPkgTask { + newTask := &GetObproxyPkgTask{ + Task: *task.NewSubTask(TASK_DOWNLOAD_RPM_FROM_SQLITE), + } + newTask.SetCanContinue().SetCanRetry().SetCanRollback() + return newTask +} + +func (t *GetObproxyPkgTask) getParams() (err error) { + if err = t.GetContext().GetParamWithValue(PARAM_UPGRADE_DIR, &t.upgradeDir); err != nil { + return err + } + if err = t.GetContext().GetParamWithValue(PARAM_BUILD_NUMBER, &t.targetBuildNumber); err != nil { + return err + } + if err = t.GetContext().GetParamWithValue(PARAM_VERSION, &t.targetVersion); err != nil { + return err + } + if err = t.GetContext().GetParamWithValue(PARAM_DISTRIBUTION, &t.distribution); err != nil { + return err + } + return nil +} + +func (t *GetObproxyPkgTask) Execute() (err error) { + if t.IsContinue() { + t.ExecuteLog("The task is continuing.") + if err = t.Rollback(); err != nil { + return err + } + } + + if err = t.getAllRequiredPkgs(); err != nil { + return + } + return nil +} + +func (t *GetObproxyPkgTask) getAllRequiredPkgs() (err error) { + if err = t.getParams(); err != nil { + return err + } + + t.ExecuteLogf("The directory for this upgrade check task is %s", t.upgradeDir) + if err = os.MkdirAll(t.upgradeDir, 0755); err != nil { + return err + } + + t.ExecuteLog("Confirm that all the required packages have been uploaded.") + + if t.upgradePkgInfo, err = agentService.GetUpgradePkgInfoByVersionAndRelease(constant.PKG_OBPROXY_CE, t.targetVersion, t.targetBuildNumber, t.distribution, global.Architecture); err != nil { + return err + } + + if err = t.CheckDiskFreeSpace(); err != nil { + return + } + + return t.downloadAllRequiredPkgs() +} + +func (t *GetObproxyPkgTask) CheckDiskFreeSpace() error { + t.ExecuteLog("Check the remaining disk space.") + t.ExecuteLogf("The directory being checked is %s", t.upgradeDir) + expectedSize := (t.upgradePkgInfo.Size + t.upgradePkgInfo.PayloadSize) * uint64(confficient) + t.ExecuteLogf("The required disk size is %d", expectedSize) + diskInfo, err := system.GetDiskInfo(t.upgradeDir) + if err != nil { + return errors.Wrap(err, "failed to get disk info") + } + t.ExecuteLogf("The remaining disk size is %d", diskInfo.FreeSizeBytes) + if diskInfo.FreeSizeBytes < expectedSize { + return fmt.Errorf("the remaining disk space is insufficient, the remaining disk space is %d, and the required disk space is %d", diskInfo.FreeSizeBytes, expectedSize) + } + return nil +} + +func (t *GetObproxyPkgTask) downloadAllRequiredPkgs() (err error) { + t.ExecuteLogf("Download all packages to %s", t.upgradeDir) + pkgInfo := t.upgradePkgInfo + rpmDir := GenerateUpgradeRpmDir(t.upgradeDir, pkgInfo.Version, pkgInfo.Architecture) + if err := os.MkdirAll(rpmDir, 0755); err != nil { + return err + } + rpmPkgPath := GenerateRpmPkgPath(rpmDir, pkgInfo.Name) + if err = agentService.DownloadUpgradePkgChunkInBatch(rpmPkgPath, pkgInfo.PkgId, pkgInfo.ChunkCount); err != nil { + return err + } + t.GetContext().SetParam(PARAM_OBPROXY_RPM_PKG_PATH, rpmPkgPath) + t.ExecuteLogf("Downloaded pkg '%s' to '%s'", pkgInfo.Name, rpmPkgPath) + return nil +} + +func (t *GetObproxyPkgTask) Rollback() (err error) { + t.ExecuteLog("Rolling back...") + if err = t.deleteAllRequiredPkgs(); err != nil { + return + } + t.ExecuteLog("Successfully deleted.") + return nil +} + +func (t *GetObproxyPkgTask) deleteAllRequiredPkgs() (err error) { + t.ExecuteLog("Delete all previously downloaded packages.") + if err = t.GetContext().GetParamWithValue(PARAM_UPGRADE_DIR, &t.upgradeDir); err != nil { + return err + } + return os.RemoveAll(t.upgradeDir) + +} + +func GenerateUpgradeRpmDir(upgradeDir, version, arch string) string { + return filepath.Join(upgradeDir, arch, version) +} + +func GenerateRpmPkgPath(rpmDir, rpmName string) string { + return fmt.Sprintf("%s/%s.rpm", rpmDir, rpmName) +} + +type CheckObproxyPkgTask struct { + task.Task + pkgPath string +} + +func newCheckObproxyPkgTask() *CheckObproxyPkgTask { + newTask := &CheckObproxyPkgTask{ + Task: *task.NewSubTask(TASK_CHECK_OBPROXY_PKG), + } + newTask. + SetCanContinue(). + SetCanRollback(). + SetCanRetry(). + SetCanPass(). + SetCanCancel() + return newTask +} + +func (t *CheckObproxyPkgTask) Execute() (err error) { + if t.GetContext().GetParamWithValue(PARAM_OBPROXY_RPM_PKG_PATH, &t.pkgPath); err != nil { + return err + } + if err = t.checkRequiredPkgs(); err != nil { + return + } + return nil +} + +func (t *CheckObproxyPkgTask) checkRequiredPkgs() (err error) { + if err = t.checkUpgradePkgFromDb(t.pkgPath); err != nil { + return err + } + t.ExecuteInfoLog("obproxy-ce package is checked successfully.") + return nil +} + +func (t *CheckObproxyPkgTask) checkUpgradePkgFromDb(filePath string) (err error) { + input, err := os.Open(filePath) + if err != nil { + return err + } + defer input.Close() + r := &upgradeRpmPkgInfo{ + rpmFile: input, + } + + if err = r.CheckUpgradePkg(false); err != nil { + return err + } + return nil +} + +type ReinstallObproxyBinTask struct { + task.Task + rpmPkgPath string +} + +func newReinstallObproxyBinTask() *ReinstallObproxyBinTask { + newTask := &ReinstallObproxyBinTask{ + Task: *task.NewSubTask(TASK_REINSTALL_OBPROXY_BIN), + } + newTask.SetCanContinue(). + SetCanRetry(). + SetCanRollback(). + SetCanCancel(). + SetCanPass() + return newTask +} + +func (t *ReinstallObproxyBinTask) Execute() error { + if err := t.GetContext().GetParamWithValue(PARAM_OBPROXY_RPM_PKG_PATH, &t.rpmPkgPath); err != nil { + return err + } + if err := t.installRpmPkgInPlace(t.rpmPkgPath); err != nil { + return err + } + t.ExecuteLogf("Successfully installed %s", t.rpmPkgPath) + return nil +} + +func (t *ReinstallObproxyBinTask) installRpmPkgInPlace(rpmPkgPath string) (err error) { + log.Infof("InstallRpmPkg: %s", rpmPkgPath) + f, err := os.Open(rpmPkgPath) + if err != nil { + return + } + defer f.Close() + + rpmPkg, err := rpm.Read(f) + if err != nil { + return + } + + if err = pkg.CheckCompressAndFormat(rpmPkg); err != nil { + return + } + + xzReader, err := xz.NewReader(f) + if err != nil { + return + } + cpioReader := cpio.NewReader(xzReader) + + for { + hdr, err := cpioReader.Next() + if err == io.EOF { + break + } + if err != nil { + return err + } + + m := hdr.Mode + if m.IsRegular() && hdr.FileInfo().Name() == "obproxy" { + // Remove obproxy + if err := os.RemoveAll(path.ObproxyBinPath()); err != nil { + return err + } + outFile, err := os.OpenFile(path.ObproxyBinPath(), os.O_CREATE|os.O_WRONLY, 0755) + if err != nil { + return err + } + defer outFile.Close() + log.Infof("Extracting %s", hdr.Name) + if _, err := io.Copy(outFile, cpioReader); err != nil { + return err + } + } + } + + return nil +} + +func (t *ReinstallObproxyBinTask) Rollback() (err error) { + t.ExecuteLog("uninstall new obproxy") + var upgradeDir string + if err = t.GetContext().GetParamWithValue(PARAM_UPGRADE_DIR, &upgradeDir); err != nil { + return err + } + + backupDir := filepath.Join(upgradeDir, "backup") + + dest := path.ObproxyBinPath() + if err := os.RemoveAll(dest); err != nil { + return err + } + return system.CopyFile(fmt.Sprintf("%s/%s", backupDir, constant.PROC_OBPROXY), dest) +} + +type BackupObproxyForUpgradeTask struct { + task.Task + upgradeDir string + backupDir string +} + +func newBackupObproxyForUpgradeTask() *BackupObproxyForUpgradeTask { + newTask := &BackupObproxyForUpgradeTask{ + Task: *task.NewSubTask(TASK_BACKUP_FOR_UPGRADE), + } + newTask. + SetCanRetry(). + SetCanContinue(). + SetCanRollback(). + SetCanPass(). + SetCanCancel() + return newTask +} + +func (t *BackupObproxyForUpgradeTask) Execute() (err error) { + if t.IsContinue() { + t.ExecuteLog("The task is continuing.") + if err = t.Rollback(); err != nil { + return err + } + } + + if err = t.BackupObproxyForUpgrade(); err != nil { + return + } + return nil +} + +func (t *BackupObproxyForUpgradeTask) getParams() (err error) { + if err = t.GetContext().GetParamWithValue(PARAM_UPGRADE_DIR, &t.upgradeDir); err != nil { + return err + } + + t.backupDir = filepath.Join(t.upgradeDir, "backup") + return nil +} + +func (t *BackupObproxyForUpgradeTask) BackupObproxyForUpgrade() error { + t.ExecuteLog("Backup important files.") + if err := t.getParams(); err != nil { + return err + } + + t.ExecuteLogf("The directory for backup is %s", t.backupDir) + t.ExecuteLogf("Backup the bin directory %s", path.BinDir()) + if err := system.CopyDirs(path.ObproxyBinDir(), t.backupDir); err != nil { + return err + } + return nil +} + +func (t *BackupObproxyForUpgradeTask) Rollback() (err error) { + t.ExecuteLog("Rolling back...") + if err = t.deleteBackupDir(); err != nil { + return err + } + t.ExecuteLog("Successfully deleted") + return nil +} + +func (t *BackupObproxyForUpgradeTask) deleteBackupDir() (err error) { + if err = t.getParams(); err != nil { + return err + } + if t.backupDir != "" { + t.ExecuteLog("Delete " + t.backupDir) + if err := os.RemoveAll(t.backupDir); err != nil { + return err + } + } + return nil +} diff --git a/agent/executor/obproxy/start.go b/agent/executor/obproxy/start.go new file mode 100644 index 00000000..f3ab36b8 --- /dev/null +++ b/agent/executor/obproxy/start.go @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package obproxy + +import ( + "github.com/oceanbase/obshell/agent/engine/task" + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/meta" +) + +func StartObproxy() (*task.DagDetailDTO, *errors.OcsAgentError) { + if !meta.IsObproxyAgent() { + return nil, errors.Occur(errors.ErrBadRequest, "This is not an obproxy agent") + } + + template := task.NewTemplateBuilder(DAG_START_OBPROXY). + SetType(task.DAG_OBPROXY). + AddNode(newPrepareForObproxyAgentNode(true)). + AddNode(newStartObproxyWithoutOptionsNode()).Build() + context := task.NewTaskContext().SetParam(PARAM_OBPROXY_HOME_PATH, meta.OBPROXY_HOME_PATH) + dag, err := localTaskService.CreateDagInstanceByTemplate(template, context) + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err) + } + return task.NewDagDetailDTO(dag), nil + +} diff --git a/agent/executor/obproxy/stop.go b/agent/executor/obproxy/stop.go new file mode 100644 index 00000000..e24e665b --- /dev/null +++ b/agent/executor/obproxy/stop.go @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package obproxy + +import ( + "os/exec" + "time" + + log "github.com/sirupsen/logrus" + + "github.com/oceanbase/obshell/agent/engine/task" + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/lib/process" + "github.com/oceanbase/obshell/agent/meta" +) + +func StopObproxy() (*task.DagDetailDTO, *errors.OcsAgentError) { + if !meta.IsObproxyAgent() { + return nil, errors.Occur(errors.ErrBadRequest, "This is not an obproxy agent") + } + + template := task.NewTemplateBuilder(DAG_STOP_OBPROXY). + SetMaintenance(task.ObproxyMaintenance()). + SetType(task.DAG_OBPROXY). + AddNode(newPrepareForObproxyAgentNode(true)). + AddTask(newStopObproxyTask(), false).Build() + + ctx := task.NewTaskContext().SetParam(PARAM_OBPROXY_HOME_PATH, meta.OBPROXY_HOME_PATH) + dag, err := localTaskService.CreateDagInstanceByTemplate(template, ctx) + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err) + } + return task.NewDagDetailDTO(dag), nil +} + +// StopObproxyTask will stop obproyxd and obproxy. +type StopObproxyTask struct { + task.Task +} + +func newStopObproxyTask() *StopObproxyTask { + newTask := &StopObproxyTask{ + Task: *task.NewSubTask(TASK_STOP_OBPROXY), + } + newTask.SetCanContinue(). + SetCanRetry(). + SetCanRollback(). + SetCanCancel(). + SetCanPass() + return newTask +} + +func (t *StopObproxyTask) Execute() error { + // if err := t.stopObproxyd(); err != nil { + // return err + // } + if err := t.stopObproxy(); err != nil { + return err + } + return nil +} + +func (t *StopObproxyTask) stopObproxy() error { + pid, err := process.GetObproxyPid() + if err != nil { + return err + } + t.ExecuteLogf("Get obproxy pid: %s", pid) + if pid == "" { + t.ExecuteLog("Obproxy is not running") + return nil + } + for i := 0; i < STOP_PROCESS_MAX_RETRY_TIME; i++ { + t.ExecuteLogf("Kill obproxy process %s", pid) + res := exec.Command("kill", "-9", pid) + if err := res.Run(); err != nil { + log.Warn("Kill obproxy process failed") + } + + time.Sleep(time.Second * time.Duration(STOP_PROCESS_RETRY_INTERVAL)) + t.TimeoutCheck() + + t.ExecuteLog("Check obproxy process") + exist, err := process.CheckObproxyProcess() + if err != nil { + log.Warnf("Check obproxy process failed: %v", err) + } else if !exist { + t.ExecuteLog("Successfully killed the obproxy process") + return nil + } + } + return errors.New("kill obproxy process timeout") +} + +func (t *StopObproxyTask) stopObproxyd() error { + pid, err := process.GetObproxydPid() + if err != nil { + return err + } + t.ExecuteLogf("Get obproxyd pid: %s", pid) + if pid == "" { + t.ExecuteLog("Obproxyd is not running") + return nil + } + for i := 0; i < STOP_PROCESS_MAX_RETRY_TIME; i++ { + t.ExecuteLogf("Kill obproxyd process %s", pid) + res := exec.Command("kill", "-9", pid) + if err := res.Run(); err != nil { + log.Warn("Kill obproxyd process failed") + } + + time.Sleep(time.Second * time.Duration(STOP_PROCESS_RETRY_INTERVAL)) + t.TimeoutCheck() + + t.ExecuteLog("Check obproxyd process") + exist, err := process.CheckObproxydProcess() + if err != nil { + log.Warnf("Check obproxyd process failed: %v", err) + } else if !exist { + t.ExecuteLog("Successfully killed the obproxyd process") + return nil + } + } + return errors.New("kill obproxyd process timeout") +} diff --git a/agent/executor/obproxy/upgrade.go b/agent/executor/obproxy/upgrade.go new file mode 100644 index 00000000..ec08de3a --- /dev/null +++ b/agent/executor/obproxy/upgrade.go @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package obproxy + +import ( + "fmt" + "os" + "regexp" + "strings" + "time" + + "github.com/oceanbase/obshell/agent/config" + "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/engine/task" + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/global" + "github.com/oceanbase/obshell/agent/lib/parse" + "github.com/oceanbase/obshell/agent/lib/path" + "github.com/oceanbase/obshell/agent/lib/pkg" + "github.com/oceanbase/obshell/agent/lib/process" + "github.com/oceanbase/obshell/agent/lib/system" + "github.com/oceanbase/obshell/agent/meta" + obproxydb "github.com/oceanbase/obshell/agent/repository/db/obproxy" + "github.com/oceanbase/obshell/agent/repository/model/bo" + "github.com/oceanbase/obshell/param" + "github.com/oceanbase/obshell/utils" + log "github.com/sirupsen/logrus" + "gorm.io/gorm" +) + +const waitPeriod = 5 // seconds + +func UpgradeObproxy(param param.UpgradeObproxyParam) (*task.DagDetailDTO, *errors.OcsAgentError) { + if !meta.IsObproxyAgent() { + return nil, errors.Occur(errors.ErrBadRequest, "not obproxy agent") + } + if alive, err := process.CheckObproxyProcess(); err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err) + } else if !alive { + return nil, errors.Occur(errors.ErrBadRequest, "obproxy is not running") + } + + if err := checkVersionSupport(param.Version, param.Release); err != nil { + return nil, err + } + if err := checkUpgradeDir(¶m.UpgradeDir); err != nil { + return nil, errors.Occur(errors.ErrIllegalArgument, err) + } + if err := findTargetPkg(param.Version, param.Release); err != nil { + return nil, err + } + + template := buildUpgradeObproxyTemplate() + context := buildUpgradeObproxyTaskContext(param) + dag, err := localTaskService.CreateDagInstanceByTemplate(template, context) + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err) + } + return task.NewDagDetailDTO(dag), nil +} + +func checkVersionSupport(version, release string) *errors.OcsAgentError { + // Check obproxy version + curObproxyVersion, err := obproxyService.GetObproxyVersion() + if err != nil { + return errors.Occur(errors.ErrUnexpected, err) + } + buildNumber, _, err := pkg.SplitRelease(release) + if err != nil { + return errors.Occur(errors.ErrUnexpected, err) + } + if pkg.CompareVersion(curObproxyVersion, fmt.Sprintf("%s-%s", version, buildNumber)) >= 0 { + return errors.Occur(errors.ErrBadRequest, "current obproxy version is greater than or equal to the target version") + } + return nil +} + +func findTargetPkg(version, release string) *errors.OcsAgentError { + buildNumber, distribution, _ := pkg.SplitRelease(release) + _, err := agentService.GetUpgradePkgInfoByVersionAndRelease(constant.PKG_OBPROXY_CE, version, buildNumber, distribution, global.Architecture) + if err != nil { + return errors.Occurf(errors.ErrBadRequest, "find target pkg '%s-%s-%s.%s.rpm' failed", constant.PKG_OBPROXY_CE, version, release, global.Architecture) + } + return nil +} + +func checkUpgradeDir(path *string) (err error) { + log.Infof("checking upgrade directory: '%s'", *path) + str := *path + + *path = strings.TrimSpace(*path) + if len(*path) == 0 { + return nil + } + + return utils.CheckPathValid(str) +} + +func buildUpgradeObproxyTemplate() *task.Template { + return task.NewTemplateBuilder(DAG_UPGRADE_OBPROXY). + SetMaintenance(task.ObproxyMaintenance()). + SetType(task.DAG_OBPROXY). + AddTask(newCreateObproxyUpgradeDirTask(), false). + AddTask(newGetObproxyPkgTask(), false). + AddTask(newCheckObproxyPkgTask(), false). + AddTask(newBackupObproxyForUpgradeTask(), false). + AddTask(newReinstallObproxyBinTask(), false). + AddTask(newCopyConfigDbFileTask(), false). + AddTask(newRecordObproxyInfoTask(), false). + AddTask(newHotRestartObproxyTask(), false). + AddTask(newWaitHotRestartObproxyFinishTask(), false). + AddTask(newRemoveUpgradeCheckDirTask(), false). + Build() +} + +func buildUpgradeObproxyTaskContext(param param.UpgradeObproxyParam) *task.TaskContext { + if param.UpgradeDir == "" { + param.UpgradeDir = meta.OBPROXY_HOME_PATH + } + buildNumber, distribution, _ := pkg.SplitRelease(param.Release) + return task.NewTaskContext(). + SetParam(PARAM_UPGRADE_DIR, fmt.Sprintf("%s/%s-%d", param.UpgradeDir, "obproxy-upgrade-dir", time.Now().Unix())). + SetParam(PARAM_VERSION, param.Version). + SetParam(PARAM_BUILD_NUMBER, buildNumber). + SetParam(PARAM_DISTRIBUTION, distribution). + SetParam(PARAM_RELEASE_DISTRIBUTION, param.Release) +} + +type CopyConfigDbFileTask struct { + task.Task + targetVersion string +} + +func newCopyConfigDbFileTask() *CopyConfigDbFileTask { + newTask := &CopyConfigDbFileTask{ + Task: *task.NewSubTask(TASK_COPY_CONFIG_DB_FILE), + } + newTask.SetCanContinue(). + SetCanRetry(). + SetCanRollback(). + SetCanCancel(). + SetCanPass() + return newTask +} + +func (t *CopyConfigDbFileTask) Execute() error { + if err := t.GetContext().GetParamWithValue(PARAM_VERSION, &t.targetVersion); err != nil { + return err + } + if pkg.CompareVersion(t.targetVersion, "4.1.0.0") >= 0 { + if _, err := os.Stat(path.ObproxyNewConfigDbFile()); err == nil { + return nil + } else { + return system.CopyFile(path.ObproxyOldConfigDbFile(), path.ObproxyNewConfigDbFile()) + } + } + + return nil +} + +func (t *CopyConfigDbFileTask) Rollback() error { + if pkg.CompareVersion(t.targetVersion, "4.1.0.0") >= 0 { + if _, err := os.Stat(path.ObproxyNewConfigDbFile()); err == nil { + return nil + } else { + return system.CopyFile(path.ObproxyOldConfigDbFile(), path.ObproxyNewConfigDbFile()) + } + } + return nil +} + +type HotRestartObproxyTask struct { + task.Task +} + +func newHotRestartObproxyTask() *HotRestartObproxyTask { + newTask := &HotRestartObproxyTask{ + Task: *task.NewSubTask(TASK_HOT_RESTART_OBPROXY), + } + newTask.SetCanContinue(). + SetCanRetry(). + SetCanRollback(). + SetCanCancel(). + SetCanPass() + return newTask +} + +func (t *HotRestartObproxyTask) Execute() error { + t.ExecuteLogf("set %s to %s", constant.OBPROXY_CONFIG_PROXY_LOCAL_CMD, constant.RESTART_FOR_PROXY_LOCAL_CMD) + return obproxyService.SetGlobalConfig(constant.OBPROXY_CONFIG_PROXY_LOCAL_CMD, constant.RESTART_FOR_PROXY_LOCAL_CMD) +} + +type RecordObproxyInfoTask struct { + task.Task +} + +func newRecordObproxyInfoTask() *RecordObproxyInfoTask { + newTask := &RecordObproxyInfoTask{ + Task: *task.NewSubTask(TASK_RECORD_OBPROXY_INFO), + } + newTask.SetCanContinue(). + SetCanRetry(). + SetCanRollback(). + SetCanCancel(). + SetCanPass() + return newTask +} + +func (t *RecordObproxyInfoTask) Execute() error { + rollbackTimeout, err := obproxyService.GetGlobalConfig(constant.OBPROXY_CONFIG_HOT_UPGRADE_ROLLBACK_TIMEOUT) + if err != nil { + return errors.Wrapf(err, "get %s failed", constant.OBPROXY_CONFIG_HOT_UPGRADE_ROLLBACK_TIMEOUT) + } + pid, err := process.FindPIDByPort(uint32(meta.OBPROXY_SQL_PORT)) + if err != nil { + return errors.Wrapf(err, "find obproxy pid failed") + } + t.GetContext().SetData(PARAM_OLD_OBPROXY_PID, pid) + t.GetContext().SetData(PARAM_HOT_UPGRADE_ROLLBACK_TIMEOUT, rollbackTimeout) + return nil +} + +type WaitHotRestartObproxyFinishTask struct { + task.Task + rollbackTimeout string + oldPid int32 + targetVersion string + buildNumber string +} + +func newWaitHotRestartObproxyFinishTask() *WaitHotRestartObproxyFinishTask { + newTask := &WaitHotRestartObproxyFinishTask{ + Task: *task.NewSubTask(TASK_WAIT_HOT_RESTART_OBPROXY_FINISH), + } + newTask.SetCanContinue(). + SetCanRetry(). + SetCanRollback(). + SetCanCancel(). + SetCanPass() + return newTask +} + +func (t *WaitHotRestartObproxyFinishTask) Execute() error { + var err error + if err = t.GetContext().GetDataWithValue(PARAM_OLD_OBPROXY_PID, &t.oldPid); err != nil { + return err + } + if err = t.GetContext().GetDataWithValue(PARAM_HOT_UPGRADE_ROLLBACK_TIMEOUT, &t.rollbackTimeout); err != nil { + return err + } + if err = t.GetContext().GetParamWithValue(PARAM_VERSION, &t.targetVersion); err != nil { + return err + } + if err = t.GetContext().GetParamWithValue(PARAM_BUILD_NUMBER, &t.buildNumber); err != nil { + return err + } + + // parse rollbackTimeout + rollbackTimeouot, err := parse.TimeParse(t.rollbackTimeout) + if err != nil { + return errors.Wrapf(err, "parse rollback timeout failed") + } + + retryTimes := rollbackTimeouot / waitPeriod + var pid int32 + for i := 0; i < retryTimes; i++ { + t.TimeoutCheck() + time.Sleep(time.Duration(waitPeriod) * time.Second) + pid, err = process.FindPIDByPort(uint32(meta.OBPROXY_SQL_PORT)) + if err != nil { + continue + } + t.ExecuteLogf("obproxy %d is running", pid) + if pid == t.oldPid { + t.ExecuteLogf("obproxy %d is still running, waiting for it to exit...", t.oldPid) + err = errors.New("obproxy is still running") + continue + } + err = t.checkVersion() + break + } + + if err == nil { + // Modify the pid file. + if err := process.WritePidForce(path.ObproxyPidPath(), int(pid)); err != nil { + return errors.Wrapf(err, "write obproxy pid file failed") + } + return nil + + } + + return errors.Wrapf(err, "wait hot restart obproxy finish timeout") +} + +func (t *WaitHotRestartObproxyFinishTask) checkVersion() (err error) { + dsConfig := config.NewObproxyDataSourceConfig().SetPort(meta.OBPROXY_SQL_PORT).SetPassword(meta.OBPROXY_SYS_PWD) + var tempDb *gorm.DB + defer func() { + if tempDb != nil { + db, _ := tempDb.DB() + db.Close() + } + }() + for retryCount := 1; retryCount <= obproxydb.WAIT_OBPROXY_CONNECTED_MAX_TIMES; retryCount++ { + t.ExecuteLogf("retry %d times", retryCount) + t.TimeoutCheck() + time.Sleep(obproxydb.WAIT_OBPROXY_CONNECTED_MAX_INTERVAL) + if tempDb, err = obproxydb.LoadTempObproxyInstance(dsConfig); err != nil { + t.ExecuteLogf("load obproxy instance failed: %s", err.Error()) + continue + } + var proxyInfo bo.ObproxyInfo + if err = tempDb.Raw("show proxyinfo binary").Scan(&proxyInfo).Error; err != nil { + t.ExecuteLogf("show proxyconfig failed: %s", err.Error()) + continue + } + // parse obproxy version + re := regexp.MustCompile(`\d+\.\d+\.\d+\.\d+-\d+`) + version := re.FindString(proxyInfo.Info) + if version != strings.Join([]string{t.targetVersion, t.buildNumber}, "-") { + t.ExecuteLogf("obproxy version is not the target version, current version: %s, target version: %s", version, t.targetVersion) + continue + } + return nil + } + return errors.New("check obproxy version timeout...") +} + +type CreateObproxyUpgradeDirTask struct { + task.Task + upgradeDir string +} + +func newCreateObproxyUpgradeDirTask() *CreateObproxyUpgradeDirTask { + newTask := &CreateObproxyUpgradeDirTask{ + Task: *task.NewSubTask(TASK_CREATE_UPGRADE_DIR), + } + newTask. + SetCanRetry(). + SetCanContinue(). + SetCanRollback(). + SetCanPass(). + SetCanCancel() + return newTask +} + +func (t *CreateObproxyUpgradeDirTask) Execute() (err error) { + if err = t.GetContext().GetParamWithValue(PARAM_UPGRADE_DIR, &t.upgradeDir); err != nil { + return err + } + t.ExecuteLogf("Upgrade dir is %s", t.upgradeDir) + if err = t.checkUpgradeDir(); err != nil { + return err + } + return nil +} + +func (t *CreateObproxyUpgradeDirTask) checkUpgradeDir() (err error) { + t.GetContext().SetData(PARAM_CREATE_UPGRADE_DIR_FLAG, false) + + t.ExecuteLogf("Mkdir %s ", t.upgradeDir) + if err = os.MkdirAll(t.upgradeDir, 0755); err != nil { + return err + } + + isDirEmpty, err := system.IsDirEmpty(t.upgradeDir) + if err != nil { + return err + } + if !isDirEmpty { + return fmt.Errorf("%s is not empty", t.upgradeDir) + } + t.GetContext().SetData(PARAM_CREATE_UPGRADE_DIR_FLAG, true) + return nil +} + +func (t *CreateObproxyUpgradeDirTask) Rollback() (err error) { + t.ExecuteLog("Rolling back...") + if t.GetContext().GetData(PARAM_CREATE_UPGRADE_DIR_FLAG) == nil { + return nil + } + t.ExecuteLog("Remove " + t.upgradeDir) + return os.RemoveAll(t.upgradeDir) +} + +// RemoveUpgradeObproxyDirTask remove upgrade dir +type RemoveUpgradeObproxyDirTask struct { + task.Task + upgradeDir string +} + +func newRemoveUpgradeCheckDirTask() *RemoveUpgradeObproxyDirTask { + newTask := &RemoveUpgradeObproxyDirTask{ + Task: *task.NewSubTask(TASK_REMOVE_UPGRADE_DIR), + } + newTask. + SetCanRetry(). + SetCanContinue(). + SetCanPass(). + SetCanCancel() + return newTask +} + +func (t *RemoveUpgradeObproxyDirTask) Execute() (err error) { + t.ExecuteLog("remove upgrade dir") + if err = t.removeUpgradeDir(); err != nil { + return + } + t.ExecuteLog("remove upgrade check dir finished") + return nil +} + +func (t *RemoveUpgradeObproxyDirTask) removeUpgradeDir() (err error) { + if err := t.GetContext().GetParamWithValue(PARAM_UPGRADE_DIR, &t.upgradeDir); err != nil { + return errors.New("get upgrade check task dir failed") + } + return os.RemoveAll(t.upgradeDir) +} diff --git a/agent/executor/obproxy/upload_pkg.go b/agent/executor/obproxy/upload_pkg.go new file mode 100644 index 00000000..05ab05ba --- /dev/null +++ b/agent/executor/obproxy/upload_pkg.go @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package obproxy + +import ( + "fmt" + "mime/multipart" + + "github.com/cavaliergopher/rpm" + log "github.com/sirupsen/logrus" + + "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/lib/pkg" + "github.com/oceanbase/obshell/agent/repository/model/sqlite" +) + +var defaultFileFormatForObproxy = "/home/admin/obproxy-%s/bin/obproxy" + +type upgradeRpmPkgInfo struct { + rpmFile multipart.File + rpmPkg *rpm.Package + version string + release string + distribution string +} + +func UpgradePkgUpload(input multipart.File) (*sqlite.UpgradePkgInfo, *errors.OcsAgentError) { + r := &upgradeRpmPkgInfo{ + rpmFile: input, + } + + if err := r.CheckUpgradePkg(true); err != nil { + return nil, errors.Occur(errors.ErrKnown, err) + } + + pkgInfo, err := obproxyService.DumpUpgradePkgInfoAndChunkTx(r.rpmPkg, r.rpmFile) + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err) + } + return pkgInfo, nil +} + +func (r *upgradeRpmPkgInfo) CheckUpgradePkg(forUpload bool) (err error) { + if r.rpmPkg, err = pkg.ReadRpm(r.rpmFile); err != nil { + return + } + r.version = r.rpmPkg.Version() + + if r.rpmPkg.Name() != constant.PKG_OBPROXY_CE { + return fmt.Errorf("unsupported name '%s', the supported name is '%s'", r.rpmPkg.Name(), constant.PKG_OBPROXY_CE) + } + return r.fileCheck() +} + +func (r *upgradeRpmPkgInfo) fileCheck() (err error) { + // Check for the necessary files required for the agent upgrade process. + if err = r.checkVersion(); err != nil { + return errors.Wrap(err, "failed to check version and release") + } + return r.findAllExpectedFiles([]string{defaultFileFormatForObproxy}) +} + +func (r *upgradeRpmPkgInfo) checkVersion() (err error) { + log.Info("version is ", r.version) + r.release, r.distribution, err = pkg.SplitRelease(r.rpmPkg.Release()) + if err != nil { + return + } + if pkg.CompareVersion(r.rpmPkg.Version(), constant.OBPROXY_MIN_VERSION_SUPPORT) < 0 { + return fmt.Errorf("unsupported obproxy version '%s', the minimum supported version is '%s'", r.rpmPkg.Version(), constant.SUPPORT_MIN_VERSION) + } + return nil +} + +func (r *upgradeRpmPkgInfo) findAllExpectedFiles(expected []string) (err error) { + succeed := true + missingFiles := make([]string, 0) + for _, expect := range expected { + expect = fmt.Sprintf(expect, r.version) + var found bool + for _, actual := range r.rpmPkg.Files() { + if actual.Name() == expect { + log.Info("found file: ", expect) + found = true + break + } + } + if !found { + log.Errorf("file '%s' not found", expect) + missingFiles = append(missingFiles, expect) + succeed = false + } + } + if !succeed { + return fmt.Errorf("these files are missing: '%v'", missingFiles) + } + return nil +} diff --git a/agent/executor/obproxy/utils.go b/agent/executor/obproxy/utils.go new file mode 100644 index 00000000..d34e40f7 --- /dev/null +++ b/agent/executor/obproxy/utils.go @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package obproxy + +import ( + "fmt" + "os/exec" + "regexp" + "strings" +) + +func getObproxyVersion(homepath string) (string, error) { + output, err := exec.Command(homepath+"/bin/obproxy", "-V").CombinedOutput() + if err != nil { + return "", err + } + re := regexp.MustCompile(`\(OceanBase (\d+\.\d+\.\d+\.\d+) (\d+)\)`) + matches := re.FindStringSubmatch(string(output)) + if len(matches) < 3 { + return "", fmt.Errorf("version not found in output: %s", output) + } + return strings.Join(matches[1:], "-"), nil +} diff --git a/agent/executor/script/script.go b/agent/executor/script/script.go index eabc21bd..1c0d288b 100644 --- a/agent/executor/script/script.go +++ b/agent/executor/script/script.go @@ -174,7 +174,7 @@ func (t *ImportScriptForTenantTask) importByPython(module, scriptPath, sqlfile s } t.ExecuteLogf("Use python to import %s.", module) - str := fmt.Sprintf("%s -h%s -P%d -t%s -f%s", scriptPath, constant.LOCAL_IP, meta.MYSQL_PORT, t.tenantName, sqlfile) + str := fmt.Sprintf("%s -h%s -P%d -t%s -f%s", scriptPath, meta.OCS_AGENT.GetLocalIp(), meta.MYSQL_PORT, t.tenantName, sqlfile) if meta.GetOceanbasePwd() != "" { pwd := strings.ReplaceAll(meta.GetOceanbasePwd(), "'", "'\"'\"'") str = fmt.Sprintf("%s -p'%s'", str, pwd) diff --git a/agent/executor/task/dag.go b/agent/executor/task/dag.go index fd5e33c8..5572e12c 100644 --- a/agent/executor/task/dag.go +++ b/agent/executor/task/dag.go @@ -27,6 +27,9 @@ import ( "github.com/oceanbase/obshell/agent/constant" "github.com/oceanbase/obshell/agent/engine/task" "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/executor/ob" + "github.com/oceanbase/obshell/agent/lib/http" + "github.com/oceanbase/obshell/agent/lib/path" "github.com/oceanbase/obshell/agent/meta" "github.com/oceanbase/obshell/agent/repository/db/oceanbase" "github.com/oceanbase/obshell/agent/secure" @@ -36,20 +39,20 @@ import ( // get dag detail by id // -// @ID getDagDetail -// @Summary get dag detail by id -// @Description get dag detail by id -// @Tags task -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param id path string true "id" -// @Param showDetails query param.TaskQueryParams true "show details" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 400 object http.OcsAgentResponse -// @Failure 404 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/task/dag/{id} [get] +// @ID getDagDetail +// @Summary get dag detail by id +// @Description get dag detail by id +// @Tags task +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param id path string true "id" +// @Param showDetails query param.TaskQueryParams true "show details" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 404 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/task/dag/{id} [get] func GetDagDetail(c *gin.Context) { var dagDTOParam task.DagDetailDTO var dagDetailDTO *task.DagDetailDTO @@ -67,6 +70,9 @@ func GetDagDetail(c *gin.Context) { } if agent != nil && !meta.OCS_AGENT.Equal(agent) { + if task.IsObproxyTask(dagDTOParam.GenericID) { + common.SendResponse(c, nil, errors.Occur(errors.ErrTaskNotFound, err)) + } if meta.OCS_AGENT.IsFollowerAgent() { // forward request to master master := agentService.GetMasterAgentInfo() @@ -113,10 +119,86 @@ func GetDagDetail(c *gin.Context) { return } + if task.ConvertToGenericID(dag, dag.GetDagType()) != dagDTOParam.GenericID { + common.SendResponse(c, nil, errors.Occur(errors.ErrTaskNotFound, "dag id not match")) + return + } dagDetailDTO, err = convertDagDetailDTO(dag, *param.ShowDetails) common.SendResponse(c, dagDetailDTO, err) } +// get all dags in cluster +// +// @ID getAllClusterDags +// @Summary get all dags in cluster +// @Description get all dags in cluster +// @Tags task +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse{data=[]task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 404 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/task/dags/ob [get] +func GetAllClusterDags(c *gin.Context) { + if !meta.OCS_AGENT.IsClusterAgent() { + common.SendResponse(c, nil, errors.Occur(errors.ErrBadRequest, "only cluster agent can get all cluster dags")) + return + } + + // TODO: distinguish between obproxy tasks and ob tasks + dags, err := clusterTaskService.GetAllDagInstances() + if err != nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrUnexpected, err)) + return + } + + dagDetailDTOs := make([]*task.DagDetailDTO, 0) + for _, dag := range dags { + dagDetailDTO, err := convertDagDetailDTO(dag, true) + if err != nil { + log.WithContext(common.NewContextWithTraceId(c)).Errorf("convert dag detail dto failed: %v", err) + continue + } + dagDetailDTOs = append(dagDetailDTOs, dagDetailDTO) + } + common.SendResponse(c, dagDetailDTOs, nil) +} + +// get all dags in agent +// +// @ID getAllAgentDags +// @Summary get all dags in the agent +// @Description get all dags in the agent +// @Tags task +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse{data=[]task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 404 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/task/dags/agent [get] +func GetAllAgentDags(c *gin.Context) { + dags, err := localTaskService.GetAllDagInstances() + if err != nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrUnexpected, err)) + return + } + + dagDetailDTOs := make([]*task.DagDetailDTO, 0) + for _, dag := range dags { + dagDetailDTO, err := convertDagDetailDTO(dag, true) + if err != nil { + log.WithContext(common.NewContextWithTraceId(c)).Errorf("convert dag detail dto failed: %v", err) + continue + } + dagDetailDTOs = append(dagDetailDTOs, dagDetailDTO) + } + common.SendResponse(c, dagDetailDTOs, nil) +} + func sendToTargetClusterAgentForScaleOut(c *gin.Context, dagDTO *task.DagDetailDTO) { // For scaling out agent, if the agent is nil, try to forward request to cluster agent. if _, err := oceanbase.GetOcsInstance(); err != nil { @@ -167,7 +249,7 @@ func convertDagDetailDTO(dag *task.Dag, fillDeatil bool) (dagDetailDTO *task.Dag return } - nodeDetailDTO, err = getNodeDetail(service, nodes[i]) + nodeDetailDTO, err = getNodeDetail(service, nodes[i], dag.GetDagType()) if err != nil { return } @@ -180,20 +262,20 @@ func convertDagDetailDTO(dag *task.Dag, fillDeatil bool) (dagDetailDTO *task.Dag // dag handler // -// @ID dagHandler -// @Summary operate dag -// @Description operate dag -// @Tags task -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param id path string true "dag id" -// @Param operator body string true "operator(rollback/retry/cancel/pass)" example({"operator": "rollback"}) -// @Success 200 object http.OcsAgentResponse -// @Failure 400 object http.OcsAgentResponse -// @Failure 404 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/task/dag/{id} [post] +// @ID dagHandler +// @Summary operate dag +// @Description operate dag +// @Tags task +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param id path string true "dag id" +// @Param body body task.DagOperator true "dag operator, supported values are (rollback/retry/cancel/pass)" +// @Success 200 object http.OcsAgentResponse +// @Failure 400 object http.OcsAgentResponse +// @Failure 404 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/task/dag/{id} [post] func DagHandler(c *gin.Context) { var dagOperator task.DagOperator var service taskservice.TaskServiceInterface @@ -215,6 +297,9 @@ func DagHandler(c *gin.Context) { } if agent != nil && !meta.OCS_AGENT.Equal(agent) { + if task.IsObproxyTask(dagOperator.GenericID) { + common.SendResponse(c, nil, errors.Occur(errors.ErrTaskNotFound, err)) + } if meta.OCS_AGENT.IsFollowerAgent() { // forward request to master master := agentService.GetMasterAgentInfo() @@ -241,6 +326,11 @@ func DagHandler(c *gin.Context) { return } + if task.ConvertToGenericID(dag, dag.GetDagType()) != dagOperator.GenericID { + common.SendResponse(c, nil, errors.Occur(errors.ErrTaskNotFound, "dag id not match")) + return + } + switch strings.ToUpper(dagOperator.Operator) { case task.ROLLBACK_STR: err = service.SetDagRollback(dag) @@ -261,17 +351,17 @@ func DagHandler(c *gin.Context) { common.SendResponse(c, nil, nil) } -// @ID GetObLastMaintenanceDag -// @Summary get ob last maintenance dag -// @Description get ob last maintenance dag -// @Tags task -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 404 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/task/dag/maintain/ob [get] +// @ID GetObLastMaintenanceDag +// @Summary get ob last maintenance dag +// @Description get ob last maintenance dag +// @Tags task +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 404 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/task/dag/maintain/ob [get] func GetObLastMaintenanceDag(c *gin.Context) { param := getTaskQueryParams(c) dag, err := clusterTaskService.FindLastMaintenanceDag() @@ -288,17 +378,17 @@ func GetObLastMaintenanceDag(c *gin.Context) { common.SendResponse(c, dagDetailDTO, err) } -// @ID GetAgentLastMaintenanceDag -// @Summary get agent last maintenance dag -// @Description get agent last maintenance dag -// @Tags task -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} -// @Failure 404 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/task/dag/maintain/agent [get] +// @ID GetAgentLastMaintenanceDag +// @Summary get agent last maintenance dag +// @Description get agent last maintenance dag +// @Tags task +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse{data=task.DagDetailDTO} +// @Failure 404 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/task/dag/maintain/agent [get] func GetAgentLastMaintenanceDag(c *gin.Context) { param := getTaskQueryParams(c) if meta.OCS_AGENT.IsMasterAgent() { @@ -326,18 +416,22 @@ func GetAgentLastMaintenanceDag(c *gin.Context) { common.SendResponse(c, dagDetailDTO, err) } -// @ID GetAllAgentsLastMaintenanceDag -// @Summary get agent last maintenance dag -// @Description get agent last maintenance dag -// @Tags task -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Success 200 object http.OcsAgentResponse{data=[]task.DagDetailDTO} -// @Failure 404 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/task/dag/maintain/agents [get] +// @ID GetAllAgentsLastMaintenanceDag +// @Summary get agent last maintenance dag +// @Description get agent last maintenance dag +// @Tags task +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse{data=[]task.DagDetailDTO} +// @Failure 404 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/task/dag/maintain/agents [get] func GetAllAgentLastMaintenanceDag(c *gin.Context) { + common.SendResponse(c, getAllAgentLastMaintenanceDag(c), nil) +} + +func getAllAgentLastMaintenanceDag(c *gin.Context) []*task.DagDetailDTO { param := getTaskQueryParams(c) dagDetailDTOs := make([]*task.DagDetailDTO, 0) dag, err := localTaskService.FindLastMaintenanceDag() @@ -366,20 +460,20 @@ func GetAllAgentLastMaintenanceDag(c *gin.Context) { dagDetailDTOs = append(dagDetailDTOs, dagDetailDTO) } } - common.SendResponse(c, dagDetailDTOs, nil) + return dagDetailDTOs } -// @ID GetUnfinishedDags -// @Summary get unfinished dags -// @Description get unfinished dags -// @Tags task -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param showDetails query param.TaskQueryParams true "show details" -// @Success 200 object http.OcsAgentResponse{data=[]task.DagDetailDTO} -// @Failure 400 object http.OcsAgentResponse -// @Router /api/v1/task/dag/unfinish [get] +// @ID GetUnfinishedDags +// @Summary get unfinished dags +// @Description get unfinished dags +// @Tags task +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param showDetails query param.TaskQueryParams true "show details" +// @Success 200 object http.OcsAgentResponse{data=[]task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Router /api/v1/task/dag/unfinish [get] func GetUnfinishedDags(c *gin.Context) { ctx := common.NewContextWithTraceId(c) switch meta.OCS_AGENT.GetIdentity() { @@ -409,18 +503,18 @@ func GetUnfinishedDags(c *gin.Context) { } } -// @ID GetClusterUnfinishDags -// @Summary get cluster unfinished dags -// @Description get cluster unfinished dags -// @Tags task -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param showDetails query param.TaskQueryParams true "show details" -// @Success 200 object http.OcsAgentResponse{data=[]task.DagDetailDTO} -// @Failure 400 object http.OcsAgentResponse -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/task/dag/ob/unfinish [get] +// @ID GetClusterUnfinishDags +// @Summary get cluster unfinished dags +// @Description get cluster unfinished dags +// @Tags task +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param showDetails query param.TaskQueryParams true "show details" +// @Success 200 object http.OcsAgentResponse{data=[]task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/task/dag/ob/unfinish [get] func GetClusterUnfinishDags(c *gin.Context) { if !meta.OCS_AGENT.IsClusterAgent() { common.SendResponse(c, nil, errors.Occur(errors.ErrBadRequest, "only cluster agent can get cluster unfinished dags")) @@ -432,17 +526,17 @@ func GetClusterUnfinishDags(c *gin.Context) { common.SendResponse(c, dagDetailDTOs, err) } -// @ID GetAgentUnfinishDags -// @Summary get agent unfinished dags -// @Description get agent unfinished dags -// @Tags task -// @Accept application/json -// @Produce application/json -// @Param X-OCS-Header header string true "Authorization" -// @Param showDetails query param.TaskQueryParams true "show details" -// @Success 200 object http.OcsAgentResponse{data=[]task.DagDetailDTO} -// @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/task/dag/agent/unfinish [get] +// @ID GetAgentUnfinishDags +// @Summary get agent unfinished dags +// @Description get agent unfinished dags +// @Tags task +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param showDetails query param.TaskQueryParams true "show details" +// @Success 200 object http.OcsAgentResponse{data=[]task.DagDetailDTO} +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/task/dag/agent/unfinish [get] func GetAgentUnfinishDags(c *gin.Context) { param := getTaskQueryParams(c) dagDetailDTOs, err := getAgentUnfinishDags(*param.ShowDetails) @@ -501,3 +595,45 @@ func convertDagDetailDTOs(dags []*task.Dag, fillDetails bool) (dagDetailDTOs []* } return } + +// @ID GetAgentMainDags +// @Summary get agent main dags +// @Description get agent main dags +// @Tags task +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Success 200 object http.OcsAgentResponse{data=[]task.DagDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 404 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/task/dag/agent/main_dags [get] +func GetAgentMainDags(c *gin.Context) { + mainDags := make([]*task.DagDetailDTO, 0) + allDags := getAllAgentLastMaintenanceDag(c) + mainDagIdMap := make(map[string]bool) + for _, dag := range allDags { + if dag.IsSucceed() { + continue + } + if dag.AdditionalData != nil { + data := *(dag.AdditionalData) + if mainDagid, ok := data[ob.ADDL_KEY_MAIN_DAG_ID].(string); ok { + if _, ok := mainDagIdMap[mainDagid]; ok { + continue + } + // Get Detail + var res task.DagDetailDTO + if err := http.SendGetRequestViaUnixSocket(path.ObshellSocketPath(), constant.URI_TASK_API_PREFIX+constant.URI_DAG+"/"+mainDagid, nil, &res); err != nil { + log.WithError(err).Errorf("get main dag %s detail failed", mainDagid) + continue + } else { + mainDags = append(mainDags, &res) + mainDagIdMap[mainDagid] = true + } + } + } + } + common.SendResponse(c, mainDags, nil) + return +} diff --git a/agent/executor/task/node.go b/agent/executor/task/node.go index e2a9b858..c8706779 100644 --- a/agent/executor/task/node.go +++ b/agent/executor/task/node.go @@ -60,6 +60,9 @@ func GetNodeDetail(c *gin.Context) { } if agent != nil && !meta.OCS_AGENT.Equal(agent) { + if task.IsObproxyTask(nodeDTOParam.GenericID) { + common.SendResponse(c, nil, errors.Occur(errors.ErrTaskNotFound, err)) + } if meta.OCS_AGENT.IsFollowerAgent() { // forward request to master master := agentService.GetMasterAgentInfo() @@ -86,6 +89,7 @@ func GetNodeDetail(c *gin.Context) { common.SendResponse(c, nil, errors.Occur(errors.ErrTaskNotFound, err)) return } + if *param.ShowDetails { _, err = service.GetSubTasks(node) if err != nil { @@ -93,7 +97,16 @@ func GetNodeDetail(c *gin.Context) { return } - nodeDetailDTO, err = getNodeDetail(service, node) + dag, err := service.GetDagInstance(int64(node.GetDagId())) + if err != nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrUnexpected, err)) + return + } + if task.ConvertToGenericID(dag, dag.GetDagType())[0] != nodeDTOParam.GenericID[0] { + common.SendResponse(c, nil, errors.Occur(errors.ErrTaskNotFound, "node type not match")) + return + } + nodeDetailDTO, err = getNodeDetail(service, node, dag.GetDagType()) if err != nil { common.SendResponse(c, nil, errors.Occur(errors.ErrUnexpected, err)) return @@ -103,12 +116,12 @@ func GetNodeDetail(c *gin.Context) { common.SendResponse(c, nodeDetailDTO, nil) } -func getNodeDetail(service taskservice.TaskServiceInterface, node *task.Node) (nodeDetailDTO *task.NodeDetailDTO, err error) { - nodeDetailDTO = task.NewNodeDetailDTO(node) +func getNodeDetail(service taskservice.TaskServiceInterface, node *task.Node, dagType string) (nodeDetailDTO *task.NodeDetailDTO, err error) { + nodeDetailDTO = task.NewNodeDetailDTO(node, dagType) subTasks := node.GetSubTasks() n := len(subTasks) for i := 0; i < n; i++ { - taskDetailDTO, err := getSubTaskDetail(service, subTasks[i]) + taskDetailDTO, err := getSubTaskDetail(service, subTasks[i], dagType) if err != nil { return nil, err } diff --git a/agent/executor/task/sub_task.go b/agent/executor/task/sub_task.go index 5d0b4e44..78f7c4ca 100644 --- a/agent/executor/task/sub_task.go +++ b/agent/executor/task/sub_task.go @@ -59,6 +59,9 @@ func GetSubTaskDetail(c *gin.Context) { } if agent != nil && !meta.OCS_AGENT.Equal(agent) { + if task.IsObproxyTask(taskDTOParam.GenericID) { + common.SendResponse(c, nil, errors.Occur(errors.ErrTaskNotFound, err)) + } if meta.OCS_AGENT.IsFollowerAgent() { // forward request to master master := agentService.GetMasterAgentInfo() @@ -85,7 +88,22 @@ func GetSubTaskDetail(c *gin.Context) { return } - taskDetailDTO, err = getSubTaskDetail(service, subTask) + dagType := "" + if subTask.IsLocalTask() { + dag, err := service.GetDagBySubTaskId(subTask.GetID()) + if err != nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrTaskNotFound, err)) + return + } + dagType = dag.GetDagType() + if task.ConvertToGenericID(dag, dag.GetDagType())[0] != taskDTOParam.GenericID[0] { + common.SendResponse(c, nil, errors.Occur(errors.ErrTaskNotFound, "sub task type not match")) + return + } + + } + + taskDetailDTO, err = getSubTaskDetail(service, subTask, dagType) if err != nil { common.SendResponse(c, nil, errors.Occur(errors.ErrUnexpected, err)) return @@ -94,10 +112,73 @@ func GetSubTaskDetail(c *gin.Context) { common.SendResponse(c, taskDetailDTO, nil) } -func getSubTaskDetail(service taskservice.TaskServiceInterface, subTask task.ExecutableTask) (taskDetailDTO *task.TaskDetailDTO, err error) { - taskDetailDTO = task.NewTaskDetailDTO(subTask) +func getSubTaskDetail(service taskservice.TaskServiceInterface, subTask task.ExecutableTask, dagType string) (taskDetailDTO *task.TaskDetailDTO, err error) { + taskDetailDTO = task.NewTaskDetailDTO(subTask, dagType) if subTask.IsRunning() || subTask.IsFinished() { taskDetailDTO.TaskLogs, err = service.GetSubTaskLogsByTaskID(subTask.GetID()) } return } + +// get full sub_task logs by id +// +// @ID getFullSubTaskLogs +// @Summary get full sub_task logs by sub_task_id +// @Description get full sub_task logs by sub_task_id +// @Tags task +// @Accept application/json +// @Produce application/json +// @Param X-OCS-Header header string true "Authorization" +// @Param id path string true "id" +// @Success 200 object http.OcsAgentResponse{data=task.TaskDetailDTO} +// @Failure 400 object http.OcsAgentResponse +// @Failure 404 object http.OcsAgentResponse +// @Failure 500 object http.OcsAgentResponse +// @Router /api/v1/task/sub_task/{id}/logs [get] +func GetFullSubTaskLogs(c *gin.Context) { + var taskDTOParam task.TaskDetailDTO + var service taskservice.TaskServiceInterface + + if err := c.BindUri(&taskDTOParam); err != nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrIllegalArgument, err)) + return + } + + taskID, agent, err := task.ConvertGenericID(taskDTOParam.GenericID) + if err != nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrIllegalArgument, err)) + return + } + + if agent != nil && !meta.OCS_AGENT.Equal(agent) { + if task.IsObproxyTask(taskDTOParam.GenericID) { + common.SendResponse(c, nil, errors.Occur(errors.ErrTaskNotFound, err)) + } + if meta.OCS_AGENT.IsFollowerAgent() { + // forward request to master + master := agentService.GetMasterAgentInfo() + if master == nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrBadRequest, "Master Agent is not found")) + return + } + common.ForwardRequest(c, master, nil) + } else { + common.ForwardRequest(c, agent, nil) + } + return + } + + if agent == nil { + service = clusterTaskService + } else { + service = localTaskService + } + + subTaskLogs, err := service.GetFullSubTaskLogsByTaskID(taskID) + if err != nil { + common.SendResponse(c, nil, errors.Occur(errors.ErrUnexpected, err)) + return + } + + common.SendResponse(c, subTaskLogs, nil) +} diff --git a/agent/executor/tenant/compaction.go b/agent/executor/tenant/compaction.go new file mode 100644 index 00000000..d6a1d96f --- /dev/null +++ b/agent/executor/tenant/compaction.go @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tenant + +import ( + "sort" + "time" + + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/repository/model/bo" +) + +func GetTenantCompaction(tenantName string) (*bo.TenantCompaction, *errors.OcsAgentError) { + tenant, err := tenantService.GetTenantByName(tenantName) + if err != nil { + return nil, errors.Occurf(errors.ErrUnexpected, "Get tenant '%s' failed.", tenantName) + } + if tenant == nil { + return nil, errors.Occurf(errors.ErrBadRequest, "Tenant '%s' is not exist.", tenantName) + } + tenantCompaction, err := tenantService.GetTenantCompaction(tenant.TenantID) + if err != nil { + return nil, errors.Occurf(errors.ErrUnexpected, err.Error()) + } + return tenantCompaction.ToBO(), nil +} + +func TenantMajorCompaction(tenantName string) *errors.OcsAgentError { + tenant, err := tenantService.GetTenantByName(tenantName) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Get tenant '%s' failed.", tenantName) + } + if tenant == nil { + return errors.Occurf(errors.ErrBadRequest, "Tenant '%s' is not exist.", tenantName) + } + + tenantCompaction, err := tenantService.GetTenantCompaction(tenant.TenantID) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, err.Error()) + } + if tenantCompaction.Status != "IDLE" { + return errors.Occurf(errors.ErrIllegalArgument, "Tenant '%s' is in '%s' status, operation not allowed", tenantName, tenantCompaction.Status) + } + + err = tenantService.TenantMajorCompaction(tenantName) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, err.Error()) + } + return nil +} + +func ClearTenantCompactionError(tenantName string) *errors.OcsAgentError { + if err := tenantService.ClearTenantCompactionError(tenantName); err != nil { + return errors.Occurf(errors.ErrUnexpected, err.Error()) + } + return nil +} + +func GetTopCompactions(top int) ([]bo.TenantCompactionHistory, *errors.OcsAgentError) { + tenantCompactions, err := tenantService.GetAllMajorCompactions() + if err != nil { + return nil, errors.Occurf(errors.ErrUnexpected, err.Error()) + } + tenantIdToNameMap, err := tenantService.GetAllNotMetaTenantIdToNameMap() + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + tenantCompactionHistories := make([]bo.TenantCompactionHistory, 0) + for _, tenantCompaction := range tenantCompactions { + tenantName, ok := tenantIdToNameMap[tenantCompaction.TenantId] + if !ok { + continue + } + tenantCompactionHistory := bo.TenantCompactionHistory{ + TenantId: tenantCompaction.TenantId, + StartTime: tenantCompaction.StartTime, + LastFinishTime: tenantCompaction.LastFinishTime, + Status: tenantCompaction.Status, + TenantName: tenantName, + } + if !tenantCompactionHistory.StartTime.After(tenantCompactionHistory.LastFinishTime) { + tenantCompactionHistory.CostTime = int64(tenantCompactionHistory.LastFinishTime.Sub(tenantCompactionHistory.StartTime) / time.Second) + } else { + timeNow, err := obclusterService.GetCurrentTimestamp() + if err != nil { + return nil, errors.Occurf(errors.ErrUnexpected, err.Error()) + } + tenantCompactionHistory.CostTime = int64(timeNow.Sub(tenantCompactionHistory.StartTime) / time.Second) + } + tenantCompactionHistories = append(tenantCompactionHistories, tenantCompactionHistory) + } + // sort by cost time + sort.Slice(tenantCompactionHistories, func(i, j int) bool { + return tenantCompactionHistories[i].CostTime > tenantCompactionHistories[j].CostTime + }) + if len(tenantCompactionHistories) > top { + tenantCompactionHistories = tenantCompactionHistories[:top] + } + return tenantCompactionHistories, nil +} diff --git a/agent/executor/tenant/create_tenant.go b/agent/executor/tenant/create_tenant.go index 89f07dbc..70bc9cfc 100644 --- a/agent/executor/tenant/create_tenant.go +++ b/agent/executor/tenant/create_tenant.go @@ -31,6 +31,8 @@ import ( "github.com/oceanbase/obshell/agent/executor/pool" "github.com/oceanbase/obshell/agent/executor/script" "github.com/oceanbase/obshell/agent/executor/zone" + "github.com/oceanbase/obshell/agent/lib/path" + "github.com/oceanbase/obshell/agent/meta" tenantservice "github.com/oceanbase/obshell/agent/service/tenant" "github.com/oceanbase/obshell/param" "github.com/oceanbase/obshell/utils" @@ -101,7 +103,7 @@ func checkParameters(parameters map[string]interface{}) error { return nil } -func checkScenario(scenario string) error { +func checkAndLoadScenario(param *param.CreateTenantParam, scenario string) error { if scenario == "" { return nil } @@ -110,10 +112,30 @@ func checkScenario(scenario string) error { if len(scenarios) == 0 { return errors.New("current observer does not support scenario") } - if utils.ContainsString(scenarios, strings.ToLower(scenario)) { - return nil + if !utils.ContainsString(scenarios, strings.ToLower(scenario)) { + errors.Errorf("scenario only support to be one of %s", strings.Join(scenarios, ", ")) + } + + variables, err := parseTemplate(VARIABLES_TEMPLATE, path.ObshellDefaultVariablePath(), scenario) + if err != nil { + return errors.Wrap(err, "Parse variable template failed") + } + for key, value := range variables { + if _, exist := param.Variables[key]; !exist { + param.Variables[key] = value + } + } + + parameters, err := parseTemplate(PARAMETERS_TEMPLATE, path.ObshellDefaultParameterPath(), scenario) + if err != nil { + return errors.Wrap(err, "Parse parameter template failed") + } + for key, value := range parameters { + if _, exist := param.Parameters[key]; !exist { + param.Parameters[key] = value + } } - return errors.Errorf("scenario only support to be one of %s", strings.Join(scenarios, ", ")) + return nil } func renderCreateTenantParam(param *param.CreateTenantParam) error { @@ -182,10 +204,6 @@ func checkCreateTenantParam(param *param.CreateTenantParam) (err error) { return } - if err = checkScenario(param.Scenario); err != nil { - return - } - if err = checkCharsetAndCollation(param.Charset, param.Collation); err != nil { return } @@ -206,6 +224,10 @@ func checkCreateTenantParam(param *param.CreateTenantParam) (err error) { return } + if err = checkAndLoadScenario(param, param.Scenario); err != nil { + return + } + return nil } @@ -226,7 +248,7 @@ func checkTenantName(name string) error { } func checkZoneResourceForUnit(zone string, unitName string, unitNum int) error { - source, err := tenantService.GetObServerCapacityByZone(zone) + source, err := obclusterService.GetObserverCapacityByZone(zone) if err != nil { return errors.New("Get servers's info failed.") } @@ -245,18 +267,20 @@ func checkZoneResourceForUnit(zone string, unitName string, unitNum int) error { if err != nil { return err } - log.Infof("server %s:%d used resource: %v", server.SvrIp, server.SvrPort, gatheredUnitInfo) + + serverStr := meta.NewAgentInfo(server.SvrIp, server.SvrPort).String() + log.Infof("server %s used resource: %v", serverStr, gatheredUnitInfo) if server.CpuCapacity-gatheredUnitInfo.MinCpu < unit.MinCpu || server.CpuCapacityMax-gatheredUnitInfo.MaxCpu < unit.MaxCpu { - checkErr = errors.Errorf("server %s:%d CPU resource not enough", server.SvrIp, server.SvrPort) + checkErr = errors.Errorf("server %s CPU resource not enough", serverStr) continue } if server.MemCapacity-gatheredUnitInfo.MemorySize < unit.MemorySize { - checkErr = errors.Errorf("server %s:%d MEMORY_SIZE resource not enough", server.SvrIp, server.SvrPort) + checkErr = errors.Errorf("server %s MEMORY_SIZE resource not enough", serverStr) continue } if server.LogDiskCapacity-gatheredUnitInfo.LogDiskSize < unit.LogDiskSize { - checkErr = errors.Errorf("server %s:%d LOG_DISK_SIZE resource not enough", server.SvrIp, server.SvrPort) + checkErr = errors.Errorf("server %s LOG_DISK_SIZE resource not enough", serverStr) continue } validServer += 1 @@ -270,14 +294,14 @@ func checkZoneResourceForUnit(zone string, unitName string, unitNum int) error { type gatheredUnitInfo struct { MinCpu float64 MaxCpu float64 - MemorySize int - LogDiskSize int + MemorySize int64 + LogDiskSize int64 } func gatherAllUnitsOnServer(svrIp string, svrPort int) (*gatheredUnitInfo, error) { units, err := obclusterService.GetObUnitsOnServer(svrIp, svrPort) if err != nil { - return nil, errors.Errorf("Get all units on server %s:%d failed.", svrIp, svrPort) + return nil, errors.Errorf("Get all units on server %s failed.", meta.NewAgentInfo(svrIp, svrPort).String()) } used := &gatheredUnitInfo{} for _, unit := range units { @@ -320,7 +344,7 @@ func CreateTenant(param *param.CreateTenantParam) (*task.DagDetailDTO, *errors.O } // Create 'Create tenant' dag instance. - template, err := buildCreateTenatDagTemplate(param) + template, err := buildCreateTenantDagTemplate(param) if err != nil { return nil, errors.Occur(errors.ErrUnexpected, err.Error()) } @@ -332,7 +356,7 @@ func CreateTenant(param *param.CreateTenantParam) (*task.DagDetailDTO, *errors.O return task.NewDagDetailDTO(dag), nil } -func buildCreateTenatDagTemplate(param *param.CreateTenantParam) (*task.Template, error) { +func buildCreateTenantDagTemplate(param *param.CreateTenantParam) (*task.Template, error) { createTenantNode, err := newCreateTenantNode(param) if err != nil { return nil, err @@ -344,13 +368,24 @@ func buildCreateTenatDagTemplate(param *param.CreateTenantParam) (*task.Template templateBuilder.AddNode(newSetTenantTimeZoneNode(param.TimeZone)) } if param.Parameters != nil && len(param.Parameters) != 0 { - templateBuilder.AddTask(newSetTenantParameterTask(), false) - } - if param.Scenario != "" { - templateBuilder.AddNode(newOptimizeTenantNode(param.Scenario, param)) + templateBuilder.AddNode(newSetTenantParameterNode(param.Parameters)) } templateBuilder.AddNode(newModifyTenantWhitelistNode(*param.Whitelist)) + // Delete the read-only variables + for k := range param.Variables { + if utils.ContainsString(constant.CREATE_TENANT_STATEMENT_VARIABLES, k) { + delete(param.Variables, k) + } + } + if param.Variables != nil && len(param.Variables) != 0 { + node, err := newSetTenantVariableNode(param.Variables) + if err != nil { + return nil, err + } + templateBuilder.AddNode(node) + } + agents, err := agentService.GetAllAgentsInfo() if err != nil { return nil, err @@ -366,13 +401,13 @@ func buildCreateTenatDagTemplate(param *param.CreateTenantParam) (*task.Template } templateBuilder.AddNode(setRootPwdNode) } + return templateBuilder.Build(), nil } func buildCreateTenantDagContext(param *param.CreateTenantParam) *task.TaskContext { context := task.NewTaskContext() context.SetParam(PARAM_TENANT_NAME, param.Name). - SetParam(PARAM_TENANT_PARAMETER, param.Parameters). SetParam(task.FAILURE_EXIT_MAINTENANCE, true) return context } @@ -414,7 +449,7 @@ func newCreateTenantTask() *CreateTenantTask { return newTask } -func buildCreateTenantSql(param param.CreateTenantParam, poolList []string) (string, []interface{}) { +func buildCreateTenantSql(param *param.CreateTenantParam, poolList []string) (string, []interface{}) { resourcePoolList := "\"" + strings.Join(poolList, "\",\"") + "\"" sql := fmt.Sprintf(tenantservice.SQL_CREATE_TENANT_BASIC, *param.Name, resourcePoolList) @@ -462,13 +497,16 @@ func buildCreateTenantSql(param param.CreateTenantParam, poolList []string) (str transferNumber(param.Variables) for k, v := range param.Variables { - if _, ok := v.(string); ok { - sql += ", " + k + "= `%s`" - } else { - sql += ", " + k + "= %v" + if utils.ContainsString(constant.CREATE_TENANT_STATEMENT_VARIABLES, k) { + if _, ok := v.(string); ok { + sql += ", " + k + "= `%s`" + } else { + sql += ", " + k + "= %v" + } + input = append(input, v) } - input = append(input, v) } + return sql, input } @@ -490,7 +528,7 @@ func (t *CreateTenantTask) Execute() error { for _, poolParam := range t.createResourcePoolParam { poolList = append(poolList, poolParam.PoolName) } - basic, input := buildCreateTenantSql(t.CreateTenantParam, poolList) + basic, input := buildCreateTenantSql(&t.CreateTenantParam, poolList) sql := fmt.Sprintf(basic, input...) t.ExecuteLogf("Create tenant sql: %s", sql) if err := tenantService.TryExecute(sql); err != nil { diff --git a/agent/executor/tenant/database.go b/agent/executor/tenant/database.go new file mode 100644 index 00000000..f61e9011 --- /dev/null +++ b/agent/executor/tenant/database.go @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tenant + +import ( + "fmt" + "strings" + + "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/meta" + "github.com/oceanbase/obshell/agent/repository/model/bo" + "github.com/oceanbase/obshell/param" +) + +func DeleteDatabase(tenantName, databaseName string, password *string) *errors.OcsAgentError { + db, err := GetConnectionWithPassword(tenantName, password) + defer CloseDbConnection(db) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to get db connection of tenant %s, err: %s", tenantName, err.Error()) + } + err = tenantService.DropDatabase(db, databaseName) + if err != nil { + errors.Occurf(errors.ErrUnexpected, "Failed to drop database %s of tenant %s", databaseName, tenantName) + } + return nil +} + +func CreateDatabase(tenantName string, param *param.CreateDatabaseParam) *errors.OcsAgentError { + db, err := GetConnectionWithPassword(tenantName, param.RootPassword) + defer CloseDbConnection(db) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to get db connection of tenant %s, err: %s", tenantName, err.Error()) + } + err = tenantService.CreateDatabase(db, param) + if err != nil { + errors.Occurf(errors.ErrUnexpected, "Failed to create database %s of tenant %s", param.DbName, tenantName) + } + return nil +} + +func AlterDatabase(tenantName string, databaseName string, param *param.ModifyDatabaseParam) *errors.OcsAgentError { + if param.Collation == nil && param.ReadOnly == nil { + return nil + } + db, err := GetConnectionWithPassword(tenantName, param.RootPassword) + defer CloseDbConnection(db) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to get db connection of tenant %s, err: %s", tenantName, err.Error()) + } + err = tenantService.AlterDatabase(db, databaseName, param) + if err != nil { + errors.Occurf(errors.ErrUnexpected, "Failed to modify database %s of tenant %s", databaseName, tenantName) + } + return nil +} + +func GetDatabase(tenantName, databaseName string, password *string) (*bo.Database, *errors.OcsAgentError) { + databases, err := ListDatabases(tenantName, password) + if err != nil { + return nil, err + } + for _, database := range databases { + if database.DbName == databaseName { + return &database, nil + } + } + return nil, errors.Occurf(errors.ErrNotFound, "Database %s of tenant %s", databaseName, tenantName) +} + +func ListDatabases(tenantName string, password *string) ([]bo.Database, *errors.OcsAgentError) { + db, err := GetConnectionWithPassword(tenantName, password) + defer CloseDbConnection(db) + if err != nil { + return nil, errors.Occurf(errors.ErrUnexpected, "Failed to get db connection of tenant %s, err: %s", tenantName, err.Error()) + } + databases, err := tenantService.ListDatabases(db) + if err != nil { + return nil, errors.Occurf(errors.ErrUnexpected, "Failed to list databases of tenant %s, err: %s", tenantName, err.Error()) + } + obdatabases := make([]bo.Database, 0) + for _, database := range databases { + connectionUrl := bo.ObproxyAndConnectionString{ + Type: constant.OB_CONNECTION_TYPE_DIRECT, + ConnectionString: fmt.Sprintf("jdbc:mysql://%s:%d/%s", meta.OCS_AGENT.GetIp(), meta.MYSQL_PORT, database.Name), + } + obdatabase := bo.Database{ + DbName: database.Name, + Charset: database.CharSetName, + Collation: database.CollationName, + ReadOnly: strings.HasPrefix(strings.ToUpper(database.ReadOnly), "Y"), + CreateTime: database.CreateTimestamp, + ConnectionUrls: []bo.ObproxyAndConnectionString{connectionUrl}, + } + obdatabases = append(obdatabases, obdatabase) + } + return obdatabases, nil +} diff --git a/agent/executor/tenant/enter.go b/agent/executor/tenant/enter.go index bf83c0df..2840a654 100644 --- a/agent/executor/tenant/enter.go +++ b/agent/executor/tenant/enter.go @@ -39,9 +39,7 @@ var ( const ( // task param name PARAM_CREATE_TENANT = "createTenant" - PARAM_OPTIMIZE_TENANT = "optimizeTenant" - PARAM_CREATE_TENANT_VARIABLES = "createTenantVariables" - PARAM_CREATE_TENANT_PARAMETERS = "createTenantParameters" + PARAM_TENANT_VARIABLES = "tenantVariables" PARAM_TENANT_NAME = "tenantName" PARAM_TENANT_TIME_ZONE = "timeZone" PARAM_TENANT_ID = "tenantId" @@ -74,6 +72,7 @@ const ( TASK_NAME_MODIFY_PRIMARY_ZONE = "Modify tenant primary zone" TASK_NAME_SET_ROOT_PWD = "Set root password" TASK_NAME_SET_TENANT_PARAM = "Set tenant parameters" + TASK_NAME_SET_TENANT_VARIABLE = "Set tenant variables" TASK_NAME_DROP_RESOURCE_POOL = "Drop resource pools" TASK_NAME_SET_TENANT_PARAMETER = "Set tenant parameter" TASK_NAME_DROP_TENANT = "Drop tenant" @@ -110,7 +109,7 @@ const ( PARAMETERS_TEMPLATE = "parameters" ) -func checkTenantExistAndStatus(name string) (*oceanbase.DbaObTenant, *errors.OcsAgentError) { +func checkTenantExist(name string) (*oceanbase.DbaObTenant, *errors.OcsAgentError) { tenant, err := tenantService.GetTenantByName(name) if err != nil { return tenant, errors.Occurf(errors.ErrUnexpected, "Get tenant '%s' failed.", name) @@ -118,6 +117,14 @@ func checkTenantExistAndStatus(name string) (*oceanbase.DbaObTenant, *errors.Ocs if tenant == nil { return tenant, errors.Occurf(errors.ErrBadRequest, "Tenant '%s' is not exist.", name) } + return tenant, nil +} + +func checkTenantExistAndStatus(name string) (*oceanbase.DbaObTenant, *errors.OcsAgentError) { + tenant, err := checkTenantExist(name) + if err != nil { + return tenant, err + } if tenant.Status != NORMAL_TENANT { return tenant, errors.Occurf(errors.ErrKnown, "Tenant '%s' status is '%s'.", name, tenant.Status) } @@ -136,7 +143,7 @@ func RegisterTenantTask() { task.RegisterTaskType(SetRootPwdTask{}) task.RegisterTaskType(SetTenantTimeZoneTask{}) task.RegisterTaskType(SetTenantParamterTask{}) - task.RegisterTaskType(OptimizeTenantTask{}) + task.RegisterTaskType(SetTenantVariableTask{}) task.RegisterTaskType(DropTenantTask{}) task.RegisterTaskType(RecycleTenantTask{}) task.RegisterTaskType(BatchCreateResourcePoolTask{}) diff --git a/agent/executor/tenant/info.go b/agent/executor/tenant/info.go index 37165a7c..fc513640 100644 --- a/agent/executor/tenant/info.go +++ b/agent/executor/tenant/info.go @@ -17,21 +17,49 @@ package tenant import ( + "fmt" + "strconv" + + "github.com/oceanbase/obshell/agent/constant" "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/meta" "github.com/oceanbase/obshell/agent/repository/model/bo" "github.com/oceanbase/obshell/agent/repository/model/oceanbase" ) -func GetTenantsOverView() ([]oceanbase.DbaObTenant, *errors.OcsAgentError) { - tenants, err := tenantService.GetTenantsOverView() +func GetTenantsOverView(mode string) ([]oceanbase.TenantOverview, *errors.OcsAgentError) { + if mode != "" && mode != constant.MYSQL_MODE && mode != constant.ORACAL_MODE { + return nil, errors.Occur(errors.ErrBadRequest, "mode should be mysql or oracle") + } + tenants, err := tenantService.GetTenantsOverViewByMode(mode) if err != nil { return nil, errors.Occur(errors.ErrUnexpected, err.Error()) } - return tenants, nil + tenantOverviews := make([]oceanbase.TenantOverview, 0) + for i := range tenants { + connectionStr := bo.ObproxyAndConnectionString{ + Type: constant.OB_CONNECTION_TYPE_DIRECT, + ConnectionString: fmt.Sprintf("obclient -h%s -P%d -uroot@%s -p", meta.OCS_AGENT.GetIp(), meta.MYSQL_PORT, tenants[i].TenantName), + } + connectionStrs := make([]bo.ObproxyAndConnectionString, 0) + connectionStrs = append(connectionStrs, connectionStr) + readOnly, err := tenantService.GetTenantVariable(tenants[i].TenantName, constant.VARIABLE_READ_ONLY) + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + if readOnly != nil { + tenants[i].ReadOnly = (readOnly.Value == "1") + } + tenantOverviews = append(tenantOverviews, oceanbase.TenantOverview{ + DbaObTenant: tenants[i], + ConnectionStrings: connectionStrs, + }) + } + return tenantOverviews, nil } func GetTenantInfo(tenantName string) (*bo.TenantInfo, *errors.OcsAgentError) { - tenant, ocsErr := checkTenantExistAndStatus(tenantName) + tenant, ocsErr := checkTenantExist(tenantName) if ocsErr != nil { return nil, ocsErr } @@ -40,9 +68,6 @@ func GetTenantInfo(tenantName string) (*bo.TenantInfo, *errors.OcsAgentError) { if err != nil { return nil, errors.Occur(errors.ErrUnexpected, err.Error()) } - if whitelist == nil { - return nil, errors.Occur(errors.ErrUnexpected, nil) - } pools := make([]*bo.ResourcePoolWithUnit, 0) poolInfos, err := tenantService.GetTenantResourcePool(tenant.TenantID) @@ -65,17 +90,52 @@ func GetTenantInfo(tenantName string) (*bo.TenantInfo, *errors.OcsAgentError) { pools = append(pools, &poolWithUnit) } - return &bo.TenantInfo{ - Name: tenant.TenantName, - Id: tenant.TenantID, - CreatedTime: tenant.CreatedTime, - Mode: tenant.Mode, - Status: tenant.Status, - Locked: tenant.Locked, - PrimaryZone: tenant.PrimaryZone, - Locality: tenant.Locality, - InRecyclebin: tenant.InRecyclebin, - Whitelist: whitelist.Value, - Pools: pools, - }, nil + readOnly, err := tenantService.GetTenantVariable(tenantName, constant.VARIABLE_READ_ONLY) + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + + connectionStr := bo.ObproxyAndConnectionString{ + Type: constant.OB_CONNECTION_TYPE_DIRECT, + // the host may be not in the tcp_invited_nodes + ConnectionString: fmt.Sprintf("obclient -h%s -P%d -uroot@%s -p", meta.OCS_AGENT.GetIp(), meta.MYSQL_PORT, tenantName), + } + + tenantInfo := &bo.TenantInfo{ + Name: tenant.TenantName, + Id: tenant.TenantID, + CreatedTime: tenant.CreatedTime, + Mode: tenant.Mode, + Status: tenant.Status, + Locked: tenant.Locked, + PrimaryZone: tenant.PrimaryZone, + Locality: tenant.Locality, + InRecyclebin: tenant.InRecyclebin, + Pools: pools, + ConnectionStrings: []bo.ObproxyAndConnectionString{connectionStr}, + } + + charset, err := tenantService.GetTenantVariable(tenantName, "CHARACTER_SET_SERVER") + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + collatoinMap, err := obclusterService.GetCollationMap() + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + if charset != nil && collatoinMap != nil { + id, _ := strconv.Atoi(charset.Value) + collation, ok := collatoinMap[id] + if ok { + tenantInfo.Collation = collation.Collation + tenantInfo.Charset = collation.Charset + } + } + if whitelist != nil { + tenantInfo.Whitelist = whitelist.Value + } + if readOnly != nil { + tenantInfo.ReadOnly = (readOnly.Value == "1") + } + return tenantInfo, nil } diff --git a/agent/executor/tenant/modify_replicas.go b/agent/executor/tenant/modify_replicas.go index a741966c..36e2a579 100644 --- a/agent/executor/tenant/modify_replicas.go +++ b/agent/executor/tenant/modify_replicas.go @@ -83,14 +83,13 @@ func checkModifyReplicaZoneParams(tenant *oceanbase.DbaObTenant, param []param.M } } - if unitNum != 0 && nums != replicaNum { - return errors.New("Could not modify unit num partially.") - } - currentUnitNum, err := tenantService.GetTenantUnitNum(tenant.TenantID) if err != nil { return err } + if unitNum != 0 && nums != replicaNum && unitNum != currentUnitNum { + return errors.New("Could not modify unit num partially.") + } if unitNum != 0 && unitNum != currentUnitNum { // Check if enable_rebalance is true. if enableRebalance, err := tenantService.GetTenantParameter(tenant.TenantID, constant.PARAMETER_ENABLE_REBALANCE); err != nil { diff --git a/agent/executor/tenant/optimize.go b/agent/executor/tenant/optimize.go index 3f299015..b55d610f 100644 --- a/agent/executor/tenant/optimize.go +++ b/agent/executor/tenant/optimize.go @@ -20,37 +20,10 @@ import ( "io" "os" - "github.com/oceanbase/obshell/agent/engine/task" - "github.com/oceanbase/obshell/agent/errors" "github.com/oceanbase/obshell/agent/lib/json" "github.com/oceanbase/obshell/agent/lib/path" - "github.com/oceanbase/obshell/param" ) -type OptimizeTenantTask struct { - task.Task - tenantId int - template string - createTenantVariables map[string]interface{} - createTenantParameters map[string]interface{} -} - -func newOptimizeTenantTask() *OptimizeTenantTask { - newTask := &OptimizeTenantTask{ - Task: *task.NewSubTask(TASK_NAME_OPTIMIZE_TENANT), - } - newTask.SetCanRollback().SetCanRetry().SetCanCancel().SetCanContinue().SetCanPass() - return newTask -} - -func newOptimizeTenantNode(template string, createTenantParam *param.CreateTenantParam) *task.Node { - context := task.NewTaskContext(). - SetParam(PARAM_OPTIMIZE_TENANT, template). - SetParam(PARAM_CREATE_TENANT_VARIABLES, createTenantParam.Variables). - SetParam(PARAM_CREATE_TENANT_PARAMETERS, createTenantParam.Parameters) - return task.NewNodeWithContext(newOptimizeTenantTask(), false, context) -} - func getAllSupportedScenarios() (scenarios []string) { if _, err := os.Stat(path.ObshellDefaultVariablePath()); err != nil { return @@ -156,52 +129,3 @@ func parseTemplate(templateType, filepath, scenario string) (map[string]interfac } return res, nil } - -func (t *OptimizeTenantTask) Execute() error { - if err := t.GetContext().GetParamWithValue(PARAM_TENANT_ID, &t.tenantId); err != nil { - return errors.Wrap(err, "Get tenant id failed") - } - if err := t.GetContext().GetParamWithValue(PARAM_OPTIMIZE_TENANT, &t.template); err != nil { - return errors.Wrap(err, "Get template failed") - } - if err := t.GetContext().GetParamWithValue(PARAM_CREATE_TENANT_VARIABLES, &t.createTenantVariables); err != nil { - return errors.Wrap(err, "Get create tenant variables failed") - } - if err := t.GetContext().GetParamWithValue(PARAM_CREATE_TENANT_PARAMETERS, &t.createTenantParameters); err != nil { - return errors.Wrap(err, "Get create tenant parameters failed") - } - - tenantName, err := tenantService.GetTenantName(t.tenantId) - if err != nil { - return errors.Wrap(err, "Get tenant name failed") - } - - variables, err := parseTemplate(VARIABLES_TEMPLATE, path.ObshellDefaultVariablePath(), t.template) - if err != nil { - return errors.Wrap(err, "Parse variable template failed") - } - for key := range t.createTenantVariables { - delete(variables, key) - } - transferNumber(variables) - t.ExecuteLogf("optimize variables: %v\n", variables) - - parameters, err := parseTemplate(PARAMETERS_TEMPLATE, path.ObshellDefaultParameterPath(), t.template) - if err != nil { - return errors.Wrap(err, "Parse parameter template failed") - } - for key := range t.createTenantParameters { - delete(parameters, key) - } - transferNumber(parameters) - t.ExecuteLogf("optimize parameters: %v\n", parameters) - - if err = tenantService.SetTenantVariables(tenantName, variables); err != nil { - return errors.Wrap(err, "Set tenant variables failed") - } - - if err = tenantService.SetTenantParameters(tenantName, parameters); err != nil { - return errors.Wrap(err, "Set tenant parameters failed") - } - return nil -} diff --git a/agent/executor/tenant/parameter.go b/agent/executor/tenant/parameter.go index 4729e11c..02534bfd 100644 --- a/agent/executor/tenant/parameter.go +++ b/agent/executor/tenant/parameter.go @@ -34,6 +34,7 @@ func GetTenantParameters(tenantName string, filter string) ([]oceanbase.GvObPara if err != nil { return nil, errors.Occur(errors.ErrUnexpected, err.Error()) } + return parameters, nil } @@ -75,6 +76,12 @@ type SetTenantParamterTask struct { tenantId int } +func newSetTenantParameterNode(parameters map[string]interface{}) *task.Node { + subtask := newSetTenantParameterTask() + ctx := task.NewTaskContext().SetParam(PARAM_TENANT_PARAMETER, parameters) + return task.NewNodeWithContext(subtask, false, ctx) +} + func newSetTenantParameterTask() *SetTenantParamterTask { newTask := &SetTenantParamterTask{ Task: *task.NewSubTask(TASK_NAME_SET_TENANT_PARAMETER), diff --git a/agent/executor/tenant/set_root_pwd.go b/agent/executor/tenant/set_root_pwd.go index d92b6306..7dc824cc 100644 --- a/agent/executor/tenant/set_root_pwd.go +++ b/agent/executor/tenant/set_root_pwd.go @@ -20,9 +20,13 @@ import ( "github.com/gin-gonic/gin" "github.com/oceanbase/obshell/agent/api/common" "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/engine/coordinator" "github.com/oceanbase/obshell/agent/engine/task" "github.com/oceanbase/obshell/agent/errors" "github.com/oceanbase/obshell/agent/meta" + "github.com/oceanbase/obshell/agent/repository/model/bo" + "github.com/oceanbase/obshell/agent/secure" + "github.com/oceanbase/obshell/agent/service/tenant" "github.com/oceanbase/obshell/param" ) @@ -32,7 +36,7 @@ type SetRootPwdTask struct { newPassword string } -func getExecuteAgentForSetTenantRootPwd(tenantName string) (meta.AgentInfoInterface, error) { +func GetExecuteAgentForTenant(tenantName string) (meta.AgentInfoInterface, error) { isTenantOn, err := tenantService.IsTenantActiveAgent(tenantName, meta.OCS_AGENT.GetIp(), meta.RPC_PORT) if err != nil { return nil, err @@ -50,6 +54,25 @@ func getExecuteAgentForSetTenantRootPwd(tenantName string) (meta.AgentInfoInterf return executeAgent, err } +func PersistTenantRootPassword(c *gin.Context, tenantName, rootPassword string) *errors.OcsAgentError { + // check password connectable by calling precheck api with password + body := ¶m.TenantRootPasswordParam{ + RootPassword: &rootPassword, + } + uri := constant.URI_API_V1 + constant.URI_TENANT + "/" + tenantName + constant.URI_PRECHECK + agentInfo := coordinator.OCS_COORDINATOR.Maintainer + result := &bo.ObTenantPreCheckResult{} + err := secure.SendGetRequest(agentInfo, uri, body, result) + if err != nil { + return errors.Occur(errors.ErrUnexpected, "Failed to check tenant connectable using password.") + } + if !result.IsConnectable { + return errors.Occur(errors.ErrUnexpected, "The provided password is unable to connect to the tenant.") + } + tenant.GetPasswordMap().Set(tenantName, rootPassword) + return nil +} + func ModifyTenantRootPassword(c *gin.Context, tenantName string, pwdParam param.ModifyTenantRootPasswordParam) (*errors.OcsAgentError, bool) { if _, err := checkTenantExistAndStatus(tenantName); err != nil { return err, false @@ -57,7 +80,7 @@ func ModifyTenantRootPassword(c *gin.Context, tenantName string, pwdParam param. if tenantName == constant.TENANT_SYS { return errors.Occur(errors.ErrIllegalArgument, "Can not modify root password for sys tenant."), false } - executeAgent, err := getExecuteAgentForSetTenantRootPwd(tenantName) + executeAgent, err := GetExecuteAgentForTenant(tenantName) if err != nil { return errors.Occurf(errors.ErrUnexpected, "get execute agent failed: %s", err.Error()), false } @@ -116,5 +139,6 @@ func (t *SetRootPwdTask) Execute() error { return errors.Occurf(errors.ErrUnexpected, "modify tenant root password failed: %s", err.Error()) } } + tenant.GetPasswordMap().Set(t.tenantName, t.newPassword) return nil } diff --git a/agent/executor/tenant/user.go b/agent/executor/tenant/user.go new file mode 100644 index 00000000..630f9794 --- /dev/null +++ b/agent/executor/tenant/user.go @@ -0,0 +1,466 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tenant + +import ( + "fmt" + "strings" + + "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/meta" + "github.com/oceanbase/obshell/agent/repository/model/bo" + obmodel "github.com/oceanbase/obshell/agent/repository/model/oceanbase" + "github.com/oceanbase/obshell/param" + "github.com/oceanbase/obshell/utils" + "gorm.io/gorm" +) + +func CreateUser(tenantName string, param *param.CreateUserParam) *errors.OcsAgentError { + var db *gorm.DB + defer CloseDbConnection(db) + var err error + db, err = GetConnectionWithPassword(tenantName, param.RootPassword) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to get connection of tenant %s, error: %s", tenantName, err.Error()) + } + + if param.HostName == "" { + param.HostName = constant.DEFAULT_HOST + } + + // Create user. + if err := tenantService.CreateUser(db, param.UserName, param.Password, param.HostName); err != nil { + return errors.Occurf(errors.ErrUnexpected, "create user '%s' failed: %s", param.UserName, err.Error()) + } + + // Grant privileges. + if len(param.GlobalPrivileges) != 0 { + if err := tenantService.GrantGlobalPrivilegesWithHost(db, param.UserName, param.HostName, param.GlobalPrivileges); err != nil { + return errors.Occurf(errors.ErrUnexpected, "grant global privileges to user '%s' failed: %s", param.UserName, err.Error()) + } + } + + for _, dbPrivilege := range param.DbPrivileges { + if err := tenantService.GrantDbPrivilegesWithHost(db, param.UserName, param.HostName, dbPrivilege); err != nil { + return errors.Occurf(errors.ErrUnexpected, "grant db privileges to user '%s' failed: %s", param.UserName, err.Error()) + } + } + + return nil +} + +func DropUser(tenantName, userName string, param *param.DropUserParam) *errors.OcsAgentError { + var db *gorm.DB + defer CloseDbConnection(db) + var err error + db, err = GetConnectionWithPassword(tenantName, param.RootPassword) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to get connection of tenant %s, error: %s", tenantName, err.Error()) + } + + // Check user exist. + if exist, err := tenantService.IsUserExist(db, userName); err != nil { + return errors.Occurf(errors.ErrUnexpected, "check user '%s' exist failed", userName) + } else if !exist { + return nil + } + + // Drop user. + if err := tenantService.DropUser(db, userName); err != nil { + return errors.Occurf(errors.ErrUnexpected, "drop user '%s' failed: %s", userName, err.Error()) + } + + return nil +} + +func ListUsers(tenantName string, password *string) ([]bo.ObUser, *errors.OcsAgentError) { + db, err := GetConnectionWithPassword(tenantName, password) + defer CloseDbConnection(db) + if err != nil { + return nil, errors.Occurf(errors.ErrUnexpected, "Failed to get db connection of tenant %s, err: %s", tenantName, err.Error()) + } + users, err := tenantService.ListUsers(db) + if err != nil { + return nil, errors.Occurf(errors.ErrUnexpected, "Failed to query user list of tenant %s, err: %s", tenantName, err.Error()) + } + allDatabases, err := tenantService.ListDatabases(db) + if err != nil { + return nil, errors.Occurf(errors.ErrUnexpected, "Failed to query database list of tenant %s, err: %s", tenantName, err.Error()) + } + dbPrivileges, err := tenantService.ListDatabasePrivileges(db) + if err != nil { + return nil, errors.Occurf(errors.ErrUnexpected, "Failed to query database privileges of tenant %s, err: %s", tenantName, err.Error()) + } + dbPrivilegeMap := make(map[string][]obmodel.MysqlDb) + for _, dbPrivilege := range dbPrivileges { + privileges, ok := dbPrivilegeMap[dbPrivilege.User] + if !ok { + privileges = make([]obmodel.MysqlDb, 0) + } + privileges = append(privileges, dbPrivilege) + dbPrivilegeMap[dbPrivilege.User] = privileges + } + result := make([]bo.ObUser, 0) + for _, user := range users { + // filter out inner users + isInnerUser := false + for _, innerUserName := range constant.OB_INNER_USERS { + if user.User == innerUserName { + isInnerUser = true + break + } + } + if isInnerUser { + continue + } + obUser := &bo.ObUser{ + UserName: user.User, + IsLocked: strings.HasPrefix(strings.ToUpper(user.AccountLocked), "Y"), + } + privileges, ok := dbPrivilegeMap[user.User] + if !ok { + privileges = make([]obmodel.MysqlDb, 0) + } + attachInfo(tenantName, obUser, &user, privileges, allDatabases) + result = append(result, *obUser) + } + return result, nil +} + +func ChangeUserPassword(tenantName, userName string, p *param.ChangeUserPasswordParam) *errors.OcsAgentError { + db, err := GetConnectionWithPassword(tenantName, p.RootPassword) + defer CloseDbConnection(db) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to get db connection of tenant %s, err: %s", tenantName, err.Error()) + } + err = tenantService.ChangeUserPassword(db, userName, p.NewPassword) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to change password of user %s of tenant %s, err: %s", userName, tenantName, err.Error()) + } + return nil +} + +func GetUserStats(tenantName, userName string, password *string) (*bo.ObUserStats, *errors.OcsAgentError) { + db, err := GetConnectionWithPassword(tenantName, password) + defer CloseDbConnection(db) + if err != nil { + return nil, errors.Occurf(errors.ErrUnexpected, "Failed to get db connection of tenant %s, err: %s", tenantName, err.Error()) + } + sessionStats, err := tenantService.GetUserSessionStats(db, userName) + if err != nil { + return nil, errors.Occurf(errors.ErrUnexpected, "Failed to query session stat of user %s of tenant %s, err: %s", userName, tenantName, err.Error()) + } + var totalCount int64 = 0 + var activeCount int64 = 0 + for _, sessionStat := range sessionStats { + totalCount += sessionStat.Count + if strings.ToUpper(sessionStat.State) == "ACTIVE" { + activeCount += sessionStat.Count + } + } + return &bo.ObUserStats{ + Session: &bo.ObUserSessionStats{ + Total: totalCount, + Active: activeCount, + }, + }, nil +} + +func verifyPrivilege(privileges []string) error { + for _, privilege := range privileges { + isPrivilegeValid := false + for _, availablePrivilege := range constant.OB_MYSQL_PRIVILEGES { + if strings.ToUpper(privilege) == availablePrivilege { + isPrivilegeValid = true + break + } + } + if !isPrivilegeValid { + return errors.Errorf("unsupported privilege %s", privilege) + } + } + return nil +} + +func ModifyUserGlobalPrivilege(tenantName, userName string, p *param.ModifyUserGlobalPrivilegeParam) *errors.OcsAgentError { + err := verifyPrivilege(p.GlobalPrivileges) + if err != nil { + return errors.Occurf(errors.ErrBadRequest, "Found unsupported privilege, err: %s", err.Error()) + } + obuser, userErr := GetUser(tenantName, userName, p.RootPassword) + if userErr != nil { + return userErr + } + db, err := GetConnectionWithPassword(tenantName, p.RootPassword) + defer CloseDbConnection(db) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to get db connection of tenant %s, err: %s", tenantName, err.Error()) + } + privilegesToGrant, privilegesToRevoke := utils.Difference(p.GlobalPrivileges, obuser.GlobalPrivileges) + err = tenantService.GrantGlobalPrivileges(db, userName, privilegesToGrant) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to grant privilege to user %s of tenant %s, err: %s", userName, tenantName, err.Error()) + } + err = tenantService.RevokeGlobalPrivileges(db, userName, privilegesToRevoke) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to revoke privilege from user %s of tenant %s, err: %s", userName, tenantName, err.Error()) + } + return nil +} + +func ModifyUserDbPrivilege(tenantName, userName string, p *param.ModifyUserDbPrivilegeParam) *errors.OcsAgentError { + for _, dbPrivilege := range p.DbPrivileges { + err := verifyPrivilege(dbPrivilege.Privileges) + if err != nil { + return errors.Occurf(errors.ErrBadRequest, "Found unsupported privilege for db %s, err: %s", dbPrivilege.DbName, err.Error()) + } + } + obuser, userErr := GetUser(tenantName, userName, p.RootPassword) + if userErr != nil { + return userErr + } + db, err := GetConnectionWithPassword(tenantName, p.RootPassword) + defer CloseDbConnection(db) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to get db connection of tenant %s, err: %s", tenantName, err.Error()) + } + + for _, desiredDbPrivilege := range p.DbPrivileges { + found := false + for _, currentDbPrivilege := range obuser.DbPrivileges { + if desiredDbPrivilege.DbName == currentDbPrivilege.DbName { + privilegesToGrant, privilegesToRevoke := utils.Difference(desiredDbPrivilege.Privileges, currentDbPrivilege.Privileges) + err = tenantService.GrantDbPrivileges(db, userName, ¶m.DbPrivilegeParam{ + DbName: currentDbPrivilege.DbName, + Privileges: privilegesToGrant, + }) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to grant privilege of database %s to user %s of tenant %s, err: %s", currentDbPrivilege.DbName, userName, tenantName, err.Error()) + } + err = tenantService.RevokeDbPrivileges(db, userName, ¶m.DbPrivilegeParam{ + DbName: currentDbPrivilege.DbName, + Privileges: privilegesToRevoke, + }) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to revoke privilege of database %s from user %s of tenant %s, err: %s", currentDbPrivilege.DbName, userName, tenantName, err.Error()) + } + } + } + if !found { + err = tenantService.GrantDbPrivileges(db, userName, &desiredDbPrivilege) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to grant privilege of database %s to user %s of tenant %s, err: %s", desiredDbPrivilege.DbName, userName, tenantName, err.Error()) + } + } + } + + for _, currentDbPrivilege := range obuser.DbPrivileges { + found := false + for _, desiredDbPrivilege := range p.DbPrivileges { + if desiredDbPrivilege.DbName == currentDbPrivilege.DbName { + found = true + break + } + } + if !found { + err = tenantService.RevokeDbPrivileges(db, userName, ¶m.DbPrivilegeParam{ + DbName: currentDbPrivilege.DbName, + Privileges: currentDbPrivilege.Privileges, + }) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to revoke privilege of database %s from user %s of tenant %s, err: %s", currentDbPrivilege.DbName, userName, tenantName, err.Error()) + } + } + } + return nil +} + +func LockUser(tenantName, userName string, password *string) *errors.OcsAgentError { + db, err := GetConnectionWithPassword(tenantName, password) + defer CloseDbConnection(db) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to get db connection of tenant %s, err: %s", tenantName, err.Error()) + } + err = tenantService.LockUser(db, userName) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to lock user %s of tenant %s, err: %s", userName, tenantName, err.Error()) + } + return nil +} + +func UnlockUser(tenantName, userName string, password *string) *errors.OcsAgentError { + db, err := GetConnectionWithPassword(tenantName, password) + defer CloseDbConnection(db) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to get db connection of tenant %s, err: %s", tenantName, err.Error()) + } + err = tenantService.UnlockUser(db, userName) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "Failed to lock user %s of tenant %s, err: %s", userName, tenantName, err.Error()) + } + return nil +} + +func GetUser(tenantName, userName string, password *string) (*bo.ObUser, *errors.OcsAgentError) { + db, err := GetConnectionWithPassword(tenantName, password) + defer CloseDbConnection(db) + if err != nil { + return nil, errors.Occurf(errors.ErrUnexpected, "Failed to get db connection of tenant %s, err: %s", tenantName, err.Error()) + } + user, err := tenantService.GetUser(db, userName) + if err != nil { + return nil, errors.Occurf(errors.ErrUnexpected, "Failed to query user %s of tenant %s, err: %s", userName, tenantName, err.Error()) + } + allDatabases, err := tenantService.ListDatabases(db) + if err != nil { + return nil, errors.Occurf(errors.ErrUnexpected, "Failed to query database list of tenant %s, err: %s", tenantName, err.Error()) + } + dbPrivileges, err := tenantService.ListDatabasePrivilegesOfUser(db, userName) + if err != nil { + return nil, errors.Occurf(errors.ErrUnexpected, "Failed to query database privileges of tenant %s, err: %s", tenantName, err.Error()) + } + + obUser := &bo.ObUser{ + UserName: user.User, + IsLocked: strings.HasPrefix(strings.ToUpper(user.AccountLocked), "Y"), + } + attachInfo(tenantName, obUser, user, dbPrivileges, allDatabases) + return obUser, nil +} + +func attachInfo(tenantName string, obUser *bo.ObUser, user *obmodel.MysqlUser, dbPrivileges []obmodel.MysqlDb, allDatabases []obmodel.Database) { + globalPrivileges := extractGlobalPrivileges(user) + obUser.GlobalPrivileges = globalPrivileges + databasePrivileges := extractDatabasePrivileges(dbPrivileges) + obUser.DbPrivileges = databasePrivileges + allDatabaseNames := make([]string, 0) + privilegedDatabaseNames := make([]string, 0) + for _, database := range allDatabases { + allDatabaseNames = append(allDatabaseNames, database.Name) + } + for _, databasePrivilege := range databasePrivileges { + privilegedDatabaseNames = append(privilegedDatabaseNames, databasePrivilege.DbName) + } + if len(globalPrivileges) > 0 { + obUser.AccessibleDatabases = allDatabaseNames + + } else { + obUser.AccessibleDatabases = privilegedDatabaseNames + } + connectionStr := bo.ObproxyAndConnectionString{ + Type: constant.OB_CONNECTION_TYPE_DIRECT, + ConnectionString: fmt.Sprintf("obclient -h%s -P%d -u%s@%s -p", meta.OCS_AGENT.GetIp(), meta.MYSQL_PORT, obUser.UserName, tenantName), + } + connectionStrs := make([]bo.ObproxyAndConnectionString, 0) + connectionStrs = append(connectionStrs, connectionStr) + obUser.ConnectionStrings = connectionStrs +} + +func extractDatabasePrivileges(dbPrivileges []obmodel.MysqlDb) []bo.DbPrivilege { + result := make([]bo.DbPrivilege, 0) + for _, dbPrivilege := range dbPrivileges { + privileges := make([]string, 0) + if strings.HasPrefix(strings.ToUpper(dbPrivilege.AlterPriv), "Y") { + privileges = append(privileges, constant.OB_MYSQL_PRIVILEGE_ALTER) + } + if strings.HasPrefix(strings.ToUpper(dbPrivilege.CreatePriv), "Y") { + privileges = append(privileges, constant.OB_MYSQL_PRIVILEGE_CREATE) + } + if strings.HasPrefix(strings.ToUpper(dbPrivilege.DeletePriv), "Y") { + privileges = append(privileges, constant.OB_MYSQL_PRIVILEGE_DELETE) + } + if strings.HasPrefix(strings.ToUpper(dbPrivilege.DropPriv), "Y") { + privileges = append(privileges, constant.OB_MYSQL_PRIVILEGE_DROP) + } + if strings.HasPrefix(strings.ToUpper(dbPrivilege.InsertPriv), "Y") { + privileges = append(privileges, constant.OB_MYSQL_PRIVILEGE_INSERT) + } + if strings.HasPrefix(strings.ToUpper(dbPrivilege.SelectPriv), "Y") { + privileges = append(privileges, constant.OB_MYSQL_PRIVILEGE_SELECT) + } + if strings.HasPrefix(strings.ToUpper(dbPrivilege.UpdatePriv), "Y") { + privileges = append(privileges, constant.OB_MYSQL_PRIVILEGE_UPDATE) + } + if strings.HasPrefix(strings.ToUpper(dbPrivilege.IndexPriv), "Y") { + privileges = append(privileges, constant.OB_MYSQL_PRIVILEGE_INDEX) + } + if strings.HasPrefix(strings.ToUpper(dbPrivilege.CreateViewPriv), "Y") { + privileges = append(privileges, constant.OB_MYSQL_PRIVILEGE_CREATE_VIEW) + } + if strings.HasPrefix(strings.ToUpper(dbPrivilege.ShowViewPriv), "Y") { + privileges = append(privileges, constant.OB_MYSQL_PRIVILEGE_SHOW_VIEW) + } + if len(privileges) > 0 { + result = append(result, bo.DbPrivilege{ + DbName: dbPrivilege.Db, + Privileges: privileges, + }) + } + } + return result +} + +func extractGlobalPrivileges(user *obmodel.MysqlUser) []string { + globalPrivileges := make([]string, 0) + if strings.HasPrefix(strings.ToUpper(user.AlterPriv), "Y") { + globalPrivileges = append(globalPrivileges, constant.OB_MYSQL_PRIVILEGE_ALTER) + } + if strings.HasPrefix(strings.ToUpper(user.CreatePriv), "Y") { + globalPrivileges = append(globalPrivileges, constant.OB_MYSQL_PRIVILEGE_CREATE) + } + if strings.HasPrefix(strings.ToUpper(user.DeletePriv), "Y") { + globalPrivileges = append(globalPrivileges, constant.OB_MYSQL_PRIVILEGE_DELETE) + } + if strings.HasPrefix(strings.ToUpper(user.DropPriv), "Y") { + globalPrivileges = append(globalPrivileges, constant.OB_MYSQL_PRIVILEGE_DROP) + } + if strings.HasPrefix(strings.ToUpper(user.InsertPriv), "Y") { + globalPrivileges = append(globalPrivileges, constant.OB_MYSQL_PRIVILEGE_INSERT) + } + if strings.HasPrefix(strings.ToUpper(user.SelectPriv), "Y") { + globalPrivileges = append(globalPrivileges, constant.OB_MYSQL_PRIVILEGE_SELECT) + } + if strings.HasPrefix(strings.ToUpper(user.UpdatePriv), "Y") { + globalPrivileges = append(globalPrivileges, constant.OB_MYSQL_PRIVILEGE_UPDATE) + } + if strings.HasPrefix(strings.ToUpper(user.IndexPriv), "Y") { + globalPrivileges = append(globalPrivileges, constant.OB_MYSQL_PRIVILEGE_INDEX) + } + if strings.HasPrefix(strings.ToUpper(user.CreateViewPriv), "Y") { + globalPrivileges = append(globalPrivileges, constant.OB_MYSQL_PRIVILEGE_CREATE_VIEW) + } + if strings.HasPrefix(strings.ToUpper(user.ShowViewPriv), "Y") { + globalPrivileges = append(globalPrivileges, constant.OB_MYSQL_PRIVILEGE_SHOW_VIEW) + } + if strings.HasPrefix(strings.ToUpper(user.CreateUserPriv), "Y") { + globalPrivileges = append(globalPrivileges, constant.OB_MYSQL_PRIVILEGE_CREATE_USER) + } + if strings.HasPrefix(strings.ToUpper(user.ProcessPriv), "Y") { + globalPrivileges = append(globalPrivileges, constant.OB_MYSQL_PRIVILEGE_PROCESS) + } + if strings.HasPrefix(strings.ToUpper(user.SuperPriv), "Y") { + globalPrivileges = append(globalPrivileges, constant.OB_MYSQL_PRIVILEGE_SUPER) + } + if strings.HasPrefix(strings.ToUpper(user.ShowDbPriv), "Y") { + globalPrivileges = append(globalPrivileges, constant.OB_MYSQL_PRIVILEGE_SHOW_DATABASES) + } + if strings.HasPrefix(strings.ToUpper(user.GrantPriv), "Y") { + globalPrivileges = append(globalPrivileges, constant.OB_MYSQL_PRIVILEGE_GRANT_OPTION) + } + return globalPrivileges +} diff --git a/agent/executor/tenant/utils.go b/agent/executor/tenant/utils.go new file mode 100644 index 00000000..283c6bcd --- /dev/null +++ b/agent/executor/tenant/utils.go @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tenant + +import ( + "strings" + + "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/meta" + "github.com/oceanbase/obshell/agent/repository/db/oceanbase" + "github.com/oceanbase/obshell/agent/repository/model/bo" + "github.com/oceanbase/obshell/agent/service/tenant" + + "gorm.io/gorm" +) + +func TenantPreCheck(tenantName string, password *string) (*bo.ObTenantPreCheckResult, *errors.OcsAgentError) { + isPasswordExists := password == nil + isConnectable := false + db, err := GetConnectionWithPassword(tenantName, password) + defer CloseDbConnection(db) + isConnectable = (err == nil) + isEmptyRootPassword, err := IsEmptyRootPassword(tenantName) + if err != nil { + return nil, errors.Occurf(errors.ErrUnexpected, "check tenant '%s' password if empty failed", tenantName) + } + + return &bo.ObTenantPreCheckResult{ + IsConnectable: isConnectable, + IsPasswordExists: isPasswordExists, + IsEmptyRootPassword: isEmptyRootPassword, + }, nil +} + +func GetConnection(tenantName string) (*gorm.DB, error) { + if tenantName == constant.TENANT_SYS { + return oceanbase.GetInstance() + } else { + passwordMap := tenant.GetPasswordMap() + password, _ := passwordMap.Get(tenantName) + return oceanbase.LoadGormWithTenant(tenantName, password) + } +} + +func IsEmptyRootPassword(tenantName string) (bool, error) { + if tenantName == constant.TENANT_SYS { + return meta.OCEANBASE_PWD == "", nil + } else { + if err := oceanbase.LoadGormWithTenantForTest(tenantName, ""); err != nil { + if strings.Contains(err.Error(), "Access denied") { + return false, nil + } else { + return true, err + } + } + } + return true, nil +} + +func GetConnectionWithPassword(tenantName string, password *string) (*gorm.DB, error) { + if tenantName == constant.TENANT_SYS { + return oceanbase.GetInstance() + } else { + if password != nil { + return oceanbase.LoadGormWithTenant(tenantName, *password) + } else { + return oceanbase.LoadGormWithTenant(tenantName, "") + } + } +} + +func CloseDbConnection(db *gorm.DB) { + if db == oceanbase.GetRawInstance() { + return + } + if db != nil { + tempDb, _ := db.DB() + if tempDb != nil { + tempDb.Close() + } + } +} diff --git a/agent/executor/tenant/variable.go b/agent/executor/tenant/variable.go index 28b99691..754d6a76 100644 --- a/agent/executor/tenant/variable.go +++ b/agent/executor/tenant/variable.go @@ -19,9 +19,15 @@ package tenant import ( "regexp" + "github.com/gin-gonic/gin" + "github.com/oceanbase/obshell/agent/api/common" "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/engine/task" "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/meta" "github.com/oceanbase/obshell/agent/repository/model/oceanbase" + "github.com/oceanbase/obshell/param" + "github.com/oceanbase/obshell/utils" ) func isUnkonwnTimeZoneErr(err error) bool { @@ -56,23 +62,48 @@ func GetTenantVariable(tenantName string, variableName string) (*oceanbase.CdbOb return variable, nil } -func SetTenantVariables(tenantName string, variables map[string]interface{}) *errors.OcsAgentError { +func SetTenantVariables(c *gin.Context, tenantName string, param param.SetTenantVariablesParam) *errors.OcsAgentError { if _, err := checkTenantExistAndStatus(tenantName); err != nil { return err } - for k, v := range variables { + for k, v := range param.Variables { if k == "" || v == nil { return errors.Occur(errors.ErrIllegalArgument, "variable name or value is empty") } } - transferNumber(variables) - if err := tenantService.SetTenantVariables(tenantName, variables); err != nil { - if errors.IsUnkonwnTimeZoneErr(err) { - if value, exist := variables[constant.VARIABLE_TIME_ZONE]; exist { - return timeZoneErrorReporter(value, err) + transferNumber(param.Variables) + + needConnectTenant := false + for k := range param.Variables { + if utils.ContainsString(constant.VARIAbLES_COLLATION_OR_CHARACTER, k) { + needConnectTenant = true + break + } + } + + if !needConnectTenant { + if err := tenantService.SetTenantVariables(tenantName, param.Variables); err != nil { + if errors.IsUnkonwnTimeZoneErr(err) { + if value, exist := param.Variables[constant.VARIABLE_TIME_ZONE]; exist { + return timeZoneErrorReporter(value, err) + } + } + return errors.Occur(errors.ErrBadRequest, err) + } + } else { + executeAgent, err := GetExecuteAgentForTenant(tenantName) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "get execute agent failed: %s", err.Error()) + } + + if meta.OCS_AGENT.Equal(executeAgent) { + if err := tenantService.SetTenantVariablesWithTenant(tenantName, param.TenantPassword, param.Variables); err != nil { + return errors.Occur(errors.ErrUnexpected, err) } + } else { + common.ForwardRequest(c, executeAgent, param) + return nil } - return errors.Occur(errors.ErrBadRequest, err) } return nil @@ -84,9 +115,61 @@ func timeZoneErrorReporter(timeZone interface{}, err error) *errors.OcsAgentErro re := regexp.MustCompile(pattern) if re.MatchString(v) { if empty, _ := tenantService.IsTimeZoneTableEmpty(); empty { - return errors.Occur(errors.ErrBadRequest, errors.Wrapf(err, "Please check whether the sys tenat has been import time zone info")) + return errors.Occur(errors.ErrBadRequest, errors.Wrapf(err, "Please check whether the sys tenant has been import time zone info")) } } } return errors.Occur(errors.ErrBadRequest, err) } + +type SetTenantVariableTask struct { + task.Task + variables map[string]interface{} + tenantName string +} + +func newSetTenantVariableNode(variables map[string]interface{}) (*task.Node, error) { + agents, err := agentService.GetAllAgentsInfoFromOB() + if err != nil { + return nil, errors.Wrap(err, "create set tenant variable task failed") + } + ctx := task.NewTaskContext(). + SetParam(task.EXECUTE_AGENTS, agents). + SetParam(PARAM_TENANT_VARIABLES, variables) + return task.NewNodeWithContext(newSetTenantVariableTask(), true, ctx), nil +} + +func newSetTenantVariableTask() *SetTenantVariableTask { + newTask := &SetTenantVariableTask{ + Task: *task.NewSubTask(TASK_NAME_SET_TENANT_VARIABLE), + } + + newTask.SetCanContinue().SetCanRollback().SetCanRetry().SetCanCancel() + return newTask +} + +func (t *SetTenantVariableTask) Execute() error { + if err := t.GetContext().GetParamWithValue(PARAM_TENANT_NAME, &t.tenantName); err != nil { + return errors.Wrap(err, "Get tenant name failed") + } + + if err := t.GetContext().GetParamWithValue(PARAM_TENANT_VARIABLES, &t.variables); err != nil { + return errors.Wrap(err, "Get tenant variables failed") + } + + executeAgent, err := tenantService.GetTenantActiveAgent(t.tenantName) + if err != nil { + return err + } + if executeAgent == nil { + return errors.New("tenant is not active") + } + + if meta.OCS_AGENT.Equal(executeAgent) { + transferNumber(t.variables) + if err := tenantService.SetTenantVariablesWithTenant(t.tenantName, "", t.variables); err != nil { + return errors.Occurf(errors.ErrUnexpected, "set tenant variables failed: %s", err.Error()) + } + } + return nil +} diff --git a/agent/executor/tenant/whitelist.go b/agent/executor/tenant/whitelist.go index d357f257..749a8a2f 100644 --- a/agent/executor/tenant/whitelist.go +++ b/agent/executor/tenant/whitelist.go @@ -42,7 +42,18 @@ func mergeWhitelist(specific string) string { if specific == "" { return defaultWhitelist } - return strings.Join([]string{specific, defaultWhitelist}, ",") + splits := strings.Split(specific, ",") + splits = append(splits, defaultWhitelist) + whitelistMap := make([]string, 0) + // 去重 + unique := make(map[string]struct{}) + for _, item := range splits { + if _, ok := unique[item]; !ok { + unique[item] = struct{}{} + whitelistMap = append(whitelistMap, item) + } + } + return strings.Join(whitelistMap, ",") } type ModifyTenantWhitelistTask struct { diff --git a/agent/executor/unit/enter.go b/agent/executor/unit/enter.go new file mode 100644 index 00000000..bdc7f717 --- /dev/null +++ b/agent/executor/unit/enter.go @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package unit + +import ( + "github.com/oceanbase/obshell/agent/service/obcluster" + "github.com/oceanbase/obshell/agent/service/unit" +) + +var ( + unitService = unit.UnitService{} + obclusterService = obcluster.ObclusterService{} +) diff --git a/agent/executor/unit/unit.go b/agent/executor/unit/unit.go index a96613e4..8df12a42 100644 --- a/agent/executor/unit/unit.go +++ b/agent/executor/unit/unit.go @@ -20,14 +20,9 @@ import ( "github.com/oceanbase/obshell/agent/errors" "github.com/oceanbase/obshell/agent/lib/parse" "github.com/oceanbase/obshell/agent/repository/model/oceanbase" - "github.com/oceanbase/obshell/agent/service/unit" "github.com/oceanbase/obshell/param" ) -var ( - unitService = unit.UnitService{} -) - func DropUnitConfig(name string) *errors.OcsAgentError { if exist, err := unitService.IsUnitConfigExist(name); err != nil { return errors.Occur(errors.ErrUnexpected, err.Error()) diff --git a/agent/global/variable.go b/agent/global/variable.go index b94678ca..373f1a30 100644 --- a/agent/global/variable.go +++ b/agent/global/variable.go @@ -31,17 +31,18 @@ import ( ) var ( - HomePath string - Uid uint32 - Gid uint32 - Pid = os.Getpid() - StartAt = time.Now().UnixNano() - Protocol = "http" - CaCertPool *x509.CertPool - SkipVerify bool - EnableHTTPS bool - Architecture string - Os string + HomePath string + Uid uint32 + Gid uint32 + Pid = os.Getpid() + StartAt = time.Now().UnixNano() + Protocol = "http" + CaCertPool *x509.CertPool + SkipVerify bool + EnableHTTPS bool + Architecture string + Os string + ObproxyHomePath string ) var ( diff --git a/agent/lib/binary/ob.go b/agent/lib/binary/ob.go index 1de1b0df..c78c2283 100644 --- a/agent/lib/binary/ob.go +++ b/agent/lib/binary/ob.go @@ -18,6 +18,7 @@ package binary import ( "fmt" + "os" "os/exec" "path/filepath" "regexp" @@ -27,12 +28,15 @@ import ( "github.com/oceanbase/obshell/agent/global" ) -func GetMyOBVersion() (version string, err error) { +func GetMyOBVersion() (version string, IsCommunityEdition bool, err error) { myOBPath := filepath.Join(global.HomePath, constant.DIR_BIN, constant.PROC_OBSERVER) bash := fmt.Sprintf("export LD_LIBRARY_PATH='%s/lib'; %s -V", global.HomePath, myOBPath) + if os.Stat(myOBPath); err != nil { + return "", false, errors.Wrap(err, "get my ob version failed") + } out, err := exec.Command("/bin/bash", "-c", bash).CombinedOutput() if err != nil { - return "", errors.Wrap(err, "exec get my ob version failed") + return "", false, err } res := string(out) @@ -40,15 +44,16 @@ func GetMyOBVersion() (version string, err error) { regex := regexp.MustCompile(`REVISION:\s*(\d+)-([a-fA-F0-9]+)`) match := regex.FindStringSubmatch(res) if len(match) != 3 { - return "", errors.New("get my ob build number failed") + return "", false, errors.New("get my ob build number failed") } buildNumber := match[1] // get version - regex = regexp.MustCompile(`observer\s*\(OceanBase(_CE)?\s*([\d.]+)\)`) + regex = regexp.MustCompile(`\(OceanBase(_CE)?\s*([\d.]+)\)`) match = regex.FindStringSubmatch(res) if match == nil { - return "", errors.New("get my ob version failed") + return "", false, errors.New("get my ob version failed") } - return fmt.Sprintf("%s-%s", match[2], buildNumber), nil + fmt.Println("match:", match) + return fmt.Sprintf("%s-%s", match[2], buildNumber), match[1] != "", nil } diff --git a/agent/lib/http/http.go b/agent/lib/http/http.go index bebe2f3d..d57996e5 100644 --- a/agent/lib/http/http.go +++ b/agent/lib/http/http.go @@ -128,7 +128,7 @@ func SendRequestAndBuildReturn(agentInfo meta.AgentInfoInterface, uri string, me } func NewClient() *resty.Client { - client := resty.New().SetTimeout(TCP_DEFAULT_TIME_OUT) + client := resty.New().SetTimeout(TCP_DEFAULT_TIME_OUT).SetAllowGetMethodPayload(true) if global.EnableHTTPS { tlsConfig := &tls.Config{ @@ -146,7 +146,7 @@ func NewClient() *resty.Client { func sendHttpRequest(agentInfo meta.AgentInfoInterface, uri string, method string, param, ret interface{}, headers map[string]string) (agentResponse ocsAgentResponse, err error) { var agentResp OcsAgentResponse var response *resty.Response - targetUrl := fmt.Sprintf("%s://%s:%d%s", global.Protocol, agentInfo.GetIp(), agentInfo.GetPort(), uri) + targetUrl := fmt.Sprintf("%s://%s%s", global.Protocol, agentInfo.String(), uri) request := NewClient().R() if ret != nil { request.SetResult(&agentResp) diff --git a/agent/lib/http/status.go b/agent/lib/http/status.go index 18f7a93d..0e1642bc 100644 --- a/agent/lib/http/status.go +++ b/agent/lib/http/status.go @@ -33,6 +33,7 @@ type AgentStatus struct { StartAt int64 `json:"startAt"` // timestamp when service started Port int `json:"port"` // Ports process occupied ports OBState int `json:"obState"` + SqlPort int `json:"sqlPort,omitempty"` UnderMaintenance bool `json:"underMaintenance"` } diff --git a/agent/lib/parse/config.go b/agent/lib/parse/config.go index 001e0a8b..89b41faf 100644 --- a/agent/lib/parse/config.go +++ b/agent/lib/parse/config.go @@ -17,6 +17,7 @@ package parse import ( + "fmt" "regexp" "strconv" "strings" @@ -40,6 +41,13 @@ const ( CAP_TB = "TB" CAP_PB = "PB" + KB = 1024 + MB = KB * 1024 + GB = MB * 1024 + TB = GB * 1024 + PB = TB * 1024 + EB = PB * 1024 + CAPACITY_PATTERN = `^([123456789]\d*)([KMGTP][B]?)$` ) @@ -67,3 +75,22 @@ func CapacityParser(capacity string) (int, bool) { } return 0, false } + +func FormatCapacity(bytes int64) string { + switch { + case bytes >= EB: + return fmt.Sprintf("%.2f EB", float64(bytes)/float64(EB)) + case bytes >= PB: + return fmt.Sprintf("%.2f EB", float64(bytes)/float64(PB)) + case bytes >= TB: + return fmt.Sprintf("%.2f TB", float64(bytes)/float64(TB)) + case bytes >= GB: + return fmt.Sprintf("%.2f GB", float64(bytes)/float64(GB)) + case bytes >= MB: + return fmt.Sprintf("%.2f MB", float64(bytes)/float64(MB)) + case bytes >= KB: + return fmt.Sprintf("%.2f KB", float64(bytes)/float64(KB)) + default: + return fmt.Sprintf("%d bytes", bytes) + } +} diff --git a/agent/lib/parse/time.go b/agent/lib/parse/time.go new file mode 100644 index 00000000..4ea86146 --- /dev/null +++ b/agent/lib/parse/time.go @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package parse + +import ( + "errors" + "fmt" + "regexp" + "strconv" + "strings" +) + +const ( + TIME_SECOND = "S" + TIME_MINUTE = "M" + TIME_HOUR = "H" + TIME_DAY = "D" +) + +func TimeParse(input string) (int, error) { + // Compile a regular expression to match the input format + pattern := regexp.MustCompile(`^([0-9]+)([a-zA-Z]?)$`) + matches := pattern.FindStringSubmatch(input) + + // Check if the input matches the pattern + if matches == nil { + return 0, errors.New("The input string is invalid: " + input) + } + + // Convert the captured numeric part of the input to an integer + num, err := strconv.Atoi(matches[1]) + if err != nil { + return 0, fmt.Errorf("Error parsing number: %v", err) + } + + // Get the unit character (if any) and determine the conversion factor + unit := matches[2] + switch strings.ToUpper(unit) { + case "": + // Default unit is microseconds, so convert to seconds + return num / 1000 / 1000, nil + case TIME_SECOND: + return num, nil + case TIME_MINUTE: + return num * 60, nil + case TIME_HOUR: + return num * 60 * 60, nil + case TIME_DAY: + return num * 24 * 60 * 60, nil + default: + return 0, errors.New("The input string is invalid: " + input) + } +} diff --git a/agent/lib/path/obproxy.go b/agent/lib/path/obproxy.go new file mode 100644 index 00000000..f921b1dc --- /dev/null +++ b/agent/lib/path/obproxy.go @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package path + +import ( + "fmt" + "path/filepath" + + "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/meta" +) + +func ObproxyEtcDir() string { + return filepath.Join(meta.OBPROXY_HOME_PATH, constant.OBPROXY_DIR_ETC) +} + +func ObproxyLibDir() string { + return filepath.Join(meta.OBPROXY_HOME_PATH, constant.OBPROXY_DIR_LIB) +} + +func ObproxyLogDir() string { + return filepath.Join(meta.OBPROXY_HOME_PATH, constant.OBPROXY_DIR_LIB) +} + +func ObproxyRunDir() string { + return filepath.Join(meta.OBPROXY_HOME_PATH, constant.OBPROXY_DIR_RUN) +} + +func ObproxyBinDir() string { + return filepath.Join(meta.OBPROXY_HOME_PATH, constant.OBPROXY_DIR_BIN) +} + +func ObproxyBinPath() string { + return filepath.Join(ObproxyBinDir(), constant.BIN_OBPROXY) +} + +func ObproxyPidPath() string { + return filepath.Join(ObproxyRunDir(), fmt.Sprintf("%s.pid", constant.BIN_OBPROXY)) +} + +func ObproxydPidPath() string { + return filepath.Join(ObproxyRunDir(), fmt.Sprintf("%s.pid", constant.BIN_OBPROXYD)) +} + +func ObproxyNewConfigDbFile() string { + return filepath.Join(ObproxyEtcDir(), "proxyconfig_v1.db") +} + +func ObproxyOldConfigDbFile() string { + return filepath.Join(ObproxyEtcDir(), "proxyconfig.db") +} diff --git a/agent/lib/pkg/rpm.go b/agent/lib/pkg/rpm.go new file mode 100644 index 00000000..9721ce70 --- /dev/null +++ b/agent/lib/pkg/rpm.go @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package pkg + +import ( + "fmt" + "io" + "mime/multipart" + "os" + "path/filepath" + "strings" + + + log "github.com/sirupsen/logrus" + + "github.com/cavaliergopher/cpio" + "github.com/cavaliergopher/rpm" + "github.com/oceanbase/obshell/agent/errors" + "github.com/ulikunitz/xz" +) + +func ReadRpm(input multipart.File) (pkg *rpm.Package, err error) { + if _, err = input.Seek(0, 0); err != nil { + return + } + if err = rpm.MD5Check(input); err != nil { + return + } + if _, err = input.Seek(0, 0); err != nil { + return + } + return rpm.Read(input) +} + +func SplitRelease(release string) (buildNumber, distribution string, err error) { + releaseSplit := strings.Split(release, ".") + if len(releaseSplit) < 2 { + return "", "", fmt.Errorf("release format %s is illegal", release) + } + buildNumber = releaseSplit[0] + distribution = releaseSplit[len(releaseSplit)-1] + return +} + +func InstallRpmPkgInPlace(path string) (err error) { + log.Infof("InstallRpmPkg: %s", path) + f, err := os.Open(path) + if err != nil { + return + } + defer f.Close() + + pkg, err := rpm.Read(f) + if err != nil { + return + } + if err = CheckCompressAndFormat(pkg); err != nil { + return + } + + xzReader, err := xz.NewReader(f) + if err != nil { + return + } + installPath := filepath.Dir(path) + cpioReader := cpio.NewReader(xzReader) + + for { + hdr, err := cpioReader.Next() + if err == io.EOF { + break + } + if err != nil { + return err + } + + m := hdr.Mode + if m.IsDir() { + dest := filepath.Join(installPath, hdr.Name) + log.Infof("%s is a directory, creating %s", hdr.Name, dest) + if err := os.MkdirAll(dest, 0755); err != nil { + return errors.Wrapf(err, "mkdir failed %s", hdr.Name) + } + + } else if m.IsRegular() { + if err := handleRegularFile(hdr, cpioReader, installPath); err != nil { + return err + } + + } else if hdr.Linkname != "" { + if err := handleSymlink(hdr, installPath); err != nil { + return err + } + } else { + log.Infof("Skipping unsupported file %s type: %v", hdr.Name, m) + } + } + + return nil +} + +func handleRegularFile(hdr *cpio.Header, cpioReader *cpio.Reader, installPath string) error { + dest := filepath.Join(installPath, hdr.Name) + if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil { + log.WithError(err).Error("mkdir failed") + return err + } + + outFile, err := os.Create(dest) + if err != nil { + return err + } + defer outFile.Close() + + log.Infof("Extracting %s", hdr.Name) + if _, err := io.Copy(outFile, cpioReader); err != nil { + return err + } + return nil +} + +func handleSymlink(hdr *cpio.Header, installPath string) error { + dest := filepath.Join(installPath, hdr.Name) + if err := os.Symlink(hdr.Linkname, dest); err != nil { + return errors.Wrapf(err, "create symlink failed %s -> %s", dest, hdr.Linkname) + } + log.Infof("Creating symlink %s -> %s", dest, hdr.Linkname) + return nil +} + +func CheckCompressAndFormat(pkg *rpm.Package) error { + if pkg.PayloadCompression() != "xz" { + return fmt.Errorf("unsupported compression '%s', the supported compression is 'xz'", pkg.PayloadCompression()) + } + if pkg.PayloadFormat() != "cpio" { + return fmt.Errorf("unsupported payload format '%s', the supported payload format is 'cpio'", pkg.PayloadFormat()) + } + return nil +} diff --git a/agent/lib/process/process.go b/agent/lib/process/process.go index a4d0ee0f..48820952 100644 --- a/agent/lib/process/process.go +++ b/agent/lib/process/process.go @@ -26,6 +26,7 @@ import ( "strings" "syscall" + "github.com/shirou/gopsutil/v3/net" log "github.com/sirupsen/logrus" "github.com/oceanbase/obshell/agent/lib/path" @@ -35,6 +36,20 @@ var ( obServerPidPath = filepath.Join(path.RunDir(), "observer.pid") ) +func getPidStr(pidPath string) (string, error) { + if _, err := os.Stat(pidPath); err != nil { + if os.IsNotExist(err) { + return "", nil + } + return "", err + } + content, err := os.ReadFile(pidPath) + if err != nil { + return "", err + } + return strings.TrimSpace(string(content)), nil +} + func getPid(pidPath string) (int32, error) { if _, err := os.Stat(pidPath); err != nil { if os.IsNotExist(err) { @@ -81,6 +96,28 @@ func getObserverProcess() (*ProcessInfo, error) { }, nil } +func getObproxyProcess() (*ProcessInfo, error) { + pid, err := getPid(path.ObproxyPidPath()) + if err != nil { + return nil, err + } + return &ProcessInfo{ + pid: fmt.Sprint(pid), + procPath: fmt.Sprintf("/proc/%d", pid), + }, nil +} + +func getObproxydProcess() (*ProcessInfo, error) { + pid, err := getPid(path.ObproxydPidPath()) + if err != nil { + return nil, err + } + return &ProcessInfo{ + pid: fmt.Sprint(pid), + procPath: fmt.Sprintf("/proc/%d", pid), + }, nil +} + func (p *ProcessInfo) exist() (bool, error) { if p.pid == "" { return false, nil @@ -139,6 +176,22 @@ func CheckObserverProcess() (bool, error) { return process.Exist() } +func CheckObproxyProcess() (bool, error) { + process, err := getObproxyProcess() + if err != nil { + return false, err + } + return process.Exist() +} + +func CheckObproxydProcess() (bool, error) { + process, err := getObproxydProcess() + if err != nil { + return false, err + } + return process.Exist() +} + func CheckProcessExist(pid int32) (bool, error) { proc, err := os.FindProcess(int(pid)) if err != nil { @@ -169,6 +222,10 @@ func GetObshellPid() (int32, error) { return getPid(path.ObshellPidPath()) } +func GetObshellPidStr() (string, error) { + return getPidStr(path.ObshellPidPath()) +} + func GetPid(path string) (int32, error) { return getPid(path) } @@ -208,3 +265,65 @@ func ExecuteBinary(binaryPath string, inputs []string) (err error) { // Wait for command execution to complete. return cmd.Wait() } + +// for obproxy +func GetObproxyPid() (string, error) { + process, err := getObproxyProcess() + if err != nil { + return "", err + } + return process.Pid() +} + +// for obproxy +func GetObproxydPid() (string, error) { + process, err := getObproxydProcess() + if err != nil { + return "", err + } + return process.Pid() +} + +// writePid writes the pid to the specified path atomically. +// If the file already exists, an error is returned. +func WritePid(path string, pid int) (err error) { + f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_EXCL|os.O_SYNC|syscall.O_CLOEXEC, 0644) + if err != nil { + return err + } + defer f.Close() + _, err = fmt.Fprint(f, pid) + if err != nil { + return err + } + return nil +} + +// writePid writes the pid to the specified path atomically. +func WritePidForce(path string, pid int) (err error) { + f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_SYNC|syscall.O_CLOEXEC, 0644) + if err != nil { + return err + } + defer f.Close() + _, err = fmt.Fprint(f, pid) + if err != nil { + return err + } + return nil +} + +func FindPIDByPort(port uint32) (int32, error) { + // NOTICE: use inet6 to support ipv6 + connections, err := net.Connections("inet") + if err != nil { + return 0, err + } + + for _, conn := range connections { + if conn.Laddr.Port == port { + return conn.Pid, nil + } + } + return 0, fmt.Errorf("no process found on port %d", port) +} diff --git a/agent/meta/agent.go b/agent/meta/agent.go index 2d876e97..6f7c3414 100644 --- a/agent/meta/agent.go +++ b/agent/meta/agent.go @@ -18,8 +18,14 @@ package meta import ( "fmt" + "net" + "regexp" "strconv" "strings" + + "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/utils" ) type AgentIdentity string @@ -66,6 +72,8 @@ type Agent interface { GetVersion() string GetAgentInfo() AgentInfo String() string + IsIPv6() bool + GetLocalIp() string Equal(other AgentInfoInterface) bool } @@ -80,11 +88,25 @@ func (agentInfo *AgentInfo) GetIp() string { return agentInfo.Ip } +func (agentInfo *AgentInfo) GetLocalIp() string { + if agentInfo.IsIPv6() { + return constant.LOCAL_IP_V6 + } + return constant.LOCAL_IP +} + func (agentInfo *AgentInfo) GetPort() int { return agentInfo.Port } -func (agentInfo *AgentInfo) String() string { +func (agentInfo *AgentInfo) IsIPv6() bool { + return strings.Contains(agentInfo.Ip, ":") +} + +func (agentInfo AgentInfo) String() string { + if agentInfo.IsIPv6() { + return fmt.Sprintf("[%s]:%d", agentInfo.Ip, agentInfo.Port) + } return fmt.Sprintf("%s:%d", agentInfo.Ip, agentInfo.Port) } @@ -127,13 +149,16 @@ type AgentInstance struct { } type AgentStatus struct { - Pid int `json:"pid"` - State int32 `json:"state"` - StartAt int64 `json:"startAt"` - HomePath string `json:"homePath"` - OBVersion string `json:"obVersion"` + Pid int `json:"pid"` + State int32 `json:"state"` + StartAt int64 `json:"startAt"` + HomePath string `json:"homePath"` + OBVersion string `json:"obVersion"` + Architecture string `json:"architecture"` AgentInstance - SupportedAuth []string `json:"supportedAuth"` + IsObproxyAgent bool `json:"isObproxyAgent"` + Security bool `json:"security"` + SupportedAuth []string `json:"supportedAuth"` } func (agent *ZoneDTO) GetZone() string { @@ -199,21 +224,76 @@ func NewAgentInfo(ip string, port int) *AgentInfo { } } -func NewAgentInfoByString(info string) *AgentInfo { - portIndex := strings.LastIndex(info, ":") - if portIndex == -1 { - return nil +func ConvertAddressToAgentInfo(host string) (*AgentInfo, error) { + if host == "" { + return nil, errors.New("host is empty") + } + if strings.Contains(host, ".") { + // If the host contains '.', it might be an IPv4 address, but further validation is needed. + return convertIPv4ToAgentInfo(host) + } else { + // If the host contains '.', it might be an IPv6 address, but further validation is needed. + return convertIPv6ToAgentInfo(host) } +} - ip := info[:portIndex] - port, err := strconv.Atoi(info[portIndex+1:]) - if err != nil { - return nil +func convertIPv4ToAgentInfo(host string) (*AgentInfo, error) { + var ip string + var err error + var port = constant.DEFAULT_AGENT_PORT + matches := strings.Split(host, ":") + if len(matches) == 1 { + return NewAgentInfo(matches[0], constant.DEFAULT_AGENT_PORT), nil + } else if len(matches) == 2 { + if port, err = strconv.Atoi(matches[1]); err != nil || !utils.IsValidPortValue(port) { + return nil, errors.Errorf("Invalid port: %s. Port number should be in the range [1024, 65535].", matches[1]) + } + ip = matches[0] + } else { + return nil, errors.Errorf("Invalid server format: %s", host) } - return &AgentInfo{ - Ip: ip, - Port: port, + + ipv4 := net.ParseIP(ip) + if ipv4 == nil || ipv4.To4() == nil { + return nil, errors.Errorf("%s is not a valid IP address", ip) } + return NewAgentInfo(ip, port), nil +} + +func convertIPv6ToAgentInfo(host string) (*AgentInfo, error) { + re := regexp.MustCompile(`(?:\[([0-9a-fA-F:]+)\]|([0-9a-fA-F:]+))(?:\:(\d+))?`) + matches := re.FindStringSubmatch(host) + + if matches == nil { + return nil, errors.Errorf("Invalid server format: %s", host) + } + + var ip string + var err error + var port = constant.DEFAULT_AGENT_PORT + if matches[1] != "" { + ip = matches[1] + } else { + ip = matches[2] + } + + if matches[3] != "" { + if port, err = strconv.Atoi(matches[3]); err != nil || !utils.IsValidPortValue(port) { + return nil, errors.Errorf("Invalid port: %s. Port number should be in the range [1024, 65535].", matches[1]) + } + } + + ipv6 := net.ParseIP(ip) + if ipv6 == nil || ipv6.To4() != nil { + return nil, errors.Errorf("%s is not a valid IP address", ip) + } + return NewAgentInfo(ip, port), nil +} + +func NewAgentInfoByString(info string) *AgentInfo { + // if err != nil, agent will be nil. So, no need to check err. + agent, _ := ConvertAddressToAgentInfo(info) + return agent } func NewAgentInfoByInterface(agentInfo AgentInfoInterface) *AgentInfo { @@ -306,14 +386,16 @@ func NewAgentSecretByAgentInfo(agent AgentInfoInterface, publicKey string) *Agen } } -func NewAgentStatus(agent Agent, pid int, state int32, startAt int64, homePath string, obVersion string) *AgentStatus { +func NewAgentStatus(agent Agent, pid int, state int32, startAt int64, homePath string, obVersion string, isAgentPasswordSet bool, isObproxyAgent bool) *AgentStatus { return &AgentStatus{ - Pid: pid, - State: state, - StartAt: startAt, - HomePath: homePath, - OBVersion: obVersion, - AgentInstance: *NewAgentInstanceByAgent(agent), - SupportedAuth: []string{AUTH_V2}, + Pid: pid, + State: state, + StartAt: startAt, + HomePath: homePath, + OBVersion: obVersion, + Security: isAgentPasswordSet, + IsObproxyAgent: isObproxyAgent, + AgentInstance: *NewAgentInstanceByAgent(agent), + SupportedAuth: []string{AUTH_V2}, } } diff --git a/agent/meta/obproxy.go b/agent/meta/obproxy.go new file mode 100644 index 00000000..beb67796 --- /dev/null +++ b/agent/meta/obproxy.go @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package meta + +var ( + OBPROXY_HOME_PATH = "" + OBPROXY_SQL_PORT = 0 +) + +type ObproxyInfo = AgentInfo + +func IsObproxyAgent() bool { + return OBPROXY_HOME_PATH != "" +} diff --git a/agent/meta/security.go b/agent/meta/security.go index c2f70d8b..b976d337 100644 --- a/agent/meta/security.go +++ b/agent/meta/security.go @@ -16,10 +16,31 @@ package meta +type AgentPwd struct { + inited bool + password string +} + var ( - OCEANBASE_PWD string + OCEANBASE_PWD string + OBPROXY_SYS_PWD string + AGENT_PWD AgentPwd + OCEANBASE_PASSWORD_INITIALIZED bool // Which means the oceanbase password has been initialized ) +func (p *AgentPwd) Inited() bool { + return p.inited +} + +func (p *AgentPwd) GetPassword() string { + return p.password +} + +func (p *AgentPwd) SetPassword(pwd string) { + p.password = pwd + p.inited = true +} + func GetOceanbasePwd() string { if OCS_AGENT != nil && (OCS_AGENT.IsClusterAgent() || OCS_AGENT.IsTakeover()) { return OCEANBASE_PWD @@ -29,4 +50,20 @@ func GetOceanbasePwd() string { func SetOceanbasePwd(pwd string) { OCEANBASE_PWD = pwd + if !OCEANBASE_PASSWORD_INITIALIZED { + OCEANBASE_PASSWORD_INITIALIZED = true + } +} + +func ClearOceanbasePwd() { + OCEANBASE_PWD = "" + OCEANBASE_PASSWORD_INITIALIZED = false +} + +func GetObproxySysPwd() string { + return OBPROXY_SYS_PWD +} + +func SetObproxySysPwd(pwd string) { + OBPROXY_SYS_PWD = pwd } diff --git a/agent/repository/db/obproxy/instance.go b/agent/repository/db/obproxy/instance.go new file mode 100644 index 00000000..d3d5065b --- /dev/null +++ b/agent/repository/db/obproxy/instance.go @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package obproxy + +import ( + "time" + + log "github.com/sirupsen/logrus" + + "github.com/oceanbase/obshell/agent/config" + "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/meta" + "github.com/oceanbase/obshell/agent/repository/driver" + "gorm.io/gorm" + "gorm.io/gorm/logger" + "gorm.io/gorm/schema" +) + +var ( + obproxyInstance *gorm.DB + + WAIT_OBPROXY_CONNECTED_MAX_TIMES = 100 + WAIT_OBPROXY_CONNECTED_MAX_INTERVAL = 10 * time.Second +) + +func LoadObproxyInstance() (db *gorm.DB, err error) { + if meta.OBPROXY_SQL_PORT == 0 { + return nil, errors.New("obproxy sql port has not been initialized") + } + dsConfig := config.NewObproxyDataSourceConfig().SetPort(meta.OBPROXY_SQL_PORT).SetPassword(meta.OBPROXY_SYS_PWD) + + gormConfig := gorm.Config{ + Logger: logger.Default.LogMode(dsConfig.GetLoggerLevel()), + NamingStrategy: schema.NamingStrategy{ + SingularTable: constant.DB_SINGULAR_TABLE, + }} + db, err = gorm.Open(driver.OpenObproxy(dsConfig.GetDSN()), &gormConfig) + if err == nil { + releaseDB(obproxyInstance) + obproxyInstance = db + } else { + return nil, errors.Wrap(err, "load obproxy instance failed") + } + return obproxyInstance, nil +} + +func LoadObproxyInstanceForHealthCheck(dsConfig *config.ObDataSourceConfig) (err error) { + db, err := LoadTempObproxyInstance(dsConfig) + if err != nil { + return errors.Wrap(err, "load obproxy instance failed") + } + if err := db.Exec("show proxyconfig").Error; err != nil { + return errors.Wrap(err, "check obproxy instance failed") + } + meta.OBPROXY_SYS_PWD = dsConfig.GetPassword() + releaseDB(db) + return err +} + +func LoadTempObproxyInstance(dsConfig *config.ObDataSourceConfig) (db *gorm.DB, err error) { + gormConfig := gorm.Config{ + Logger: logger.Default.LogMode(dsConfig.GetLoggerLevel()), + NamingStrategy: schema.NamingStrategy{ + SingularTable: constant.DB_SINGULAR_TABLE, + }} + db, err = gorm.Open(driver.OpenObproxy(dsConfig.GetDSN()), &gormConfig) + if err != nil { + return nil, errors.Wrap(err, "load temp obproxy instance failed") + } + return db, nil +} + +func GetObproxyInstance() (*gorm.DB, error) { + if obproxyInstance == nil { + log.Info("obproxy instance is nil, load obproxy instance") + if _, err := LoadObproxyInstance(); err != nil { + return nil, err + } + } + // health check + if err := obproxyInstance.Exec("show proxyconfig").Error; err != nil { + log.WithError(err).Warn("obproxy instance is not available") + return nil, err + } + return obproxyInstance, nil +} + +func releaseDB(preDB *gorm.DB) { + // Delay release db + if preDB != nil { + db, err := preDB.DB() + if err != nil { + log.WithError(err).Warn("release pre db failed") + } + + go func() { + defer func() { + err := recover() + if err != nil { + log.WithError(err.(error)).Warn("release pre db failed") + } + }() + + for db.Stats().InUse != 0 { + log.Debug("pre db is using, wait for release") + time.Sleep(time.Second) + } + db.Close() + }() + } +} diff --git a/agent/repository/db/oceanbase/instance.go b/agent/repository/db/oceanbase/instance.go index bd6d2e62..ca59c6e2 100644 --- a/agent/repository/db/oceanbase/instance.go +++ b/agent/repository/db/oceanbase/instance.go @@ -47,6 +47,10 @@ func GetInstance() (db *gorm.DB, err error) { return getSqlExecutableInstance(TEST_OCEANBASE_SQL) } +func GetRawInstance() (db *gorm.DB) { + return dbInstance +} + func ClearInstance() { dbInstance = nil } diff --git a/agent/repository/db/oceanbase/loader.go b/agent/repository/db/oceanbase/loader.go index 2a96ecbc..36ac0b8c 100644 --- a/agent/repository/db/oceanbase/loader.go +++ b/agent/repository/db/oceanbase/loader.go @@ -133,6 +133,28 @@ func LoadGormWithTenant(tenant string, password string) (*gorm.DB, error) { return db, nil } +// LoadTmpInstanceWithTenant creates a db instance according to the configuration. +func LoadGormWithTenantForTest(tenant string, password string) error { + dsConfig := config.NewObDataSourceConfig(). + SetPassword(password). + SetParseTime(true). + SetUsername("root@" + tenant). + SetDBName(""). + SetTryTimes(10) + dsConfig.SetLoggerLevel(logger.Silent) + if err := fillConfigPort(dsConfig); err != nil { + return errors.Wrap(err, "get port failed") + } + db, err := createGormDbByConfig(dsConfig) + defer func() { + if db != nil { + oceanbaseDB, _ := db.DB() + oceanbaseDB.Close() + } + }() + return err +} + // LoadOceanbaseInstance creates a db instance according to the configuration. // The `config` is a variable-length parameter, and the corresponding operation is selected // according to whether the parameter is set or not. If there are no special requirements, do not set config. @@ -281,3 +303,12 @@ func loadObGormForTest(dsConfig *config.ObDataSourceConfig) error { } return nil } + +func LoadTempOceanbaseInstance(dsConfig *config.ObDataSourceConfig) (*gorm.DB, error) { + db, err := gorm.Open(driver.Open(dsConfig.GetDSN())) + if err != nil { + log.WithError(err).Error("open ob db failed") + return nil, err + } + return db, nil +} diff --git a/agent/repository/db/sqlite/builder.go b/agent/repository/db/sqlite/builder.go index 4ed68d3e..ac680ce0 100644 --- a/agent/repository/db/sqlite/builder.go +++ b/agent/repository/db/sqlite/builder.go @@ -119,6 +119,7 @@ var SqliteTables = []interface{}{ sqlite.AllAgent{}, sqlite.ObSysParameter{}, sqlite.OcsInfo{}, + sqlite.ObproxyInfo{}, sqlite.ObGlobalConfig{}, sqlite.ObZoneConfig{}, sqlite.ObServerConfig{}, @@ -130,6 +131,8 @@ var SqliteTables = []interface{}{ sqlite.SubTaskLog{}, sqlite.DagInstance{}, sqlite.NodeInstance{}, + sqlite.UpgradePkgInfo{}, + sqlite.UpgradePkgChunk{}, } // MigrateSqliteTables will check if the sqlite tables exist, if not, it will create them. @@ -141,13 +144,10 @@ func MigrateSqliteTables(forUpgrade bool) (err error) { } // Check if sqlite tables exist. - var count int - err = ocs_db_sqlite.Raw("SELECT COUNT(*) FROM sqlite_master WHERE type='table'").Scan(&count).Error - if err != nil { - return err - } - if count < len(SqliteTables) { - return ocs_db_sqlite.AutoMigrate(SqliteTables...) + for _, table := range SqliteTables { + if !ocs_db_sqlite.Migrator().HasTable(table) { + return ocs_db_sqlite.AutoMigrate(SqliteTables...) + } } // Check if agent has been initialized. diff --git a/agent/repository/driver/oceanbase.go b/agent/repository/driver/oceanbase.go index ef0678e1..08e60cb7 100644 --- a/agent/repository/driver/oceanbase.go +++ b/agent/repository/driver/oceanbase.go @@ -33,6 +33,14 @@ func Open(dsn string) gorm.Dialector { } } +func OpenObproxy(dsn string) gorm.Dialector { + mysqlDialector := mysql.Open(dsn).(*mysql.Dialector) + mysqlDialector.Config.SkipInitializeWithVersion = true + return Dialector{ + Dialector: *mysqlDialector, + } +} + func (dialector Dialector) Migrator(db *gorm.DB) gorm.Migrator { mysqlMigrator := mysql.Migrator{ Migrator: migrator.Migrator{ diff --git a/agent/repository/model/bo/charset.go b/agent/repository/model/bo/charset.go new file mode 100644 index 00000000..42bafe5b --- /dev/null +++ b/agent/repository/model/bo/charset.go @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package bo + +type CollationInfo struct { + IsDefault bool `json:"is_default"` + Name string `json:"name"` +} + +type CharsetInfo struct { + Name string `json:"name"` + Description string `json:"description"` + Collations []CollationInfo `json:"collations"` + Maxlen int64 `json:"maxlen"` +} diff --git a/agent/repository/model/bo/database.go b/agent/repository/model/bo/database.go new file mode 100644 index 00000000..4a74b897 --- /dev/null +++ b/agent/repository/model/bo/database.go @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package bo + +type Database struct { + DbName string `json:"db_name"` + Charset string `json:"charset"` + Collation string `json:"collation"` + ReadOnly bool `json:"read_only"` + CreateTime int64 `json:"create_time"` + ConnectionUrls []ObproxyAndConnectionString `json:"connection_urls"` +} diff --git a/agent/repository/model/bo/obcluster.go b/agent/repository/model/bo/obcluster.go new file mode 100644 index 00000000..cbd5b69a --- /dev/null +++ b/agent/repository/model/bo/obcluster.go @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package bo + +import ( + "time" + + "github.com/oceanbase/obshell/agent/lib/parse" +) + +type BaseResourceStats struct { + CpuCoreTotal float64 `json:"cpu_core_total"` + CpuCoreAssigned float64 `json:"cpu_core_assigned"` + CpuCoreAssignedPercent float64 `json:"cpu_core_assigned_percent"` + MemoryTotal string `json:"memory_total"` + MemoryAssigned string `json:"memory_assigned"` + MemoryInBytesTotal int64 `json:"memory_in_bytes_total"` + MemoryInBytesAssigned int64 `json:"memory_in_bytes_assigned"` + MemoryAssignedPercent float64 `json:"memory_assigned_percent"` + DiskTotal string `json:"disk_total"` + DiskAssigned string `json:"disk_assigned"` + DiskInBytesTotal int64 `json:"disk_in_bytes_total"` + DiskInBytesAssigned int64 `json:"disk_in_bytes_assigned"` + DiskAssignedPercent float64 `json:"disk_assigned_percent"` +} + +func (r *BaseResourceStats) Add(stats *BaseResourceStats) { + r.CpuCoreTotal += stats.CpuCoreTotal + r.CpuCoreAssigned += stats.CpuCoreAssigned + r.MemoryInBytesTotal += stats.MemoryInBytesTotal + r.MemoryInBytesAssigned += stats.MemoryInBytesAssigned + r.DiskInBytesTotal += stats.DiskInBytesTotal + r.DiskInBytesAssigned += stats.DiskInBytesAssigned + + r.CpuCoreAssignedPercent = r.CpuCoreAssigned / r.CpuCoreTotal * 100 + r.MemoryAssignedPercent = float64(r.MemoryInBytesAssigned) / float64(r.MemoryInBytesTotal) * 100 + r.DiskAssignedPercent = float64(r.DiskInBytesAssigned) / float64(r.DiskInBytesTotal) * 100 + r.MemoryTotal = parse.FormatCapacity(r.MemoryInBytesTotal) + r.MemoryAssigned = parse.FormatCapacity(r.MemoryInBytesAssigned) + r.DiskTotal = parse.FormatCapacity(r.DiskInBytesTotal) + r.DiskAssigned = parse.FormatCapacity(r.DiskInBytesAssigned) +} + +type ResourceStatsExtendDisk struct { + BaseResourceStats + DiskUsed string `json:"disk_used"` + DiskFree string `json:"disk_free"` + DiskInBytesUsed int64 `json:"disk_in_bytes_used"` + DiskInBytesFree int64 `json:"disk_in_bytes_free"` + DiskUsedPercent float64 `json:"disk_used_percent"` +} + +func (r *ResourceStatsExtendDisk) FillExtendDiskStats() { + r.DiskUsed = parse.FormatCapacity(r.DiskInBytesAssigned) + r.DiskInBytesUsed = r.DiskInBytesAssigned + r.DiskInBytesFree = r.DiskInBytesTotal - r.DiskInBytesAssigned + r.DiskFree = parse.FormatCapacity(r.DiskInBytesFree) + r.DiskUsedPercent = float64(r.DiskInBytesUsed) / float64(r.DiskInBytesTotal) * 100 +} + +type ServerResourceStats struct { + ResourceStatsExtendDisk + Ip string `json:"ip"` + Port int `json:"port"` + Zone string `json:"zone"` +} + +type Observer struct { + Id int64 `json:"id"` + Ip string `json:"ip"` + SvrPort int `json:"svr_port"` + SqlPort int `json:"sql_port"` + Version string `json:"version"` + WithRootserver bool `json:"with_rootserver"` + Status string `json:"status"` + InnerStatus string `json:"inner_status"` + StartTime time.Time `json:"start_time"` + StopTime time.Time `json:"stop_time"` + Stats ServerResourceStats `json:"stats"` + Architecture string `json:"architecture"` +} + +type RootServer struct { + Ip string `json:"ip"` + Role string `json:"role"` + Zone string `json:"zone"` + SvrPort int `json:"svr_port"` +} + +type Zone struct { + Name string `json:"name"` + IdcName string `json:"idc_name"` + RegionName string `json:"region_name"` + Status string `json:"status"` + InnerStatus string `json:"inner_status"` + RootServer RootServer `json:"root_server"` + Servers []Observer `json:"servers"` +} + +type ClusterInfo struct { + ClusterBasicInfo + Stats BaseResourceStats `json:"stats"` + Zones []Zone `json:"zones"` + Tenants []TenantInfo `json:"tenants"` + TenantStats []TenantResourceStat `json:"tenant_stats"` +} + +type ClusterBasicInfo struct { + ClusterName string `json:"cluster_name"` + ClusterId int `json:"cluster_id"` + Status string `json:"status"` + IsCommunityEdition bool `json:"is_community_edition"` + ObVersion string `json:"ob_version"` +} + +type TenantResourceStat struct { + TenantId int `json:"tenant_id"` + TenantName string `json:"tenant_name"` + CpuUsedPercent float64 `json:"cpu_used_percent"` + MemoryUsedPercent float64 `json:"memory_used_percent"` + DataDiskUsage int64 `json:"data_disk_usage"` +} + +type ClusterParameter struct { + Name string `json:"name"` + Scope string `json:"scope"` + EditLevel string `json:"edit_level"` + DefaultValue string `json:"default_value"` + Section string `json:"section"` + DataType string `json:"data_type"` + Info string `json:"info"` + ServerValue []ObParameterValue `json:"ob_parameters"` + TenantValue []TenantParameterValue `json:"tenant_value,omitempty"` + Values []string `json:"values,omitempty"` + IsSingleValue bool `json:"is_single_value"` +} + +type ObParameterValue struct { + SvrIp string `json:"svr_ip"` + SvrPort int `json:"svr_port"` + Zone string `json:"zone"` + TenantId int `json:"tenant_id,omitempty"` + TenantName string `json:"tenant_name,omitempty"` + Value string `json:"value"` +} + +type TenantParameterValue struct { + TenantId int `json:"tenant_id"` + TenantName string `json:"tenant_name"` + Value string `json:"value"` +} diff --git a/agent/repository/model/bo/obproxy_config.go b/agent/repository/model/bo/obproxy_config.go new file mode 100644 index 00000000..fa3e1a94 --- /dev/null +++ b/agent/repository/model/bo/obproxy_config.go @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package bo + +type ProxyConfig struct { + Name string `json:"name"` + Value string `json:"value"` +} + +type ObproxyInfo struct { + Name string `json:"name"` + Info string `json:"info"` +} diff --git a/agent/repository/model/bo/task.go b/agent/repository/model/bo/task.go index 224882c6..a491d7ba 100644 --- a/agent/repository/model/bo/task.go +++ b/agent/repository/model/bo/task.go @@ -81,11 +81,11 @@ type SubTaskInstance struct { } type SubTaskLog struct { - Id int64 - SubTaskId int64 - ExecuteTimes int - LogContent string - IsSync bool - CreateTime time.Time - UpdateTime time.Time + Id int64 `json:"id"` + SubTaskId int64 `json:"sub_task_id"` + ExecuteTimes int `json:"execute_times"` + LogContent string `json:"log_content"` + IsSync bool `json:"is_sync"` + CreateTime time.Time `json:"create_time"` + UpdateTime time.Time `json:"update_time"` } diff --git a/agent/repository/model/bo/tenant.go b/agent/repository/model/bo/tenant.go index b20a2c45..9ec6ab15 100644 --- a/agent/repository/model/bo/tenant.go +++ b/agent/repository/model/bo/tenant.go @@ -21,6 +21,12 @@ import ( "github.com/oceanbase/obshell/agent/constant" ) +type ObTenantPreCheckResult struct { + IsConnectable bool `json:"is_connectable"` + IsPasswordExists bool `json:"is_password_exists"` + IsEmptyRootPassword bool `json:"is_empty_root_password"` +} + type DbaObTenantJobBo struct { JobId int JobType string @@ -94,8 +100,8 @@ type ObUnitConfig struct { Name string `json:"name"` MaxCpu float64 `json:"max_cpu"` MinCpu float64 `json:"min_cpu"` - MemorySize int `json:"memory_size"` - LogDiskSize int `json:"log_disk_size"` + MemorySize int64 `json:"memory_size"` + LogDiskSize int64 `json:"log_disk_size"` MaxIops uint `json:"max_iops"` MinIops uint `json:"min_iops"` } @@ -109,17 +115,47 @@ type ResourcePoolWithUnit struct { } type TenantInfo struct { - Name string `json:"tenant_name"` - Id int `json:"tenant_id"` - CreatedTime time.Time `json:"created_time"` - Mode string `json:"mode"` - Status string `json:"status"` - Locked string `json:"locked"` - PrimaryZone string `json:"primary_zone"` - Locality string `json:"locality"` - InRecyclebin string `json:"in_recyclebin"` - Charset string `json:"charset"` // Only for ORACLE tenant - Collation string `json:"collation"` // Only for ORACLE tenant - Whitelist string `json:"whitelist"` - Pools []*ResourcePoolWithUnit `json:"pools"` + Name string `json:"tenant_name"` + Id int `json:"tenant_id"` + CreatedTime time.Time `json:"created_time"` + Mode string `json:"mode"` + Status string `json:"status"` + Locked string `json:"locked"` + PrimaryZone string `json:"primary_zone"` + Locality string `json:"locality"` + InRecyclebin string `json:"in_recyclebin"` + Charset string `json:"charset"` // Only for ORACLE tenant + Collation string `json:"collation"` // Only for ORACLE tenant + Whitelist string `json:"whitelist"` + Pools []*ResourcePoolWithUnit `json:"pools"` + ReadOnly bool `json:"read_only"` // Default to false. + ConnectionStrings []ObproxyAndConnectionString `json:"connection_strings"` +} + +type TenantCompaction struct { + TenantId int `json:"tenant_id"` + FrozenScn int64 `json:"frozen_scn"` + FrozenTime time.Time `json:"frozen_time"` + GlobalBroadcastScn int64 `json:"global_broadcast_scn"` + LastScn int64 `json:"last_scn"` + LastFinishTime time.Time `json:"last_finish_time"` + StartTime time.Time `json:"start_time"` + Status string `json:"status"` + IsError string `json:"is_error"` + IsSuspended string `json:"is_suspended"` +} + +type TenantCompactionHistory struct { + TenantId int `json:"tenant_id"` + TenantName string `json:"tenant_name"` + Status string `json:"status"` + CostTime int64 `json:"cost_time"` + StartTime time.Time `json:"start_time"` + LastFinishTime time.Time `json:"last_finish_time"` +} + +type TenantSlowSqlCount struct { + TenantId int `json:"tenant_id"` + TenantName string `json:"tenant_name"` + Count int `json:"count"` } diff --git a/agent/repository/model/bo/tenant_user.go b/agent/repository/model/bo/tenant_user.go new file mode 100644 index 00000000..6cb64a36 --- /dev/null +++ b/agent/repository/model/bo/tenant_user.go @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package bo + +type ObproxyAndConnectionString struct { + Type string `json:"type"` + ObProxyAddress string `json:"obproxy_address"` + ObProxyPort int `json:"obproxy_port"` + ConnectionString string `json:"connection_string"` +} + +type DbPrivilege struct { + DbName string `json:"db_name"` + Privileges []string `json:"privileges"` +} + +type ObjectPrivilege struct { + Object string `json:"object"` + Privileges []string `json:"privileges"` +} + +type ObUserSessionStats struct { + Total int64 `json:"total"` + Active int64 `json:"active"` +} + +type ObUserStats struct { + Session *ObUserSessionStats `json:"session"` +} + +type ObUser struct { + UserName string `json:"user_name"` + IsLocked bool `json:"is_locked"` + ConnectionStrings []ObproxyAndConnectionString `json:"connection_strings"` + AccessibleDatabases []string `json:"accessible_databases"` + GrantedRoles []string `json:"granted_roles"` + GlobalPrivileges []string `json:"global_privileges"` + DbPrivileges []DbPrivilege `json:"db_privileges"` + ObjectPrivileges []ObjectPrivilege `json:"object_privileges"` +} diff --git a/agent/repository/model/bo/upgrade_pkg_info.go b/agent/repository/model/bo/upgrade_pkg_info.go new file mode 100644 index 00000000..df241704 --- /dev/null +++ b/agent/repository/model/bo/upgrade_pkg_info.go @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package bo + +import "time" + +type UpgradePkgInfo struct { + PkgId int `json:"pkg_id"` + Name string `json:"name"` + Version string `json:"version"` + ReleaseDistribution string `json:"release_distribution"` + Distribution string `json:"distribution"` + Release string `json:"release"` + Architecture string `json:"architecture"` + Size uint64 `json:"size"` + PayloadSize uint64 `json:"payload_size"` + ChunkCount int `json:"chunk_count"` + Md5 string `json:"md5"` + UpgradeDepYaml string `json:"upgrade_dep_yaml"` + GmtModify time.Time `json:"gmt_modify"` +} diff --git a/agent/repository/model/oceanbase/charset.go b/agent/repository/model/oceanbase/charset.go new file mode 100644 index 00000000..1aa3ed02 --- /dev/null +++ b/agent/repository/model/oceanbase/charset.go @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package oceanbase + +// select * from information_schema.collations +type ObCollation struct { + Charset string `gorm:"column:CHARACTER_SET_NAME"` + Collation string `gorm:"column:COLLATION_NAME"` + Id int `gorm:"column:ID"` + IsDefault string `gorm:"column:IS_DEFAULT"` +} + +type ObCharset struct { + Charset string `gorm:"column:Charset"` + Description string `gorm:"column:Description"` + DefaultCollation string `gorm:"column:Default collation"` + MaxLen int64 `gorm:"column:Maxlen"` +} diff --git a/agent/repository/model/oceanbase/dag_instance.go b/agent/repository/model/oceanbase/dag_instance.go index a59994b3..6df75731 100644 --- a/agent/repository/model/oceanbase/dag_instance.go +++ b/agent/repository/model/oceanbase/dag_instance.go @@ -19,6 +19,7 @@ package oceanbase import ( "time" + "github.com/oceanbase/obshell/agent/engine/task" "github.com/oceanbase/obshell/agent/repository/model/bo" ) @@ -45,8 +46,8 @@ type DagInstance struct { func (d *DagInstance) ToBO() *bo.DagInstance { MaintenanceType := d.MaintenanceType - if d.IsMaintenance && MaintenanceType == 1 { - MaintenanceType = 2 + if d.IsMaintenance && MaintenanceType == task.NOT_UNDER_MAINTENANCE { + MaintenanceType = task.GLOBAL_MAINTENANCE } return &bo.DagInstance{ Id: d.Id, diff --git a/agent/repository/model/oceanbase/database.go b/agent/repository/model/oceanbase/database.go new file mode 100644 index 00000000..4787d34e --- /dev/null +++ b/agent/repository/model/oceanbase/database.go @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package oceanbase + +type MysqlDb struct { + Host string `gorm:"column:host"` + Db string `gorm:"column:db"` + User string `gorm:"column:user"` + SelectPriv string `gorm:"column:select_priv"` + InsertPriv string `gorm:"column:insert_priv"` + UpdatePriv string `gorm:"column:update_priv"` + DeletePriv string `gorm:"column:delete_priv"` + CreatePriv string `gorm:"column:create_priv"` + DropPriv string `gorm:"column:drop_priv"` + GrantPriv string `gorm:"column:grant_priv"` + ReferencesPriv string `gorm:"column:references_priv"` + IndexPriv string `gorm:"column:index_priv"` + AlterPriv string `gorm:"column:alter_priv"` + CreateTmpTablePriv string `gorm:"column:create_tmp_table_priv"` + LockTablesPriv string `gorm:"column:lock_tables_priv"` + CreateViewPriv string `gorm:"column:create_view_priv"` + ShowViewPriv string `gorm:"column:show_view_priv"` + CreateRoutinePriv string `gorm:"column:create_routine_priv"` + AlterRoutinePriv string `gorm:"column:alter_routine_priv"` + ExecutePriv string `gorm:"column:execute_priv"` + EventPriv string `gorm:"column:event_priv"` + TriggerPriv string `gorm:"column:trigger_priv"` +} + +type DatabaseName struct { + Database string `gorm:"column:Database"` +} + +type Database struct { + CreateTimestamp int64 `gorm:"column:CREATE_TIMESTAMP"` + DatabaseID string `gorm:"column:DATABASE_ID"` + Name string `gorm:"column:NAME"` + CollationType string `gorm:"column:COLLATION_TYPE"` + CollationName string `gorm:"column:COLLATION_NAME"` + CharSetName string `gorm:"column:CHARACTER_SET_NAME"` + ReadOnly string `gorm:"column:READ_ONLY"` +} diff --git a/agent/repository/model/oceanbase/models.go b/agent/repository/model/oceanbase/models.go index af5d3459..02e26119 100644 --- a/agent/repository/model/oceanbase/models.go +++ b/agent/repository/model/oceanbase/models.go @@ -18,41 +18,68 @@ package oceanbase import ( "time" + + "github.com/oceanbase/obshell/agent/repository/model/bo" ) type ObParameters struct { - SvrIp string `gorm:"column:SVR_IP"` - SvrPort int `gorm:"column:SVR_PORT"` - Zone string `gorm:"column:ZONE"` - Scope string `gorm:"column:SCOPE"` - TenantId int `gorm:"column:TENANT_ID"` - Name string `gorm:"column:NAME"` - Value string `gorm:"column:VALUE"` - TenantName string + SvrIp string `gorm:"column:SVR_IP"` + SvrPort int `gorm:"column:SVR_PORT"` + Zone string `gorm:"column:ZONE"` + Scope string `gorm:"column:SCOPE"` + Name string `gorm:"column:NAME"` + Value string `gorm:"column:VALUE"` + TenantId int `gorm:"column:TENANT_ID"` + EditLevel string `gorm:"column:EDIT_LEVEL"` + DefaultValue string `gorm:"column:DEFAULT_VALUE"` + Section string `gorm:"column:SECTION"` + Info string `gorm:"column:INFO"` + DataType string `gorm:"column:DATA_TYPE"` +} + +func (ObParameters) TableName() string { + return "oceanbase.GV$OB_PARAMETERS" } type DbaObZones struct { Zone string `gorm:"column:ZONE"` Status string `gorm:"column:STATUS"` Region string `gorm:"column:REGION"` + Idc string `gorm:"column:IDC"` } type OBServer struct { - Zone string `gorm:"column:ZONE"` - SvrIp string `gorm:"column:SVR_IP"` - SvrPort int `gorm:"column:SVR_PORT"` - SqlPort int `gorm:"column:SQL_PORT"` - StopTime time.Time `gorm:"column:STOP_TIME"` - StartServiceTime time.Time `gorm:"column:START_SERVICE_TIME"` - WithRs string `gorm:"column:WITH_ROOTSERVER"` - Status string `gorm:"column:STATUS"` - BuildVersion string `gorm:"column:BUILD_VERSION"` + Zone string `gorm:"column:ZONE"` + Id int64 `gorm:"column:ID"` + SvrIp string `gorm:"column:SVR_IP"` + SvrPort int `gorm:"column:SVR_PORT"` + SqlPort int `gorm:"column:SQL_PORT"` + StopTime time.Time `gorm:"column:STOP_TIME"` + StartServiceTime time.Time `gorm:"column:START_SERVICE_TIME"` + WithRs string `gorm:"column:WITH_ROOTSERVER"` + Status string `gorm:"column:STATUS"` + BuildVersion string `gorm:"column:BUILD_VERSION"` + BlockMigrateInTime time.Time `gorm:"column:BLOCK_MIGRATE_IN_TIME"` } func (OBServer) TableName() string { return "oceanbase.DBA_OB_SERVERS" } +func (observer *OBServer) ToBo() bo.Observer { + return bo.Observer{ + Id: observer.Id, + Ip: observer.SvrIp, + SvrPort: observer.SvrPort, + SqlPort: observer.SqlPort, + Version: observer.BuildVersion, + InnerStatus: observer.Status, + StartTime: observer.StartServiceTime, + StopTime: observer.StopTime, + WithRootserver: observer.WithRs == "YES", + } +} + type ObLogStat struct { TenantId int `gorm:"column:TENANT_ID"` LsId int `gorm:"column:LS_ID"` @@ -80,3 +107,35 @@ type ObLogStat struct { func (ObLogStat) TableName() string { return "oceanbase.GV$OB_LOG_STAT" } + +type RootServer struct { + Zone string `gorm:"column:ZONE"` + Role string `gorm:"column:ROLE"` + SvrIp string `gorm:"column:SVR_IP"` + SvrPort int `gorm:"column:SVR_PORT"` +} + +func (r *RootServer) ToBO() bo.RootServer { + return bo.RootServer{ + Ip: r.SvrIp, + Role: r.Role, + SvrPort: r.SvrPort, + Zone: r.Zone, + } +} + +type SysStat struct { + ConId int64 `gorm:"column:CON_ID"` + SvrIp string `gorm:"column:SVR_IP"` + SvrPort int `gorm:"column:SVR_PORT"` + StatisticId int64 `gorm:"column:STATISTIC#"` + Name string `gorm:"column:NAME"` + Class int64 `gorm:"column:CLASS"` + Value int64 `gorm:"column:VALUE"` + ValueType string `gorm:"column:VALUE_TYPE"` + StatId int64 `gorm:"column:STAT_ID"` +} + +func (SysStat) TableName() string { + return "oceanbase.GV$sysstat" +} diff --git a/agent/repository/model/oceanbase/tenant.go b/agent/repository/model/oceanbase/tenant.go index 04fba6d5..6d5b5113 100644 --- a/agent/repository/model/oceanbase/tenant.go +++ b/agent/repository/model/oceanbase/tenant.go @@ -18,8 +18,16 @@ package oceanbase import ( "time" + + "github.com/oceanbase/obshell/agent/lib/parse" + "github.com/oceanbase/obshell/agent/repository/model/bo" ) +type TenantOverview struct { + DbaObTenant `json:",inline"` + ConnectionStrings []bo.ObproxyAndConnectionString `json:"connection_strings"` +} + type DbaObTenant struct { TenantID int `gorm:"column:TENANT_ID" json:"tenant_id"` TenantName string `gorm:"column:TENANT_NAME" json:"tenant_name"` @@ -30,6 +38,7 @@ type DbaObTenant struct { Locality string `gorm:"column:LOCALITY" json:"locality"` InRecyclebin string `gorm:"column:IN_RECYCLEBIN" json:"in_recyclebin"` CreatedTime time.Time `gorm:"column:CREATE_TIME" json:"created_time"` + ReadOnly bool `json:"read_only"` } type DbaObResourcePool struct { @@ -51,6 +60,11 @@ type CdbObSysVariable struct { Info string `gorm:"column:INFO" json:"info"` } +type ObSysVariableWithValue struct { + Name string `gorm:"column:Variable_name" json:"name"` + Value string `gorm:"column:Value" json:"value"` +} + type GvObParameter struct { Name string `gorm:"column:NAME" json:"name"` Value string `gorm:"column:VALUE" json:"value"` @@ -66,27 +80,46 @@ type DbaRecyclebin struct { CanPurge string `gorm:"column:CAN_PURGE" json:"can_purge"` } -// select * from information_schema.collations -type Collations struct { - Charset string `gorm:"column:CHARACTER_SET_NAME"` - Collation string `gorm:"column:COLLATION_NAME"` -} - type ObServerCapacity struct { - Zone string `gorm:"column:ZONE" json:"zone"` - SvrIp string `gorm:"column:SVR_IP" json:"svr_ip"` - SvrPort int `gorm:"column:SVR_PORT" json:"svr_port"` - SqlPort int `gorm:"column:SQL_PORT" json:"sql_port"` - CpuCapacity float64 `gorm:"column:CPU_CAPACITY" json:"cpu_capacity"` - CpuCapacityMax float64 `gorm:"column:CPU_CAPACITY_MAX" json:"cpu_capacity_max"` - MemCapacity int `gorm:"column:MEM_CAPACITY" json:"mem_capacity"` - LogDiskCapacity int `gorm:"column:LOG_DISK_CAPACITY" json:"log_disk_capacity"` + Zone string `gorm:"column:ZONE"` + SvrIp string `gorm:"column:SVR_IP"` + SvrPort int `gorm:"column:SVR_PORT"` + SqlPort int `gorm:"column:SQL_PORT"` + CpuCapacity float64 `gorm:"column:CPU_CAPACITY"` + CpuCapacityMax float64 `gorm:"column:CPU_CAPACITY_MAX"` + CpuAssigned float64 `gorm:"column:CPU_ASSIGNED"` + CpuAssignedMax float64 `gorm:"column:CPU_ASSIGNED_MAX"` + MemCapacity int64 `gorm:"column:MEM_CAPACITY"` + MemAssigned int64 `gorm:"column:MEM_ASSIGNED"` + LogDiskCapacity int64 `gorm:"column:LOG_DISK_CAPACITY"` + LogDiskAssigned int64 `gorm:"column:LOG_DISK_ASSIGNED"` + LogDiskInUse int64 `gorm:"column:LOG_DISK_IN_USE"` + DataDiskCapacity int64 `gorm:"column:DATA_DISK_CAPACITY"` + DataDiskAssigned int64 `gorm:"column:DATA_DISK_IN_USE"` } func (ObServerCapacity) TableName() string { return "oceanbase.GV$OB_SERVERS" } +func (o *ObServerCapacity) ToBO() bo.BaseResourceStats { + return bo.BaseResourceStats{ + CpuCoreTotal: o.CpuCapacity, + CpuCoreAssigned: o.CpuAssigned, + CpuCoreAssignedPercent: o.CpuAssigned / o.CpuCapacity * 100, + MemoryTotal: parse.FormatCapacity(o.MemCapacity), + MemoryAssigned: parse.FormatCapacity(o.MemAssigned), + MemoryInBytesTotal: o.MemCapacity, + MemoryInBytesAssigned: o.MemAssigned, + MemoryAssignedPercent: float64(o.MemAssigned) / float64(o.MemCapacity) * 100, + DiskTotal: parse.FormatCapacity(o.DataDiskCapacity), + DiskAssigned: parse.FormatCapacity(o.DataDiskAssigned), + DiskInBytesTotal: o.DataDiskCapacity, + DiskInBytesAssigned: o.DataDiskAssigned, + DiskAssignedPercent: float64(o.DataDiskAssigned) / float64(o.DataDiskCapacity) * 100, + } +} + type DbaObUnit struct { UnitId int `gorm:"column:UNIT_ID" json:"unit_id"` TenantId int `gorm:"column:TENANT_ID" json:"tenant_id"` @@ -98,8 +131,8 @@ type DbaObUnit struct { UnitConfigId int `gorm:"column:UNIT_CONFIG_ID" json:"unit_config_id"` MaxCpu float64 `gorm:"column:MAX_CPU" json:"max_cpu"` MinCpu float64 `gorm:"column:MIN_CPU" json:"min_cpu"` - MemorySize int `gorm:"column:MEMORY_SIZE" json:"memory_size"` - LogDiskSize int `gorm:"column:LOG_DISK_SIZE" json:"log_disk_size"` + MemorySize int64 `gorm:"column:MEMORY_SIZE" json:"memory_size"` + LogDiskSize int64 `gorm:"column:LOG_DISK_SIZE" json:"log_disk_size"` MaxIops uint `gorm:"column:MAX_IOPS" json:"max_iops"` MinIops uint `gorm:"column:MIN_IOPS" json:"min_iops"` } @@ -116,3 +149,36 @@ type DbaObTenantJob struct { StartTime time.Time `gorm:"column:START_TIME"` ModifyTime time.Time `gorm:"column:MODIFY_TIME"` } + +type CdbObMajorCompaction struct { + TenantId int `gorm:"column:TENANT_ID"` + FrozenScn int64 `gorm:"column:FROZEN_SCN"` + FrozenTime time.Time `gorm:"column:FROZEN_TIME"` + GlobalBroadcastScn int64 `gorm:"column:GLOBAL_BROADCAST_SCN"` + LastScn int64 `gorm:"column:LAST_SCN"` + LastFinishTime time.Time `gorm:"column:LAST_FINISH_TIME"` + StartTime time.Time `gorm:"column:START_TIME"` + Status string `gorm:"column:STATUS"` + IsError string `gorm:"column:IS_ERROR"` + IsSuspended string `gorm:"column:IS_SUSPENDED"` + Info string `gorm:"column:INFO"` +} + +func (CdbObMajorCompaction) TableName() string { + return "oceanbase.CDB_OB_MAJOR_COMPACTION" +} + +func (c *CdbObMajorCompaction) ToBO() *bo.TenantCompaction { + return &bo.TenantCompaction{ + TenantId: c.TenantId, + FrozenScn: c.FrozenScn, + FrozenTime: c.FrozenTime, + GlobalBroadcastScn: c.GlobalBroadcastScn, + LastScn: c.LastScn, + LastFinishTime: c.LastFinishTime, + StartTime: c.StartTime, + Status: c.Status, + IsError: c.IsError, + IsSuspended: c.IsSuspended, + } +} diff --git a/agent/repository/model/oceanbase/tenant_user.go b/agent/repository/model/oceanbase/tenant_user.go new file mode 100644 index 00000000..434c6dd6 --- /dev/null +++ b/agent/repository/model/oceanbase/tenant_user.go @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package oceanbase + +type SessionStats struct { + Count int64 `gorm:"column:COUNT"` + State string `gorm:"column:STATE"` +} + +type MysqlUser struct { + Host string `gorm:"column:host"` + User string `gorm:"column:user"` + Password string `gorm:"column:password"` + SelectPriv string `gorm:"column:select_priv"` + InsertPriv string `gorm:"column:insert_priv"` + UpdatePriv string `gorm:"column:update_priv"` + DeletePriv string `gorm:"column:delete_priv"` + CreatePriv string `gorm:"column:create_priv"` + DropPriv string `gorm:"column:drop_priv"` + ReloadPriv string `gorm:"column:reload_priv"` + ShutdownPriv string `gorm:"column:shutdown_priv"` + ProcessPriv string `gorm:"column:process_priv"` + FilePriv string `gorm:"column:file_priv"` + GrantPriv string `gorm:"column:grant_priv"` + ReferencesPriv string `gorm:"column:references_priv"` + IndexPriv string `gorm:"column:index_priv"` + AlterPriv string `gorm:"column:alter_priv"` + ShowDbPriv string `gorm:"column:show_db_priv"` + SuperPriv string `gorm:"column:super_priv"` + CreateTmpTablePriv string `gorm:"column:create_tmp_table_priv"` + LockTablesPriv string `gorm:"column:lock_tables_priv"` + ExecutePriv string `gorm:"column:execute_priv"` + ReplSlavePriv string `gorm:"column:repl_slave_priv"` + ReplClientPriv string `gorm:"column:repl_client_priv"` + CreateViewPriv string `gorm:"column:create_view_priv"` + ShowViewPriv string `gorm:"column:show_view_priv"` + CreateRoutinePriv string `gorm:"column:create_routine_priv"` + AlterRoutinePriv string `gorm:"column:alter_routine_priv"` + CreateUserPriv string `gorm:"column:create_user_priv"` + EventPriv string `gorm:"column:event_priv"` + TriggerPriv string `gorm:"column:trigger_priv"` + CreateTablespacePriv string `gorm:"column:create_tablespace_priv"` + SslType string `gorm:"column:ssl_type"` + SslCipher string `gorm:"column:ssl_cipher"` + X509Issuer string `gorm:"column:x509_issuer"` + X509Subject string `gorm:"column:x509_subject"` + MaxQuestions int64 `gorm:"column:max_questions"` + MaxUpdates int64 `gorm:"column:max_updates"` + MaxConnections int64 `gorm:"column:max_connections"` + MaxUserConnections int64 `gorm:"column:max_user_connections"` + Plugin string `gorm:"column:plugin"` + AuthenticationString string `gorm:"column:authentication_string"` + PasswordExpired string `gorm:"column:password_expired"` + AccountLocked string `gorm:"column:account_locked"` + DropDatabaseLinkPriv string `gorm:"column:drop_database_link_priv"` + CreateDatabaseLinkPriv string `gorm:"column:create_database_link_priv"` + CreateRolePriv string `gorm:"column:create_role_priv"` + DropRolePriv string `gorm:"column:drop_role_priv"` +} diff --git a/agent/repository/model/oceanbase/unit.go b/agent/repository/model/oceanbase/unit.go index 005bf98b..7ab7ba79 100644 --- a/agent/repository/model/oceanbase/unit.go +++ b/agent/repository/model/oceanbase/unit.go @@ -27,8 +27,8 @@ type DbaObUnitConfig struct { Name string `gorm:"column:name" json:"name"` MaxCpu float64 `gorm:"column:max_cpu" json:"max_cpu"` MinCpu float64 `gorm:"column:min_cpu" json:"min_cpu"` - MemorySize int `gorm:"column:memory_size" json:"memory_size"` - LogDiskSize int `gorm:"column:log_disk_size" json:"log_disk_size"` + MemorySize int64 `gorm:"column:memory_size" json:"memory_size"` + LogDiskSize int64 `gorm:"column:log_disk_size" json:"log_disk_size"` MaxIops uint `gorm:"column:max_iops" json:"max_iops"` MinIops uint `gorm:"column:min_iops" json:"min_iops"` GmtCreate time.Time `gorm:"column:create_time" json:"create_time"` diff --git a/agent/repository/model/oceanbase/upgrade_pkg_info.go b/agent/repository/model/oceanbase/upgrade_pkg_info.go index a9350088..cce15c4e 100644 --- a/agent/repository/model/oceanbase/upgrade_pkg_info.go +++ b/agent/repository/model/oceanbase/upgrade_pkg_info.go @@ -16,7 +16,11 @@ package oceanbase -import "time" +import ( + "time" + + "github.com/oceanbase/obshell/agent/repository/model/bo" +) type UpgradePkgInfo struct { PkgId int `gorm:"primaryKey;autoIncrement;not null"` @@ -33,3 +37,20 @@ type UpgradePkgInfo struct { UpgradeDepYaml string `gorm:"type:longtext"` GmtModify time.Time `gorm:"type:TIMESTAMP;default:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"` } + +func (upgradePkgInfo *UpgradePkgInfo) ToBO() bo.UpgradePkgInfo { + return bo.UpgradePkgInfo{ + PkgId: upgradePkgInfo.PkgId, + Name: upgradePkgInfo.Name, + Version: upgradePkgInfo.Version, + ReleaseDistribution: upgradePkgInfo.ReleaseDistribution, + Distribution: upgradePkgInfo.Distribution, + Release: upgradePkgInfo.Release, + Architecture: upgradePkgInfo.Architecture, + Size: upgradePkgInfo.Size, + PayloadSize: upgradePkgInfo.PayloadSize, + ChunkCount: upgradePkgInfo.ChunkCount, + Md5: upgradePkgInfo.Md5, + GmtModify: upgradePkgInfo.GmtModify, + } +} diff --git a/agent/repository/model/sqlite/dag_instance.go b/agent/repository/model/sqlite/dag_instance.go index a619066c..dccd7906 100644 --- a/agent/repository/model/sqlite/dag_instance.go +++ b/agent/repository/model/sqlite/dag_instance.go @@ -19,6 +19,7 @@ package sqlite import ( "time" + "github.com/oceanbase/obshell/agent/engine/task" "github.com/oceanbase/obshell/agent/repository/model/bo" ) @@ -42,9 +43,13 @@ type DagInstance struct { } func (d *DagInstance) ToBO() *bo.DagInstance { - MaintenanceType := 0 + MaintenanceType := task.NOT_UNDER_MAINTENANCE if d.IsMaintenance { - MaintenanceType = 2 + if task.DAG_TYPE_MAP[task.DAG_OBPROXY] == d.Type { + MaintenanceType = task.OBPROXY_MAINTENACE + } else { + MaintenanceType = task.GLOBAL_MAINTENANCE + } } return &bo.DagInstance{ Id: d.Id, diff --git a/agent/repository/model/sqlite/obproxy_info.go b/agent/repository/model/sqlite/obproxy_info.go new file mode 100644 index 00000000..5f65e6be --- /dev/null +++ b/agent/repository/model/sqlite/obproxy_info.go @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sqlite + +type ObproxyInfo struct { + Name string `gorm:"type:varchar(128);not null;unique"` + Value string `gorm:"type:varchar(65536);not null"` + Info string +} diff --git a/agent/repository/model/sqlite/upgrade_pkg_chunk.go b/agent/repository/model/sqlite/upgrade_pkg_chunk.go new file mode 100644 index 00000000..2eafabff --- /dev/null +++ b/agent/repository/model/sqlite/upgrade_pkg_chunk.go @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sqlite + +type UpgradePkgChunk struct { + PkgId int `gorm:"primaryKey;column:pkg_id;not null"` + ChunkId int `gorm:"primaryKey;column:chunk_id;not null"` + ChunkCount int `gorm:"not null"` + Chunk []byte `gorm:"type:MEDIUMBLOB;not null"` +} diff --git a/agent/repository/model/sqlite/upgrade_pkg_info.go b/agent/repository/model/sqlite/upgrade_pkg_info.go new file mode 100644 index 00000000..fac4cd54 --- /dev/null +++ b/agent/repository/model/sqlite/upgrade_pkg_info.go @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sqlite + +import "time" + +type UpgradePkgInfo struct { + PkgId int `gorm:"primaryKey;autoIncrement;not null"` + Name string `gorm:"type:varchar(128);not null"` + Version string `gorm:"type:varchar(128);not null"` + ReleaseDistribution string `gorm:"type:varchar(128);not null"` + Distribution string `gorm:"type:varchar(128);not null"` + Release string `gorm:"type:varchar(128);not null"` + Architecture string `gorm:"type:varchar(128);not null"` + Size uint64 `gorm:"not null"` + PayloadSize uint64 `gorm:"not null"` + ChunkCount int `gorm:"not null"` + Md5 string `gorm:"type:varchar(128);not null"` + GmtModify time.Time `gorm:"type:TIMESTAMP;default:CURRENT_TIMESTAMP"` +} diff --git a/agent/rpc/agent_handler.go b/agent/rpc/agent_handler.go index d67e6058..264cc71f 100644 --- a/agent/rpc/agent_handler.go +++ b/agent/rpc/agent_handler.go @@ -30,11 +30,39 @@ import ( "github.com/oceanbase/obshell/param" ) -func agentJoinHandler(c *gin.Context) { +func agentAddTokenHandler(c *gin.Context) { if !meta.OCS_AGENT.IsMasterAgent() { common.SendResponse(c, nil, errors.Occurf(errors.ErrBadRequest, "%s:%d is not master", meta.OCS_AGENT.GetIp(), meta.OCS_AGENT.GetPort())) return } + var param param.AddTokenParam + ip := c.RemoteIP() + if err := c.Bind(¶m); err != nil { + return + } + if param.AgentInfo.Ip == "" { + param.AgentInfo.Ip = ip + } + + agentService := agentservice.AgentService{} + agentInstance, err := agentService.FindAgentInstance(¶m.AgentInfo) + if err != nil { + common.SendResponse(c, nil, err) + return + } + if agentInstance != nil { + common.SendResponse(c, nil, errors.Occurf(errors.ErrBadRequest, "%s:%d already exists", agentInstance.Ip, agentInstance.Port)) + return + } + + common.SendResponse(c, nil, agent.AddSingleToken(param)) +} + +func agentJoinHandler(c *gin.Context) { + if !meta.OCS_AGENT.IsMasterAgent() { + common.SendResponse(c, nil, errors.Occurf(errors.ErrBadRequest, "%s is not master", meta.OCS_AGENT.String())) + return + } ip := c.RemoteIP() var param param.JoinMasterParam @@ -53,7 +81,7 @@ func agentJoinHandler(c *gin.Context) { } if agentInstance != nil { - common.SendResponse(c, nil, errors.Occurf(errors.ErrBadRequest, "%s:%d already exists", agentInstance.Ip, agentInstance.Port)) + common.SendResponse(c, nil, errors.Occurf(errors.ErrBadRequest, "%s already exists", agentInstance.String())) return } else { if err := agent.AddFollowerAgent(param); err != nil { @@ -73,7 +101,7 @@ func agentRemoveHandler(c *gin.Context) { } else if meta.OCS_AGENT.IsSingleAgent() { common.SendResponse(c, task.DagDetailDTO{}, nil) } else { - common.SendResponse(c, nil, errors.Occurf(errors.ErrBadRequest, "%s:%d is %s", meta.OCS_AGENT.GetIp(), meta.OCS_AGENT.GetPort(), meta.OCS_AGENT.GetIdentity())) + common.SendResponse(c, nil, errors.Occurf(errors.ErrBadRequest, "%s is %s", meta.OCS_AGENT.String(), meta.OCS_AGENT.GetIdentity())) } } @@ -132,7 +160,7 @@ func updateAllAgentsHandler(c *gin.Context) { func obServerDeployHandler(c *gin.Context) { if !meta.OCS_AGENT.IsFollowerAgent() { - common.SendResponse(c, nil, errors.Occurf(errors.ErrBadRequest, "%s:%d is not follower agent", meta.OCS_AGENT.GetIp(), meta.OCS_AGENT.GetPort())) + common.SendResponse(c, nil, errors.Occurf(errors.ErrBadRequest, "%s is not follower agent", meta.OCS_AGENT.String())) return } var dirs param.DeployTaskParams @@ -151,7 +179,7 @@ func obServerDeployHandler(c *gin.Context) { func obServerDestroyHandler(c *gin.Context) { if !meta.OCS_AGENT.IsFollowerAgent() { - common.SendResponse(c, nil, errors.Occurf(errors.ErrBadRequest, "%s:%d is not follower agent", meta.OCS_AGENT.GetIp(), meta.OCS_AGENT.GetPort())) + common.SendResponse(c, nil, errors.Occurf(errors.ErrBadRequest, "%s is not follower agent", meta.OCS_AGENT.String())) return } dag, err := ob.CreateDestroyDag() @@ -228,7 +256,7 @@ func agentUpdateHandler(c *gin.Context) { func takeOverAgentUpdateBinaryHandler(c *gin.Context) { if !meta.OCS_AGENT.IsTakeover() { - common.SendResponse(c, nil, errors.Occurf(errors.ErrBadRequest, "%s:%d is not takeover agent", meta.OCS_AGENT.GetIp(), meta.OCS_AGENT.GetPort())) + common.SendResponse(c, nil, errors.Occurf(errors.ErrBadRequest, "%s is not takeover agent", meta.OCS_AGENT.String())) return } diff --git a/agent/rpc/agent_route.go b/agent/rpc/agent_route.go index c63a1bb5..d3184068 100644 --- a/agent/rpc/agent_route.go +++ b/agent/rpc/agent_route.go @@ -36,6 +36,7 @@ func InitOcsAgentRpcRoutes(s *http2.State, r *gin.Engine, isLocalRoute bool) { agent := v1.Group(constant.URI_AGENT_GROUP) agent.POST("", agentJoinHandler) + agent.POST(constant.URI_TOKEN, agentAddTokenHandler) agent.DELETE("", agentRemoveHandler) agent.POST(constant.URI_UPDATE, agentUpdateHandler) agent.POST(constant.URI_SYNC_BIN, takeOverAgentUpdateBinaryHandler) diff --git a/agent/secure/auth.go b/agent/secure/auth.go index d82114e3..5763c816 100644 --- a/agent/secure/auth.go +++ b/agent/secure/auth.go @@ -18,46 +18,70 @@ package secure import ( "errors" + "fmt" "strconv" "strings" log "github.com/sirupsen/logrus" "github.com/oceanbase/obshell/agent/config" + "github.com/oceanbase/obshell/agent/meta" "github.com/oceanbase/obshell/agent/repository/db/oceanbase" ) -type AgentAuth struct { - Password string - Ts int64 +type RouteType int +type VerifyType int + +const ( + ROUTE_OCEANBASE RouteType = iota + ROUTE_OBPROXY + ROUTE_TASK + + OCEANBASE_PASSWORD VerifyType = iota + AGENT_PASSWORD +) + +func VerifyTimeStamp(ts string, curTs int64) error { + tsInt, err := strconv.ParseInt(ts, 10, 64) + if err != nil { + log.WithError(err).Errorf("parse ts failed, ts:%v", ts) + return err + } + if curTs > int64(tsInt) { + log.Warnf("auth expired at: %v, current: %v", ts, curTs) + return errors.New("auth expired") + } + return nil } -func VerifyAuth(pwd string, ts string, curTs int64) error { +func VerifyAuth(pwd string, ts string, curTs int64, verifyType VerifyType) error { if pwd != "" { - tsInt, err := strconv.ParseInt(ts, 10, 64) - if err != nil { - log.WithError(err).Errorf("parse ts failed, ts:%v", ts) + if err := VerifyTimeStamp(ts, curTs); err != nil { return err } - if curTs > int64(tsInt) { - log.Warnf("auth expired at: %v, current: %v", ts, curTs) - return errors.New("auth expired") - } } - if pwd != meta.OCEANBASE_PWD { - if oceanbase.HasOceanbaseInstance() { - if err := VerifyOceanbasePassword(pwd); err != nil { - return err - } - if err := dumpPassword(); err != nil { - log.WithError(err).Error("dump password failed") - return err + if verifyType == AGENT_PASSWORD { + if pwd != meta.AGENT_PWD.GetPassword() { + return fmt.Errorf("access denied: %s", "agent password is incorrect") + } + } else if verifyType == OCEANBASE_PASSWORD { + if pwd != meta.OCEANBASE_PWD { + if oceanbase.HasOceanbaseInstance() { + if err := VerifyOceanbasePassword(pwd); err != nil { + return err + } + if err := dumpPassword(); err != nil { + log.WithError(err).Error("dump password failed") + return err + } + } else { + return fmt.Errorf("access denied: %s", "oceanbase password is incorrect") } - } else { - return errors.New("access denied") } + } else { + return errors.New("unknown password type") } return nil } diff --git a/agent/secure/body.go b/agent/secure/body.go index dca99c21..b3d36642 100644 --- a/agent/secure/body.go +++ b/agent/secure/body.go @@ -86,7 +86,7 @@ func EncryptBodyWithRsa(agentInfo meta.AgentInfoInterface, body interface{}) (en } pk := GetAgentPublicKey(agentInfo) if pk == "" { - log.Warnf("no key for agent '%s:%d'", agentInfo.GetIp(), agentInfo.GetPort()) + log.Warnf("no key for agent '%s'", agentInfo.String()) return } encryptedBody, err = crypto.RSAEncrypt(mBody, pk) diff --git a/agent/secure/crypto.go b/agent/secure/crypto.go index b9f9ef0b..cf309246 100644 --- a/agent/secure/crypto.go +++ b/agent/secure/crypto.go @@ -88,19 +88,19 @@ func GetAgentPublicKey(agent meta.AgentInfoInterface) string { pk, err := getPublicKeyByAgentInfo(agent) if err != nil { // Need to query sqlite instead. - log.WithError(err).Errorf("query oceanbase '%s' for '%s:%d' failed", constant.TABLE_ALL_AGENT, agent.GetIp(), agent.GetPort()) + log.WithError(err).Errorf("query oceanbase '%s' for '%s' failed", constant.TABLE_ALL_AGENT, agent.String()) } if pk != "" { err = updateAgentPublicKey(agent, pk) if err != nil { - log.WithError(err).Errorf("update sqlite '%s' for '%s:%d' failed", constant.TABLE_ALL_AGENT, agent.GetIp(), agent.GetPort()) + log.WithError(err).Errorf("update sqlite '%s' for '%s' failed", constant.TABLE_ALL_AGENT, agent.String()) } // Although backup failed, the key should be returned. return pk } pk, err = getPublicKeyByAgentInfo(agent) if err != nil { - log.WithError(err).Errorf("query sqlite '%s' for '%s:%d' failed", constant.TABLE_ALL_AGENT, agent.GetIp(), agent.GetPort()) + log.WithError(err).Errorf("query sqlite '%s' for '%s' failed", constant.TABLE_ALL_AGENT, agent.String()) } if pk != "" { return pk @@ -113,27 +113,49 @@ func GetAgentPublicKey(agent meta.AgentInfoInterface) string { return "" } -// LoadPassword will load password from environment variable or sqlite. -func LoadPassword(password *string) error { +// LoadOceanbasePassword will load password from environment variable or sqlite. +func LoadOceanbasePassword(password *string) error { if password == nil { rootPwd, isSet := syscall.Getenv(constant.OB_ROOT_PASSWORD) if !isSet { - return CheckPasswordInSqlite() + return CheckObPasswordInSqlite() } log.Info("get password from environment variable") password = &rootPwd } else { - log.Infof("get password from command line: %s", *password) + log.Infof("get password from command line.") } // clear root password, avoid to cover sqlite when agent restart syscall.Unsetenv(constant.OB_ROOT_PASSWORD) meta.SetOceanbasePwd(*password) - go dumpTempPassword(*password) + go dumpTempObPassword(*password) return nil } -func dumpTempPassword(pwd string) { +func LoadAgentPassword() error { + var pwd string + err := getOCSInfo(constant.CONFIG_AGENT_PASSWORD, &pwd) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + log.Info("no password in sqlite") + return nil + } + return err + } + // Decrypt password + if pwd != "" { + pwd, err = Crypter.Decrypt(pwd) + if err != nil { + return err + } + } + meta.AGENT_PWD.SetPassword(pwd) + return nil + +} + +func dumpTempObPassword(pwd string) { log.Info("current password is temporary, will dump it into sqlite") for meta.OCEANBASE_PWD == pwd { if oceanbase.HasOceanbaseInstance() { @@ -148,9 +170,9 @@ func dumpTempPassword(pwd string) { } } -// CheckPasswordInSqlite will try connecting ob using password stored in sqlite. -func CheckPasswordInSqlite() error { - log.Info("retore password from sqlite") +// CheckObPasswordInSqlite will try connecting ob using password stored in sqlite. +func CheckObPasswordInSqlite() error { + log.Info("retore password of root@sys from sqlite") password, err := getCipherPassword() if err != nil { if !errors.Is(err, gorm.ErrRecordNotFound) { @@ -186,6 +208,19 @@ func dumpPassword() error { return updateOBConifg(constant.CONFIG_ROOT_PWD, passwrod) } +func dumpObproxyPassword() error { + passwrod := meta.OBPROXY_SYS_PWD + if meta.OBPROXY_SYS_PWD != "" { + cipherPassword, err := Crypter.Encrypt(meta.OBPROXY_SYS_PWD) + if err != nil { + log.WithError(err).Error("encrypt password failed") + return err + } + passwrod = cipherPassword + } + return updateObproxyConfig(constant.OBPROXY_CONFIG_OBPROXY_SYS_PASSWORD, passwrod) +} + func EncryptPwdInObConfigs(configs []sqlite.ObConfig) (err error) { for i := range configs { if configs[i].Name == constant.CONFIG_ROOT_PWD && configs[i].Value != "" { diff --git a/agent/secure/handler.go b/agent/secure/handler.go index 2d7ca2ae..a5dbac6d 100644 --- a/agent/secure/handler.go +++ b/agent/secure/handler.go @@ -34,7 +34,7 @@ func GetSecret(ctx context.Context) *meta.AgentSecret { } func sendGetSecretApi(agentInfo meta.AgentInfoInterface) *meta.AgentSecret { - log.Infof("Send get secret request from '%s:%d'", agentInfo.GetIp(), agentInfo.GetPort()) + log.Infof("Send get secret request from '%s'", agentInfo.String()) ret := &meta.AgentSecret{} err := http.SendGetRequest(agentInfo, "/api/v1/secret", nil, ret) if err != nil { diff --git a/agent/secure/header.go b/agent/secure/header.go index 58a20b51..7e4c35fe 100644 --- a/agent/secure/header.go +++ b/agent/secure/header.go @@ -20,13 +20,12 @@ import ( "fmt" "time" - "github.com/oceanbase/obshell/agent/lib/json" - log "github.com/sirupsen/logrus" "github.com/oceanbase/obshell/agent/constant" "github.com/oceanbase/obshell/agent/errors" "github.com/oceanbase/obshell/agent/lib/crypto" + "github.com/oceanbase/obshell/agent/lib/json" "github.com/oceanbase/obshell/agent/meta" ) @@ -42,16 +41,32 @@ type HttpHeader struct { Token string Uri string Keys []byte + Sha256 string ForwardType int ForwardAgent meta.AgentInfo } +func BuildAgentHeader(agentInfo meta.AgentInfoInterface, password string, uri string, isForword bool, keys ...[]byte) map[string]string { + auth := buildHeader(agentInfo, password, uri, isForword, keys...) + header := map[string]string{ + constant.OCS_AGENT_HEADER: auth, + } + return header +} + func BuildHeader(agentInfo meta.AgentInfoInterface, uri string, isForword bool, keys ...[]byte) map[string]string { - headers := make(map[string]string) + auth := buildHeader(agentInfo, meta.OCEANBASE_PWD, uri, isForword, keys...) + header := map[string]string{ + constant.OCS_HEADER: auth, + } + return header +} + +func buildHeader(agentInfo meta.AgentInfoInterface, password string, uri string, isForword bool, keys ...[]byte) string { pk := GetAgentPublicKey(agentInfo) if pk == "" { - log.Warnf("no key for agent '%s:%d'", agentInfo.GetIp(), agentInfo.GetPort()) - return nil + log.Warnf("no key for agent '%s'", agentInfo.String()) + return "" } var token string @@ -68,7 +83,7 @@ func BuildHeader(agentInfo meta.AgentInfoInterface, uri string, isForword bool, aesKeys = append(keys[0], keys[1]...) } header := HttpHeader{ - Auth: meta.OCEANBASE_PWD, + Auth: password, Ts: fmt.Sprintf("%d", time.Now().Add(getAuthExpiredDuration()).Unix()), Token: token, Uri: uri, @@ -83,15 +98,14 @@ func BuildHeader(agentInfo meta.AgentInfoInterface, uri string, isForword bool, mAuth, err := json.Marshal(header) if err != nil { log.WithError(err).Error("json marshal failed") - return nil + return "" } auth, err := crypto.RSAEncrypt(mAuth, pk) if err != nil { log.WithError(err).Error("rsa encrypt failed") - return nil + return "" } - headers[constant.OCS_HEADER] = auth - return headers + return auth } func DecryptHeader(ciphertext string) (HttpHeader, error) { diff --git a/agent/secure/http.go b/agent/secure/http.go index e66ee999..56230b52 100644 --- a/agent/secure/http.go +++ b/agent/secure/http.go @@ -19,6 +19,7 @@ package secure import ( "github.com/go-resty/resty/v2" + "github.com/oceanbase/obshell/agent/config" "github.com/oceanbase/obshell/agent/errors" "github.com/oceanbase/obshell/agent/lib/http" "github.com/oceanbase/obshell/agent/meta" @@ -130,6 +131,10 @@ func BuildBodyAndHeader(agentInfo meta.AgentInfoInterface, uri string, param int } func BuildBody(agentInfo meta.AgentInfoInterface, param interface{}) (encryptedBody interface{}, Key, Iv []byte, err error) { + if config.IsEncryptionDisabled() { + encryptedBody = param + return + } encryptedBody, Key, Iv, err = nil, nil, nil, nil if encryptMethod == "rsa" { encryptedBody, err = EncryptBodyWithRsa(agentInfo, param) @@ -144,3 +149,12 @@ func BuildBody(agentInfo meta.AgentInfoInterface, param interface{}) (encryptedB func BuildHeaderForForward(agentInfo meta.AgentInfoInterface, uri string, keys ...[]byte) map[string]string { return BuildHeader(agentInfo, uri, true, keys...) } + +func SendRequestWithPassword(agentInfo meta.AgentInfoInterface, uri string, method string, agentPassword string, param interface{}, ret interface{}) error { + encryptedBody, Key, Iv, err := BuildBody(agentInfo, param) + if err != nil { + return errors.Wrap(err, "build body failed") + } + header := BuildAgentHeader(agentInfo, agentPassword, uri, false, Key, Iv) + return http.SendRequestAndBuildReturn(agentInfo, uri, method, encryptedBody, ret, header) +} diff --git a/agent/secure/service.go b/agent/secure/service.go index d19f6e41..e8c66d69 100644 --- a/agent/secure/service.go +++ b/agent/secure/service.go @@ -74,6 +74,22 @@ func updateOBConifg(key string, value interface{}) (err error) { return updateOBConifgInTransaction(db, key, value) } +func updateObproxyConfig(key string, value interface{}) (err error) { + db, err := sqlitedb.GetSqliteInstance() + if err != nil { + return + } + data := map[string]interface{}{ + "name": key, + "value": value, + } + err = db.Model(obConfigModel).Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "name"}}, + DoUpdates: clause.AssignmentColumns([]string{"value"}), + }).Create(data).Error + return +} + func updateOBConifgInTransaction(tx *gorm.DB, key string, value interface{}) (err error) { data := map[string]interface{}{ "name": key, diff --git a/agent/secure/token.go b/agent/secure/token.go index b4c8202f..32e2cf6b 100644 --- a/agent/secure/token.go +++ b/agent/secure/token.go @@ -26,7 +26,13 @@ import ( // NewToken generates a token for the agent to join/scale-out an existing cluster func NewToken(targetAgent meta.AgentInfoInterface) (string, error) { - token := uuid.New().String() + token, err := getTokenByAgentInfo(meta.OCS_AGENT) + if err != nil { + return "", err + } + if token == "" { + token = uuid.New().String() + } if err := updateToken(meta.OCS_AGENT, token); err != nil { return "", err } @@ -42,7 +48,7 @@ func VerifyToken(token string) error { if err != nil { return err } - if agentToken != token { + if agentToken != token || token == "" { return errors.New("wrong token") } return nil diff --git a/agent/service/agent/all_agents.go b/agent/service/agent/all_agents.go index 02d3f9e6..8f3b9aa8 100644 --- a/agent/service/agent/all_agents.go +++ b/agent/service/agent/all_agents.go @@ -215,6 +215,25 @@ func (s *AgentService) addAgentToken(tx *gorm.DB, agentInfo meta.AgentInfoInterf }).Create(&ocsToken).Error } +func (s *AgentService) AddSingleToken(agentInfo meta.AgentInfoInterface, token string) error { + if token == "" { + return nil + } + db, err := sqlitedb.GetSqliteInstance() + if err != nil { + return err + } + ocsToken := sqlite.OcsToken{ + Ip: agentInfo.GetIp(), + Port: agentInfo.GetPort(), + Token: token, + } + return db.Model(&sqlite.OcsToken{}).Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "ip"}, {Name: "port"}}, + DoUpdates: clause.AssignmentColumns([]string{"token"}), + }).Create(&ocsToken).Error +} + func (s *AgentService) addAgent(db *gorm.DB, agentInstance meta.Agent, homePath string, os string, arch string, publicKey string) error { agent := &sqlite.AllAgent{ Ip: agentInstance.GetIp(), @@ -230,20 +249,6 @@ func (s *AgentService) addAgent(db *gorm.DB, agentInstance meta.Agent, homePath return db.Create(agent).Error } -func (s *AgentService) UpdateAgent(agentInstance meta.Agent, homePath string, os string, arch string, publicKey string, token string) error { - db, err := sqlitedb.GetSqliteInstance() - if err != nil { - return err - } - return db.Transaction(func(tx *gorm.DB) error { - err = s.addAgentToken(tx, agentInstance, token) - if err == nil { - err = s.updateAgent(tx, agentInstance, homePath, os, arch, publicKey) - } - return err - }) -} - func (s *AgentService) UpdateAgentOBPort(agent meta.AgentInfoInterface, mysqlPort, rpcPort int) error { db, err := sqlitedb.GetSqliteInstance() if err != nil { @@ -394,7 +399,7 @@ func (s *AgentService) CheckCanBeTakeOverMaster() (bool, error) { } if !self_exist { - return false, fmt.Errorf("%s:%d not in cluster", meta.OCS_AGENT.GetIp(), meta.RPC_PORT) + return false, fmt.Errorf("%s not in cluster", meta.NewAgentInfo(meta.OCS_AGENT.GetIp(), meta.RPC_PORT).String()) } return other_exist, nil diff --git a/agent/service/agent/binary.go b/agent/service/agent/binary.go index 02c8339d..dd83cd9e 100644 --- a/agent/service/agent/binary.go +++ b/agent/service/agent/binary.go @@ -85,6 +85,9 @@ func (s *AgentService) UpgradeBinary() error { if err := tx.Exec("SET SESSION ob_query_timeout=1000000000").Error; err != nil { return err } + if err := tx.Exec("SET SESSION ob_trx_timeout=1000000000").Error; err != nil { + return err + } info := &oceanbase.AgentBinaryInfo{ Version: constant.VERSION, diff --git a/agent/service/agent/config.go b/agent/service/agent/config.go index 4cd2982b..300cd9ac 100644 --- a/agent/service/agent/config.go +++ b/agent/service/agent/config.go @@ -26,6 +26,7 @@ import ( "github.com/oceanbase/obshell/agent/meta" sqlitedb "github.com/oceanbase/obshell/agent/repository/db/sqlite" "github.com/oceanbase/obshell/agent/repository/model/sqlite" + "github.com/oceanbase/obshell/agent/secure" ) func (s *AgentService) UpdatePort(mysqlPort, rpcPort int) error { @@ -105,3 +106,26 @@ func (s *AgentService) getOBConifg(db *gorm.DB, name string, value interface{}) } return err } + +func (s *AgentService) SetAgentPassword(password string) error { + sqliteDb, err := sqlitedb.GetSqliteInstance() + if err != nil { + return err + } + encrptyPassword, err := secure.Encrypt(password) + if err != nil { + return err + } + + if err := sqliteDb.Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "name"}}, + DoUpdates: clause.AssignmentColumns([]string{"value"}), + }).Create(&sqlite.OcsInfo{ + Name: constant.CONFIG_AGENT_PASSWORD, + Value: encrptyPassword}).Error; err != nil { + return err + } + + meta.AGENT_PWD.SetPassword(password) + return nil +} diff --git a/agent/service/agent/enter.go b/agent/service/agent/enter.go index e314e671..1fe5dc84 100644 --- a/agent/service/agent/enter.go +++ b/agent/service/agent/enter.go @@ -28,6 +28,7 @@ import ( "github.com/oceanbase/obshell/agent/meta" sqlitedb "github.com/oceanbase/obshell/agent/repository/db/sqlite" "github.com/oceanbase/obshell/agent/repository/model/sqlite" + "github.com/oceanbase/obshell/agent/secure" ) var ( @@ -75,10 +76,50 @@ func (s *AgentService) InitAgent() error { } default: } + + if err := s.initObproxy(); err != nil { + return err + } + meta.OCS_AGENT = ocsAgent return nil } +// initObproxy will initialize obproxy info of the agent. +func (s *AgentService) initObproxy() (err error) { + db, err := sqlitedb.GetSqliteInstance() + if err != nil { + return + } + + if err = db.Model(&sqlite.ObproxyInfo{}). + Select("value"). + Where("name = ?", constant.OBPROXY_INFO_HOME_PATH). + Scan(&meta.OBPROXY_HOME_PATH).Error; err != nil { + return + } + + if err = db.Model(&sqlite.ObproxyInfo{}). + Select("value"). + Where("name = ?", constant.OBPROXY_INFO_SQL_PORT). + Scan(&meta.OBPROXY_SQL_PORT).Error; err != nil { + return + } + + encryptedSysPwd := "" + if err = db.Model(&sqlite.ObproxyInfo{}). + Select("value"). + Where("name = ?", constant.OBPROXY_CONFIG_OBPROXY_SYS_PASSWORD). + Scan(&encryptedSysPwd).Error; err != nil { + return err + } + if meta.OBPROXY_SYS_PWD, err = secure.Decrypt(encryptedSysPwd); err != nil { + return err + } + + return nil +} + func (s *AgentService) initOBPort() error { sqliteDb, err := sqlitedb.GetSqliteInstance() if err != nil { @@ -106,11 +147,17 @@ func (agentService *AgentService) InitializeAgentStatus() (err error) { } if err = db.Create(&sqlite.OcsInfo{Name: constant.OCS_INFO_STATUS, Value: strconv.Itoa(task.NOT_UNDER_MAINTENANCE)}).Error; err != nil { sqliteErr, ok := err.(sqlite3.Error) - if ok && sqliteErr.Code == sqlite3.ErrConstraint { - return nil + if !ok || sqliteErr.Code != sqlite3.ErrConstraint { + return } } - return + if err = db.Create(&sqlite.ObproxyInfo{Name: constant.OCS_INFO_STATUS, Value: strconv.Itoa(task.NOT_UNDER_MAINTENANCE)}).Error; err != nil { + sqliteErr, ok := err.(sqlite3.Error) + if !ok || sqliteErr.Code != sqlite3.ErrConstraint { + return + } + } + return nil } func (s *AgentService) getAgentInfo() (agentInfo meta.AgentInstance, err error) { diff --git a/agent/service/agent/info.go b/agent/service/agent/info.go index b9292093..b046f7ef 100644 --- a/agent/service/agent/info.go +++ b/agent/service/agent/info.go @@ -277,6 +277,7 @@ func (s *AgentService) BeSingleAgent() error { return err } ocsAgent.MasterAgent = nil + meta.ClearOceanbasePwd() return nil }) } diff --git a/agent/service/agent/obproxy.go b/agent/service/agent/obproxy.go new file mode 100644 index 00000000..808e9b0a --- /dev/null +++ b/agent/service/agent/obproxy.go @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package agent + +import ( + "os" + "strconv" + + "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/meta" + sqlitedb "github.com/oceanbase/obshell/agent/repository/db/sqlite" + "github.com/oceanbase/obshell/agent/repository/model/sqlite" + "gorm.io/gorm" + "gorm.io/gorm/clause" +) + +func (*AgentService) DeleteObproxy() error { + db, err := sqlitedb.GetSqliteInstance() + if err != nil { + return err + } + return db.Transaction(func(tx *gorm.DB) error { + if err := tx.Exec("DELETE FROM obproxy_info").Error; err != nil { + return err + } + meta.OBPROXY_HOME_PATH = "" + meta.OBPROXY_SQL_PORT = 0 + return nil + }) +} + +func (*AgentService) AddObproxy(homePath string, sqlPort int, enObproxySysPwd, enObproxyProxyroPwd string) error { + db, err := sqlitedb.GetSqliteInstance() + if err != nil { + return err + } + infos := make(map[string]string) + infos[constant.OBPROXY_INFO_OBPROXY_SYS_PASSWORD] = enObproxySysPwd + infos[constant.OBPROXY_INFO_PROXYRO_PASSWORD] = enObproxyProxyroPwd + infos[constant.OBPROXY_INFO_HOME_PATH] = homePath + infos[constant.OBPROXY_INFO_SQL_PORT] = strconv.Itoa(sqlPort) + + return db.Transaction(func(tx *gorm.DB) error { + for k, v := range infos { + // create or update + if err := tx.Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "name"}}, + DoUpdates: clause.AssignmentColumns([]string{"value"}), + }).Create(&sqlite.ObproxyInfo{ + Name: k, + Value: v, + }).Error; err != nil { + return err + } + } + meta.OBPROXY_HOME_PATH = homePath + return nil + }) +} + +func (*AgentService) GetUpgradePkgInfoByVersion(name, version, arch, distribution string, deprecatedInfo []string) (pkgInfo sqlite.UpgradePkgInfo, err error) { + db, err := sqlitedb.GetSqliteInstance() + if err != nil { + return + } + if len(deprecatedInfo) == 0 { + err = db.Model(&sqlite.UpgradePkgInfo{}).Where("name = ? and version = ? and distribution = ? and architecture = ? ", name, version, arch, distribution).Last(&pkgInfo).Error + } else { + err = db.Model(&sqlite.UpgradePkgInfo{}).Where("name = ? and version = ? and distribution = ? and architecture = ? and `release` not in ?", name, version, distribution, arch, deprecatedInfo).Last(&pkgInfo).Error + } + return +} + +func (*AgentService) GetUpgradePkgInfoByVersionAndRelease(name, version, release, distribution, arch string) (pkgInfo sqlite.UpgradePkgInfo, err error) { + db, err := sqlitedb.GetSqliteInstance() + if err != nil { + return + } + err = db.Model(&sqlite.UpgradePkgInfo{}).Where("name = ? and version = ? and distribution = ? and architecture = ? and `release` = ?", name, version, distribution, arch, release).Last(&pkgInfo).Error + return +} + +func (agentService *AgentService) DownloadUpgradePkgChunkInBatch(filepath string, pkgId, chunkCount int) error { + file, err := os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0755) + if err != nil { + return err + } + defer file.Close() + + for i := 0; i < chunkCount; i++ { + chunk, err := agentService.GetUpgradePkgChunkByPkgIdAndChunkId(pkgId, i) + if err != nil { + return err + } + _, err = file.Write(chunk.Chunk) + if err != nil { + return err + } + } + return nil +} + +func (agentService *AgentService) GetUpgradePkgChunkByPkgIdAndChunkId(pkgId, chunkId int) (chunk sqlite.UpgradePkgChunk, err error) { + db, err := sqlitedb.GetSqliteInstance() + if err != nil { + return chunk, err + } + err = db.Model(&sqlite.UpgradePkgChunk{}).Where("pkg_id = ? and chunk_id = ?", pkgId, chunkId).First(&chunk).Error + return +} + +func (agentService *AgentService) GetUpgradePkgChunkCountByPkgId(pkgId int) (count int64, err error) { + db, err := sqlitedb.GetSqliteInstance() + if err != nil { + return 0, err + } + err = db.Model(&sqlite.UpgradePkgChunk{}).Where("pkg_id = ?", pkgId).Count(&count).Error + return +} diff --git a/agent/service/obcluster/config.go b/agent/service/obcluster/config.go index ad30fb82..18e72222 100644 --- a/agent/service/obcluster/config.go +++ b/agent/service/obcluster/config.go @@ -43,6 +43,15 @@ func (s *ObserverService) GetObConfigByName(name string) (config sqlite.ObConfig return } +func (s *ObserverService) GetObConfigValueByName(name string, val interface{}) (err error) { + db, err := sqlitedb.GetSqliteInstance() + if err != nil { + return + } + err = db.Model(&sqlite.ObConfig{}).Select("value").Where("name = ?", name).Scan(val).Error + return +} + func (s *ObserverService) GetOBParatemerByName(name string, value interface{}) (err error) { db, err := oceanbase.GetInstance() if err != nil { diff --git a/agent/service/obcluster/enter.go b/agent/service/obcluster/enter.go index ca81a92e..3b8882c8 100644 --- a/agent/service/obcluster/enter.go +++ b/agent/service/obcluster/enter.go @@ -22,10 +22,12 @@ type ObclusterService struct{} const ( ob_parameters_view = "oceanbase.V$OB_PARAMETERS" - COLLATIONS = "information_schema.collations" - DBA_OB_SERVERS = "oceanbase.DBA_OB_SERVERS" - DBA_OB_ZONES = "oceanbase.DBA_OB_ZONES" - DBA_OB_UNITS = "oceanbase.DBA_OB_UNITS" - GV_OB_LOG_STAT = "oceanbase.GV$OB_LOG_STAT" - GV_OB_PARAMETERS = "oceanbase.GV$OB_PARAMETERS" + COLLATIONS = "information_schema.collations" + DBA_OB_SERVERS = "oceanbase.DBA_OB_SERVERS" + DBA_OB_ZONES = "oceanbase.DBA_OB_ZONES" + DBA_OB_UNITS = "oceanbase.DBA_OB_UNITS" + GV_OB_LOG_STAT = "oceanbase.GV$OB_LOG_STAT" + GV_OB_PARAMETERS = "oceanbase.GV$OB_PARAMETERS" + GV_OB_SERVERS = "oceanbase.GV$OB_SERVERS" + CDB_OB_LS_LOCATIONS = "oceanbase.CDB_OB_LS_LOCATIONS" ) diff --git a/agent/service/obcluster/obcluster.go b/agent/service/obcluster/obcluster.go index 38e412ee..71ad4ee1 100644 --- a/agent/service/obcluster/obcluster.go +++ b/agent/service/obcluster/obcluster.go @@ -34,6 +34,7 @@ import ( sqlitedb "github.com/oceanbase/obshell/agent/repository/db/sqlite" "github.com/oceanbase/obshell/agent/repository/model/oceanbase" "github.com/oceanbase/obshell/agent/repository/model/sqlite" + "github.com/oceanbase/obshell/param" ) func (obclusterService *ObclusterService) ExecuteSql(sql string) (err error) { @@ -100,6 +101,15 @@ func (obclusterService *ObclusterService) GetUTCTime() (t time.Time, err error) return } +func (*ObclusterService) GetCurrentTimestamp() (t time.Time, err error) { + db, err := oceanbasedb.GetInstance() + if err != nil { + return t, err + } + err = db.Raw("SELECT CURRENT_TIMESTAMP(6)").Scan(&t).Error + return +} + func (ObclusterService *ObclusterService) GetServerCheckpointScn(servers []oceanbase.OBServer) (map[oceanbase.OBServer]uint64, error) { db, err := oceanbasedb.GetInstance() if err != nil { @@ -125,10 +135,10 @@ func (obclusterService *ObclusterService) MinorFreeze(servers []oceanbase.OBServ } var targetCmd []string for _, server := range servers { - targetCmd = append(targetCmd, fmt.Sprintf("'%s:%d'", server.SvrIp, server.SvrPort)) + targetCmd = append(targetCmd, meta.NewAgentInfo(server.SvrIp, server.SvrPort).String()) } - serverList := strings.Join(targetCmd, ",") - sql := fmt.Sprintf("alter system minor freeze server = (%[1]s);", serverList) + serverList := strings.Join(targetCmd, "','") + sql := fmt.Sprintf("alter system minor freeze server = ('%[1]s');", serverList) return db.Exec(sql).Error } @@ -212,6 +222,15 @@ func (ObclusterService *ObclusterService) GetAllArchs() (archs []string, err err return } +func (ObclusterService *ObclusterService) GetAllUpgradePkgInfos() (pkgInfos []oceanbase.UpgradePkgInfo, err error) { + oceanbaseDb, err := oceanbasedb.GetOcsInstance() + if err != nil { + return nil, err + } + err = oceanbaseDb.Model(&oceanbase.UpgradePkgInfo{}).Find(&pkgInfos).Error + return +} + func (obclusterService *ObclusterService) GetUpgradePkgInfoByVersion(name, version, arch, distribution string, deprecatedInfo []string) (pkgInfo oceanbase.UpgradePkgInfo, err error) { oceanbaseDb, err := oceanbasedb.GetOcsInstance() if err != nil { @@ -234,21 +253,21 @@ func (obclusterService *ObclusterService) GetUpgradePkgInfoByVersionAndRelease(n return } -func (obclusterService *ObclusterService) AddServer(ip, port, zoneName string) (err error) { +func (obclusterService *ObclusterService) AddServer(svrInfo meta.ObserverSvrInfo, zoneName string) (err error) { db, err := oceanbasedb.GetInstance() if err != nil { return err } - alterSql := fmt.Sprintf("ALTER SYSTEM ADD SERVER '%s:%s' ZONE '%s'", ip, port, zoneName) + alterSql := fmt.Sprintf("ALTER SYSTEM ADD SERVER '%s' ZONE '%s'", svrInfo.String(), zoneName) return db.Exec(alterSql).Error } -func (obclusterService *ObclusterService) DeleteServerInZone(ip, port, zoneName string) (err error) { +func (obclusterService *ObclusterService) DeleteServerInZone(svrInfo meta.ObserverSvrInfo, zoneName string) (err error) { db, err := oceanbasedb.GetInstance() if err != nil { return err } - alterSql := fmt.Sprintf("ALTER SYSTEM DELETE SERVER '%s:%s' ZONE '%s'", ip, port, zoneName) + alterSql := fmt.Sprintf("ALTER SYSTEM DELETE SERVER '%s' ZONE '%s'", svrInfo.String(), zoneName) return db.Exec(alterSql).Error } @@ -257,7 +276,7 @@ func (obclusterService *ObclusterService) DeleteServer(svrInfo meta.ObserverSvrI if err != nil { return err } - alterSql := fmt.Sprintf("ALTER SYSTEM DELETE SERVER '%s:%d'", svrInfo.GetIp(), svrInfo.GetPort()) + alterSql := fmt.Sprintf("ALTER SYSTEM DELETE SERVER '%s'", svrInfo.String()) return db.Exec(alterSql).Error } @@ -266,30 +285,30 @@ func (ObclusterService *ObclusterService) CancelDeleteServer(svrInfo meta.Observ if err != nil { return err } - alterSql := fmt.Sprintf("ALTER SYSTEM CANCEL DELETE SERVER '%s:%d'", svrInfo.GetIp(), svrInfo.GetPort()) + alterSql := fmt.Sprintf("ALTER SYSTEM CANCEL DELETE SERVER '%s'", svrInfo.String()) return db.Exec(alterSql).Error } -func (obclusterService *ObclusterService) IsServerExist(ip string, port string) (bool, error) { +func (obclusterService *ObclusterService) IsServerExist(svrInfo meta.ObserverSvrInfo) (bool, error) { db, err := oceanbasedb.GetInstance() if err != nil { return false, err } var count int - err = db.Raw("select count(*) from oceanbase.dba_ob_servers where svr_ip = ? and svr_port = ?", ip, port).First(&count).Error + err = db.Raw("select count(*) from oceanbase.dba_ob_servers where svr_ip = ? and svr_port = ?", svrInfo.GetIp(), svrInfo.GetPort()).First(&count).Error if err != nil { return false, err } return count > 0, nil } -func (obclusterService *ObclusterService) IsServerExistWithZone(ip string, port string, zone string) (bool, error) { +func (obclusterService *ObclusterService) IsServerExistWithZone(svrInfo meta.ObserverSvrInfo, zone string) (bool, error) { db, err := oceanbasedb.GetInstance() if err != nil { return false, err } var count int64 - err = db.Table(DBA_OB_SERVERS).Where("svr_ip = ? and svr_port = ? and zone = ?", ip, port, zone).Count(&count).Error + err = db.Table(DBA_OB_SERVERS).Where("svr_ip = ? and svr_port = ? and zone = ?", svrInfo.GetIp(), svrInfo.GetPort(), zone).Count(&count).Error if err != nil { return false, err } @@ -643,7 +662,7 @@ func (obclusterService *ObclusterService) RestoreParamsForUpgrade(params []ocean } sql = fmt.Sprintf("ALTER SYSTEM SET %s = '%s' TENANT = %s", param.Name, param.Value, tenantName) case "CLUSTER": - sql = fmt.Sprintf("ALTER SYSTEM SET %s = '%s' SERVER = '%s:%d'", param.Name, param.Value, param.SvrIp, param.SvrPort) + sql = fmt.Sprintf("ALTER SYSTEM SET %s = '%s' SERVER = '%s'", param.Name, param.Value, meta.NewAgentInfo(param.SvrIp, param.SvrPort).String()) default: return errors.New("unknown scope") } @@ -669,6 +688,44 @@ func (obclusterService *ObclusterService) GetObParametersForUpgrade(params []str return } +func (*ObclusterService) GetAllUnhiddenParameters() ([]oceanbase.ObParameters, error) { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return nil, err + } + + var unhiddenParams []oceanbase.ObParameters + err = oceanbaseDb.Table(GV_OB_PARAMETERS).Where("NAME NOT LIKE ?", `\_%`).Find(&unhiddenParams).Error + + return unhiddenParams, err +} + +func (obclusterService *ObclusterService) GetParameterByName(name string) (param *oceanbase.ObParameters, err error) { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return + } + err = oceanbaseDb.Table(GV_OB_PARAMETERS).Where("NAME = ?", name).Scan(¶m).Error + return +} + +func (obclusterService *ObclusterService) SetParameter(parameter param.SetParameterParam) error { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return err + } + + sql := fmt.Sprintf("ALTER SYSTEM SET `%s` = \"%v\"", parameter.Name, parameter.Value) + if parameter.Zone != "" { + sql += fmt.Sprintf(" ZONE = `%s`", parameter.Zone) + } else if parameter.Server != "" { + sql += fmt.Sprintf(" SERVER = '%s'", parameter.Server) + } else if parameter.Tenant != "" { + sql += fmt.Sprintf(" TENANT = `%s`", parameter.Tenant) // when tenant is not empty, zone and server won't influence the sql. + } + return oceanbaseDb.Exec(sql).Error +} + func (ObclusterService *ObclusterService) GetAllZonesWithRegion() (zones []oceanbase.DbaObZones, err error) { oceanbaseDb, err := oceanbasedb.GetInstance() if err != nil { @@ -687,13 +744,13 @@ func (obclusterService *ObclusterService) GetServerByZone(name string) (servers return } -func (obclusterService *ObclusterService) GetCharsetAndCollation(charset string, collation string) (*oceanbase.Collations, error) { +func (obclusterService *ObclusterService) GetCharsetAndCollation(charset string, collation string) (*oceanbase.ObCollation, error) { oceanbaseDb, err := oceanbasedb.GetInstance() if err != nil { return nil, err } - var charsetInfo *oceanbase.Collations + var charsetInfo *oceanbase.ObCollation if collation == "" { err = oceanbaseDb.Table(COLLATIONS).Select("CHARACTER_SET_NAME, COLLATION_NAME").Where("CHARACTER_SET_NAME = ?", charset).Scan(&charsetInfo).Error return charsetInfo, err @@ -706,6 +763,41 @@ func (obclusterService *ObclusterService) GetCharsetAndCollation(charset string, } } +func (*ObclusterService) GetAllCharsets() (charsets []oceanbase.ObCharset, err error) { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return nil, err + } + err = oceanbaseDb.Raw("SHOW CHARACTER SET").Scan(&charsets).Error + return +} + +func (*ObclusterService) GetAllCollations() (collations []oceanbase.ObCollation, err error) { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return nil, err + } + err = oceanbaseDb.Table(COLLATIONS).Scan(&collations).Error + return +} + +func (*ObclusterService) GetCollationMap() (collationMap map[int]oceanbase.ObCollation, err error) { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return nil, err + } + var collations []oceanbase.ObCollation + err = oceanbaseDb.Table(COLLATIONS).Scan(&collations).Error + if err != nil { + return nil, err + } + collationMap = make(map[int]oceanbase.ObCollation) + for _, collation := range collations { + collationMap[collation.Id] = collation + } + return +} + func (ObclusterService *ObclusterService) GetObUnitsOnServer(svrIp string, svrPort int) (units []oceanbase.DbaObUnit, err error) { oceanbaseDb, err := oceanbasedb.GetInstance() if err != nil { @@ -737,7 +829,7 @@ func (ObclusterService *ObclusterService) IsLsMultiPaxosAlive(lsId int, tenantId // GetLogInfosInServer returns the log stat in target server // only contains tenant_id and ls_id. -func (ObclusterService *ObclusterService) GetLogInfosInServer(svrInfo meta.ObserverSvrInfo) (logStats []oceanbase.ObLogStat, err error) { +func (*ObclusterService) GetLogInfosInServer(svrInfo meta.ObserverSvrInfo) (logStats []oceanbase.ObLogStat, err error) { oceanbaseDb, err := oceanbasedb.GetInstance() if err != nil { return nil, err @@ -746,7 +838,7 @@ func (ObclusterService *ObclusterService) GetLogInfosInServer(svrInfo meta.Obser return } -func (ObclusterService *ObclusterService) HasUnitInZone(zone string) (exist bool, err error) { +func (*ObclusterService) HasUnitInZone(zone string) (exist bool, err error) { oceanbaseDb, err := oceanbasedb.GetInstance() if err != nil { return false, err @@ -755,3 +847,119 @@ func (ObclusterService *ObclusterService) HasUnitInZone(zone string) (exist bool err = oceanbaseDb.Table(DBA_OB_UNITS).Where("ZONE = ?", zone).Count(&count).Error return count > 0, err } + +func (obclusterService *ObclusterService) CreateProxyroUser(password string) error { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return err + } + + sqlText := fmt.Sprintf("CREATE USER IF NOT EXISTS `%s`@`%s`", constant.SYS_USER_PROXYRO, "%") + if password != "" { + sqlText += fmt.Sprintf(" IDENTIFIED BY '%s'", strings.ReplaceAll(password, "'", "'\"'\"'")) + } + if err = oceanbaseDb.Exec(sqlText).Error; err != nil { + return err + } + if err := oceanbaseDb.Exec(fmt.Sprintf("GRANT SELECT ON oceanbase.* TO %s", constant.SYS_USER_PROXYRO)).Error; err != nil { + return err + } + return nil +} + +func (obclusterService *ObclusterService) GetRsListStr() (rsListStr string, err error) { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return "", err + } + err = oceanbaseDb.Table(GV_OB_PARAMETERS). + Select("VALUE"). + Where("NAME = ?", "rootservice_list"). + Scan(&rsListStr).Error + return +} + +func (obclusterService *ObclusterService) IsCommunityEdition() (bool, error) { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return false, err + } + var count int64 + err = oceanbaseDb.Raw("select version() REGEXP 'OceanBase[\\s_]CE'").Scan(&count).Error + if err != nil { + return false, err + } + return count > 1, nil +} + +func (*ObclusterService) GetAllZoneRootServers() (rootServersMap map[string]oceanbase.RootServer, err error) { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return nil, err + } + var rootServers []oceanbase.RootServer + err = oceanbaseDb.Table(CDB_OB_LS_LOCATIONS).Select("SVR_IP, SVR_PORT, ZONE, ROLE").Where("LS_ID = 1 AND TENANT_ID = 1").Scan(&rootServers).Error + if err != nil { + return nil, err + } + rootServersMap = make(map[string]oceanbase.RootServer) + for _, server := range rootServers { + rootServersMap[server.Zone] = server + } + return +} + +func (ObclusterService) GetObserverCapacityByZone(zone string) (servers []oceanbase.ObServerCapacity, err error) { + db, err := oceanbasedb.GetInstance() + if err != nil { + return nil, err + } + err = db.Table(GV_OB_SERVERS).Where("ZONE = ?", zone).Scan(&servers).Error + return +} + +func (ObclusterService) GetAllObserverResourceMap() (observerResourceMap map[meta.ObserverSvrInfo]oceanbase.ObServerCapacity, err error) { + db, err := oceanbasedb.GetInstance() + if err != nil { + return nil, err + } + var serverResources []oceanbase.ObServerCapacity + err = db.Table(GV_OB_SERVERS).Scan(&serverResources).Error + if err != nil { + return nil, err + } + observerResourceMap = make(map[meta.ObserverSvrInfo]oceanbase.ObServerCapacity) + for _, serverResource := range serverResources { + observerResourceMap[meta.ObserverSvrInfo{ + Ip: serverResource.SvrIp, + Port: serverResource.SvrPort, + }] = serverResource + } + return +} + +func (*ObclusterService) GetTenantSysStat(tenantId int, StatId int) (sysStat oceanbase.SysStat, err error) { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return sysStat, err + } + err = oceanbaseDb.Model(oceanbase.SysStat{}).Where("CON_ID = ? AND STAT_ID = ?", tenantId, StatId).Scan(&sysStat).Error + return +} + +func (obclusterService *ObclusterService) GetTenantMutilSysStat(tenantId int, StatIds []int) (sysStatMap map[int64]oceanbase.SysStat, err error) { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return nil, err + } + var sysStats []oceanbase.SysStat + err = oceanbaseDb.Model(oceanbase.SysStat{}).Select("CON_ID, SVR_IP, SVR_PORT, NAME, CLASS, VALUE_TYPE, STAT_ID, sum(VALUE) AS VALUE").Where("CON_ID = ? AND STAT_ID IN ?", tenantId, StatIds).Group("STAT_ID").Scan(&sysStats).Error + if err != nil { + return nil, err + } + sysStatMap = make(map[int64]oceanbase.SysStat) + for _, sysStat := range sysStats { + sysStatMap[int64(sysStat.StatId)] = sysStat + } + return sysStatMap, nil +} diff --git a/agent/service/obproxy/enter.go b/agent/service/obproxy/enter.go new file mode 100644 index 00000000..14483e2c --- /dev/null +++ b/agent/service/obproxy/enter.go @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package obproxy + +type ObproxyService struct{} + +const ( + OBPROXY_PROXYRO_USERNAME = "proxyro" + + GV_OB_PARAMETERS = "oceanbase.GV$OB_PARAMETERS" +) diff --git a/agent/service/obproxy/obproxy.go b/agent/service/obproxy/obproxy.go new file mode 100644 index 00000000..7710c7eb --- /dev/null +++ b/agent/service/obproxy/obproxy.go @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package obproxy + +import ( + "encoding/hex" + "fmt" + "mime/multipart" + "regexp" + "strconv" + "strings" + + "github.com/cavaliergopher/rpm" + "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/meta" + obproxydb "github.com/oceanbase/obshell/agent/repository/db/obproxy" + sqlitedb "github.com/oceanbase/obshell/agent/repository/db/sqlite" + "github.com/oceanbase/obshell/agent/secure" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + + "github.com/oceanbase/obshell/agent/repository/model/bo" + "github.com/oceanbase/obshell/agent/repository/model/sqlite" +) + +func (obproxyService *ObproxyService) SetSysPassword(password string) (err error) { + return obproxyService.SetGlobalConfig(constant.OBPROXY_CONFIG_OBPROXY_SYS_PASSWORD, password) +} + +func (obproxyService *ObproxyService) SetProxyroPassword(password string) error { + return obproxyService.SetGlobalConfig(constant.OBPROXY_CONFIG_PROXYRO_PASSWORD, password) +} + +func (*ObproxyService) SetGlobalConfig(name string, value string) error { + db, err := obproxydb.GetObproxyInstance() + if err != nil { + return err + } + + if err := db.Exec(fmt.Sprintf("ALTER proxyconfig SET %s = %s ", name, value)).Error; err != nil { + return err + } + return nil +} + +func (*ObproxyService) GetObproxyVersion() (version string, err error) { + db, err := obproxydb.GetObproxyInstance() + if err != nil { + return + } + var proxyInfo bo.ObproxyInfo + if err = db.Raw("show proxyinfo binary").Scan(&proxyInfo).Error; err != nil { + return "", err + } + // parse obproxy version + re := regexp.MustCompile(`\d+\.\d+\.\d+\.\d+-\d+`) + version = re.FindString(proxyInfo.Info) + return version, err +} + +func (*ObproxyService) GetGlobalConfig(name string) (value string, err error) { + db, err := obproxydb.GetObproxyInstance() + if err != nil { + return + } + var proxyConfig bo.ProxyConfig + err = db.Raw(fmt.Sprintf("show proxyconfig like '%s'", name)).Scan(&proxyConfig).Error + return proxyConfig.Value, err +} + +func (obproxyService *ObproxyService) UpdateSqlPort(sqlPort int) (err error) { + if err := obproxyService.UpdateObproxyInfo(constant.OBPROXY_INFO_SQL_PORT, strconv.Itoa(sqlPort)); err != nil { + return err + } + meta.OBPROXY_SQL_PORT = sqlPort + return nil +} + +func (obproxyService *ObproxyService) UpdateObproxySysPassword(obproxySysPassword string) (err error) { + encryptPwd, err := secure.Encrypt(obproxySysPassword) + if err != nil { + return err + } + if err := obproxyService.UpdateObproxyInfo(constant.OBPROXY_INFO_OBPROXY_SYS_PASSWORD, encryptPwd); err != nil { + return err + } + meta.OBPROXY_SYS_PWD = obproxySysPassword + return nil +} + +func (obproxyService *ObproxyService) UpdateObproxyInfo(name string, value string) (err error) { + db, err := sqlitedb.GetSqliteInstance() + if err != nil { + return + } + obproxyInfo := &sqlite.ObproxyInfo{ + Name: name, + Value: value, + } + return db.Model(obproxyInfo).Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "name"}}, + DoUpdates: clause.AssignmentColumns([]string{"value"}), + }).Create(obproxyInfo).Error +} + +func (*ObproxyService) GetObclusterName(db *gorm.DB) (name string, err error) { + err = db.Table(GV_OB_PARAMETERS).Where("name = ?", "cluster").Select("value").Scan(&name).Error + return +} + +func (*ObproxyService) ClearObproxyInfo() (err error) { + db, err := sqlitedb.GetSqliteInstance() + if err != nil { + return + } + return db.Delete(&sqlite.ObproxyInfo{}).Error +} + +func (*ObproxyService) DumpUpgradePkgInfoAndChunkTx(rpmPkg *rpm.Package, file multipart.File) (pkgInfo *sqlite.UpgradePkgInfo, err error) { + payloadSize := uint64(rpmPkg.Signature.GetTag(1000).Int64()) + chunkCount := payloadSize / constant.CHUNK_SIZE + if payloadSize%constant.CHUNK_SIZE != 0 { + chunkCount++ + } + pkgInfo = &sqlite.UpgradePkgInfo{ + Name: rpmPkg.Name(), + Version: rpmPkg.Version(), + ReleaseDistribution: rpmPkg.Release(), + Distribution: strings.Split(rpmPkg.Release(), ".")[1], + Release: strings.Split(rpmPkg.Release(), ".")[0], + Architecture: rpmPkg.Architecture(), + Size: rpmPkg.Size(), + ChunkCount: int(chunkCount), + PayloadSize: payloadSize, + Md5: hex.EncodeToString(rpmPkg.Signature.Tags[1004].Bytes()), + } + + db, err := sqlitedb.GetSqliteInstance() + if err != nil { + return nil, err + } + err = db.Transaction(func(tx *gorm.DB) error { + if err := tx.Model(&sqlite.UpgradePkgInfo{}).Create(&pkgInfo).Error; err != nil { + return err + } + chunkBuffer := make([]byte, constant.CHUNK_SIZE) + _, err = file.Seek(0, 0) + if err != nil { + return errors.Wrap(err, "Seek failed") + } + for i := 0; i < pkgInfo.ChunkCount; i++ { + n, err := file.Read(chunkBuffer) + if err != nil { + return err + } + record := &sqlite.UpgradePkgChunk{ + PkgId: pkgInfo.PkgId, + ChunkId: i, + ChunkCount: pkgInfo.ChunkCount, + Chunk: chunkBuffer[:n]} + if err = tx.Model(&sqlite.UpgradePkgChunk{}).Create(record).Error; err != nil { + return err + } + } + return nil + }) + return +} diff --git a/agent/service/task/convert.go b/agent/service/task/convert.go index 957b6799..23c26bed 100644 --- a/agent/service/task/convert.go +++ b/agent/service/task/convert.go @@ -71,7 +71,7 @@ func (s *taskService) convertNodeInstance(bo *bo.NodeInstance) (*task.Node, erro return nil, err } - return task.NewNodeWithId(bo.Id, bo.Name, bo.Type, bo.State, bo.Operator, bo.StructName, ctx, s.isLocal, bo.StartTime, bo.EndTime), nil + return task.NewNodeWithId(bo.Id, bo.Name, int(bo.DagId), bo.Type, bo.State, bo.Operator, bo.StructName, ctx, s.isLocal, bo.StartTime, bo.EndTime), nil } // convertSubTaskInstance convert SubTaskInstance to task.ExecutableTask. @@ -196,6 +196,22 @@ func (s *taskService) convertSubTaskInstanceBOSlice(model interface{}) []*bo.Sub return subTaskInstancesBO } +func (s *taskService) convertSubTaskLogBOSlice(model interface{}) []*bo.SubTaskLog { + subTaskLogsBO := make([]*bo.SubTaskLog, 0) + if s.isLocal { + subTaskLogs := model.(*[]sqlite.SubTaskLog) + for _, subTaskLog := range *subTaskLogs { + subTaskLogsBO = append(subTaskLogsBO, subTaskLog.ToBO()) + } + } else { + subTaskLogs := model.(*[]oceanbase.SubTaskLog) + for _, subTaskLog := range *subTaskLogs { + subTaskLogsBO = append(subTaskLogsBO, subTaskLog.ToBO()) + } + } + return subTaskLogsBO +} + func (s *taskService) getDagModel() interface{} { if s.isLocal { return &sqlite.DagInstance{} @@ -245,6 +261,13 @@ func (s *taskService) getSubTaskModelSlice() interface{} { return &[]oceanbase.SubtaskInstance{} } +func (s *taskService) getSubTaskLogModelSlice() interface{} { + if s.isLocal { + return &[]sqlite.SubTaskLog{} + } + return &[]oceanbase.SubTaskLog{} +} + func (s *taskService) getDbInstance() (*gorm.DB, error) { if s.isLocal { return sqlitedb.GetSqliteInstance() diff --git a/agent/service/task/dag.go b/agent/service/task/dag.go index db1eeb04..b025e54c 100644 --- a/agent/service/task/dag.go +++ b/agent/service/task/dag.go @@ -41,6 +41,27 @@ func (s *taskService) GetDagInstance(dagId int64) (*task.Dag, error) { return s.convertDagInstance(s.convertDagInstanceBO(dest)) } +func (s *taskService) GetAllDagInstances() ([]*task.Dag, error) { + db, err := s.getDbInstance() + if err != nil { + return nil, err + } + dest := s.getDagModelSlice() + if err = db.Model(s.getDagModel()).Find(dest).Error; err != nil { + return nil, err + } + dagInstancesBO := s.convertDagInstanceBOSlice(dest) + dags := make([]*task.Dag, 0, len(dagInstancesBO)) + for _, dagInstanceBO := range dagInstancesBO { + dag, err := s.convertDagInstance(dagInstanceBO) + if err != nil { + return nil, err + } + dags = append(dags, dag) + } + return dags, nil +} + func (s *taskService) GetDagDetail(dagId int64) (dagDetailDTO *task.DagDetailDTO, err error) { dag, err := s.GetDagInstance(dagId) if err != nil { @@ -56,7 +77,7 @@ func (s *taskService) GetDagDetail(dagId int64) (dagDetailDTO *task.DagDetailDTO return nil, err } - nodeDetailDTO, err := getNodeDetail(s, nodes[i]) + nodeDetailDTO, err := getNodeDetail(s, nodes[i], dag.GetDagType()) if err != nil { return nil, err } @@ -65,12 +86,12 @@ func (s *taskService) GetDagDetail(dagId int64) (dagDetailDTO *task.DagDetailDTO return dagDetailDTO, nil } -func getNodeDetail(service TaskServiceInterface, node *task.Node) (nodeDetailDTO *task.NodeDetailDTO, err error) { - nodeDetailDTO = task.NewNodeDetailDTO(node) +func getNodeDetail(service TaskServiceInterface, node *task.Node, dagType string) (nodeDetailDTO *task.NodeDetailDTO, err error) { + nodeDetailDTO = task.NewNodeDetailDTO(node, dagType) subTasks := node.GetSubTasks() n := len(subTasks) for i := 0; i < n; i++ { - taskDetailDTO, err := getSubTaskDetail(service, subTasks[i]) + taskDetailDTO, err := getSubTaskDetail(service, subTasks[i], dagType) if err != nil { return nil, err } @@ -79,8 +100,8 @@ func getNodeDetail(service TaskServiceInterface, node *task.Node) (nodeDetailDTO return } -func getSubTaskDetail(service TaskServiceInterface, subTask task.ExecutableTask) (taskDetailDTO *task.TaskDetailDTO, err error) { - taskDetailDTO = task.NewTaskDetailDTO(subTask) +func getSubTaskDetail(service TaskServiceInterface, subTask task.ExecutableTask, dagType string) (taskDetailDTO *task.TaskDetailDTO, err error) { + taskDetailDTO = task.NewTaskDetailDTO(subTask, dagType) if subTask.IsRunning() || subTask.IsFinished() { taskDetailDTO.TaskLogs, err = service.GetSubTaskLogsByTaskID(subTask.GetID()) } @@ -140,25 +161,29 @@ func (s *taskService) FindLastMaintenanceDag() (*task.Dag, error) { return dag, err } -func (s *taskService) GetDagIDBySubTaskId(taskID int64) (dagID int64, err error) { +// notice: GetDagBySubTaskId will occur error if the task is remote. +func (s *taskService) GetDagBySubTaskId(taskID int64) (*task.Dag, error) { db, err := s.getDbInstance() if err != nil { - return + return nil, err } var nodeID int64 if err = db.Model(s.getSubTaskModel()).Select("node_id").Where("id=?", taskID).First(&nodeID).Error; err != nil { - return + return nil, err } - err = db.Model(s.getNodeModel()).Select("dag_id").Where("id=?", nodeID).First(&dagID).Error - return + var dagID int64 + if err = db.Model(s.getNodeModel()).Select("dag_id").Where("id=?", nodeID).First(&dagID).Error; err != nil { + return nil, err + } + return s.GetDagInstance(dagID) } func (s *taskService) GetDagGenericIDBySubTaskId(taskID int64) (dagGenericID string, err error) { - var dagID int64 - if dagID, err = s.GetDagIDBySubTaskId(taskID); err != nil { + dag, err := s.GetDagBySubTaskId(taskID) + if err != nil { return } - dagGenericID = task.ConvertIDToGenericID(dagID, s.isLocal) + dagGenericID = task.ConvertIDToGenericID(dag.GetID(), s.isLocal, dag.GetDagType()) return } @@ -245,6 +270,7 @@ func (s *taskService) newDagInstanceBO(template *task.Template, ctx *task.TaskCo return &bo.DagInstance{ Name: template.Name, Stage: 1, + Type: template.Type, MaxStage: len(template.GetNodes()), State: task.READY, Operator: task.RUN, diff --git a/agent/service/task/interface.go b/agent/service/task/interface.go index b1570f32..9259df6a 100644 --- a/agent/service/task/interface.go +++ b/agent/service/task/interface.go @@ -23,6 +23,7 @@ import ( "github.com/oceanbase/obshell/agent/engine/task" "github.com/oceanbase/obshell/agent/meta" + "github.com/oceanbase/obshell/agent/repository/model/bo" "github.com/oceanbase/obshell/agent/repository/model/sqlite" ) @@ -102,6 +103,8 @@ type SubTaskServiceInterface interface { GetLocalTaskInstanceByRemoteTaskId(int64) (*sqlite.SubtaskInstance, error) + GetDagBySubTaskId(taskId int64) (*task.Dag, error) + GetSubTasks(*task.Node) ([]task.ExecutableTask, error) GetSubTaskByTaskID(int64) (task.ExecutableTask, error) @@ -134,4 +137,5 @@ type SubTaskServiceInterface interface { type SubTaskLogServiceInterface interface { GetSubTaskLogsByTaskID(int64) ([]string, error) + GetFullSubTaskLogsByTaskID(int64) ([]*bo.SubTaskLog, error) } diff --git a/agent/service/task/status_maintainer.go b/agent/service/task/status_maintainer.go index 9c4d3786..66d6d45c 100644 --- a/agent/service/task/status_maintainer.go +++ b/agent/service/task/status_maintainer.go @@ -55,7 +55,7 @@ func (maintainer *clusterStatusMaintainer) setStatus(tx *gorm.DB, newStatus int, return nil } } - return fmt.Errorf("failed to start maintenance: agent status is not %d", oldStatus) + return fmt.Errorf("failed to start maintenance: cluster is under maintenance") } return nil } @@ -85,7 +85,7 @@ func (maintainer *clusterStatusMaintainer) holdPartialLock(tx *gorm.DB, dag task if err1 := maintainer.getPartialLockForUpdate(tx, &paritialLock); err1 != nil { return err1 } else if paritialLock.GmtLocked.After(ZERO_TIME) { - return fmt.Errorf("failed to start maintenance: %s is already under maintenance", paritialLock.LockName) + return fmt.Errorf("failed to start maintenance: %s is under maintenance", paritialLock.LockName) } return nil } @@ -119,8 +119,8 @@ func (maintainer *clusterStatusMaintainer) UpdateMaintenanceTask(tx *gorm.DB, da } if lock.DagID > 0 && dag.IsFail() && dag.GetID() != lock.DagID { - gid := task.ConvertIDToGenericID(dag.GetID(), false) - oldGid := task.ConvertIDToGenericID(lock.DagID, false) + gid := task.ConvertIDToGenericID(dag.GetID(), false, "") + oldGid := task.ConvertIDToGenericID(lock.DagID, false, "") return fmt.Errorf("%s has already executed task %s. '%s: %s' cannot be executed. Please submit a new request", lock.LockName, oldGid, gid, dag.GetName()) } @@ -188,12 +188,39 @@ type agentStatusMaintainer struct { } func (maintainer *agentStatusMaintainer) setStatus(tx *gorm.DB, newStatus int, oldStatus int) error { - resp := tx.Model(&sqlite.OcsInfo{}).Where("name=? and value=?", constant.OCS_INFO_STATUS, oldStatus).Update("value", strconv.Itoa(newStatus)) + resp := tx.Model(&sqlite.OcsInfo{}).Where("name=? and value=?", constant.OBPROXY_INFO_STATUS, oldStatus).Update("value", strconv.Itoa(newStatus)) if resp.Error != nil { return resp.Error } if resp.RowsAffected == 0 { - return fmt.Errorf("failed to start maintenance: agent status is not %d", oldStatus) + if newStatus == task.NOT_UNDER_MAINTENANCE { + var nowStatus int + if err := tx.Set("gorm:query_option", "FOR UPDATE").Model(&sqlite.OcsInfo{}).Select("value").Where("name=?", "status").First(&nowStatus).Error; err != nil { + return err + } else if nowStatus == newStatus { + return nil + } + } + return fmt.Errorf("failed to start maintenance: agent is under maintaince") + } + return nil +} + +func (maintainer *agentStatusMaintainer) setObproxyStatus(tx *gorm.DB, newStatus int, oldStatus int) error { + resp := tx.Model(&sqlite.ObproxyInfo{}).Where("name=? and value=?", constant.OBPROXY_INFO_STATUS, oldStatus).Update("value", strconv.Itoa(newStatus)) + if resp.Error != nil { + return resp.Error + } + if resp.RowsAffected == 0 { + if newStatus == task.NOT_UNDER_MAINTENANCE { + var nowStatus int + if err := tx.Set("gorm:query_option", "FOR UPDATE").Model(&sqlite.OcsInfo{}).Select("value").Where("name=?", "status").First(&nowStatus).Error; err != nil { + return err + } else if nowStatus == newStatus { + return nil + } + } + return fmt.Errorf("failed to start maintenance: agent is under maintenance") } return nil } @@ -202,7 +229,14 @@ func (maintainer *agentStatusMaintainer) StartMaintenance(tx *gorm.DB, dag task. if !dag.IsMaintenance() { return nil } - return maintainer.setStatus(tx, task.GLOBAL_MAINTENANCE, task.NOT_UNDER_MAINTENANCE) + switch dag.GetMaintenanceType() { + case task.GLOBAL_MAINTENANCE: + return maintainer.setStatus(tx, dag.GetMaintenanceType(), task.NOT_UNDER_MAINTENANCE) + case task.OBPROXY_MAINTENACE: + return maintainer.setObproxyStatus(tx, dag.GetMaintenanceType(), task.NOT_UNDER_MAINTENANCE) + default: + return nil + } } func (maintainer *agentStatusMaintainer) UpdateMaintenanceTask(tx *gorm.DB, dag *task.Dag) error { @@ -210,7 +244,14 @@ func (maintainer *agentStatusMaintainer) UpdateMaintenanceTask(tx *gorm.DB, dag } func (maintainer *agentStatusMaintainer) StopMaintenance(tx *gorm.DB, dag task.Maintainer) error { - return maintainer.setStatus(tx, task.NOT_UNDER_MAINTENANCE, task.GLOBAL_MAINTENANCE) + switch dag.GetMaintenanceType() { + case task.GLOBAL_MAINTENANCE: + return maintainer.setStatus(tx, task.NOT_UNDER_MAINTENANCE, task.GLOBAL_MAINTENANCE) + case task.OBPROXY_MAINTENACE: + return maintainer.setObproxyStatus(tx, task.NOT_UNDER_MAINTENANCE, task.OBPROXY_MAINTENACE) + default: + return nil + } } func (maintainer *agentStatusMaintainer) IsRunning() (bool, error) { diff --git a/agent/service/task/sub_task.go b/agent/service/task/sub_task.go index 5aa12b68..48e65fbb 100644 --- a/agent/service/task/sub_task.go +++ b/agent/service/task/sub_task.go @@ -182,7 +182,7 @@ func (s *taskService) StartSubTask(subtask task.ExecutableTask) error { } else if taskInstanceBO.ExecuteTimes != subtask.GetExecuteTimes() { return fmt.Errorf("failed to start task: sub task %d execute times is %d now", subtask.GetID(), taskInstanceBO.ExecuteTimes) } else if taskInstanceBO.ExecuterAgentIp != subtask.GetExecuteAgent().Ip || taskInstanceBO.ExecuterAgentPort != subtask.GetExecuteAgent().Port { - return fmt.Errorf("failed to start task: sub task %d execute agent is %s:%d now", subtask.GetID(), taskInstanceBO.ExecuterAgentIp, taskInstanceBO.ExecuterAgentPort) + return fmt.Errorf("failed to start task: sub task %d execute agent is %s now", subtask.GetID(), meta.NewAgentInfo(taskInstanceBO.ExecuterAgentIp, taskInstanceBO.ExecuterAgentPort).String()) } } subtask.SetState(taskInstanceBO.State) diff --git a/agent/service/task/sub_task_log.go b/agent/service/task/sub_task_log.go index ff6ba609..eeb978e2 100644 --- a/agent/service/task/sub_task_log.go +++ b/agent/service/task/sub_task_log.go @@ -20,6 +20,7 @@ import ( "github.com/oceanbase/obshell/agent/engine/task" oceanbasedb "github.com/oceanbase/obshell/agent/repository/db/oceanbase" sqlitedb "github.com/oceanbase/obshell/agent/repository/db/sqlite" + "github.com/oceanbase/obshell/agent/repository/model/bo" "github.com/oceanbase/obshell/agent/repository/model/oceanbase" "github.com/oceanbase/obshell/agent/repository/model/sqlite" ) @@ -91,6 +92,22 @@ func (s *taskService) GetSubTaskLogsByTaskID(taskID int64) (subTaskLogs []string return } +func (s *taskService) GetFullSubTaskLogsByTaskID(taskID int64) (subTaskLogs []*bo.SubTaskLog, err error) { + db, err := s.getDbInstance() + if err != nil { + return nil, err + } + dest := s.getSubTaskLogModelSlice() + if err = db.Model(s.getSubTaskLogModel()).Where("sub_task_id = ?", taskID).Find(dest).Error; err != nil { + return nil, err + } + subTaskLogsBO := s.convertSubTaskLogBOSlice(dest) + if err != nil { + return nil, err + } + return subTaskLogsBO, nil +} + func (s *SubTaskLogService) GetUnSyncSubTaskLogById(id int64, limit int) (subTaskLogs []sqlite.SubTaskLog, err error) { sqliteDb, err := sqlitedb.GetSqliteInstance() if err != nil { diff --git a/agent/service/tenant/cache.go b/agent/service/tenant/cache.go new file mode 100644 index 00000000..dadeb87d --- /dev/null +++ b/agent/service/tenant/cache.go @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tenant + +import "sync" + +type PasswordMap struct { + m sync.Map +} + +func (pm *PasswordMap) Set(key, value string) { + pm.m.Store(key, value) +} + +func (pm *PasswordMap) Get(key string) (string, bool) { + value, ok := pm.m.Load(key) + if !ok { + return "", false + } + return value.(string), true +} + +var globalPasswordMap *PasswordMap +var once sync.Once + +func GetPasswordMap() *PasswordMap { + once.Do(func() { + globalPasswordMap = &PasswordMap{} + }) + return globalPasswordMap +} diff --git a/agent/service/tenant/database.go b/agent/service/tenant/database.go new file mode 100644 index 00000000..f3f45fb0 --- /dev/null +++ b/agent/service/tenant/database.go @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tenant + +import ( + "fmt" + + "github.com/oceanbase/obshell/agent/repository/model/oceanbase" + "github.com/oceanbase/obshell/param" + "gorm.io/gorm" +) + +const ( + LIST_DATABASE_SQL = ` + SELECT + floor(time_to_usec(o.CREATED) / 1000000) AS CREATE_TIMESTAMP, + o.OBJECT_ID AS DATABASE_ID, + d.DATABASE_NAME AS NAME, + c.ID AS COLLATION_TYPE, + c.COLLATION_NAME AS COLLATION_NAME, + c.CHARACTER_SET_NAME AS CHARACTER_SET_NAME, + c.ID AS COLLATION_TYPE, + d.READ_ONLY as READ_ONLY + FROM + oceanbase.DBA_OB_DATABASES d + JOIN + oceanbase.DBA_OBJECTS o + JOIN + information_schema.collations c + ON + d.DATABASE_NAME = o.OBJECT_NAME + AND + d.COLLATION = c.COLLATION_NAME + WHERE + o.OBJECT_TYPE = 'DATABASE' + ` + GET_DATABASE_SQL = LIST_DATABASE_SQL + " and d.DATABASE_NAME = ?" +) + +func (t *TenantService) AlterDatabase(db *gorm.DB, databaseName string, modifyDatabaseParam *param.ModifyDatabaseParam) error { + sql := fmt.Sprintf("ALTER DATABASE `%s`", databaseName) + if modifyDatabaseParam.Collation != nil { + sql = fmt.Sprintf("%s DEFAULT COLLATE = '%s'", sql, *modifyDatabaseParam.Collation) + } + if modifyDatabaseParam.ReadOnly != nil { + if *modifyDatabaseParam.ReadOnly { + sql = sql + " READ ONLY" + } else { + sql = sql + " READ WRITE" + } + } + return db.Exec(sql).Error +} + +func (t *TenantService) CreateDatabase(db *gorm.DB, createDatabaseParam *param.CreateDatabaseParam) error { + sql := fmt.Sprintf("CREATE DATABASE `%s`", createDatabaseParam.DbName) + if createDatabaseParam.Collation != nil { + sql = fmt.Sprintf("%s DEFAULT COLLATE = '%s'", sql, *createDatabaseParam.Collation) + } + if createDatabaseParam.ReadOnly != nil { + if *createDatabaseParam.ReadOnly { + sql = sql + " READ ONLY" + } else { + sql = sql + " READ WRITE" + } + } + return db.Exec(sql).Error +} + +func (t *TenantService) DropDatabase(db *gorm.DB, databaseName string) error { + sql := fmt.Sprintf("DROP DATABASE `%s`", databaseName) + return db.Exec(sql).Error +} + +func (t *TenantService) ListDatabases(db *gorm.DB) ([]oceanbase.Database, error) { + dbNames := make([]oceanbase.DatabaseName, 0) + dbs := make([]oceanbase.Database, 0) + result := db.Raw("SHOW DATABASES").Scan(&dbNames) + if result.Error != nil { + return dbs, result.Error + } + result = db.Raw(LIST_DATABASE_SQL).Scan(&dbs) + availableDbs := make([]oceanbase.Database, 0, len(dbs)) + for i := range dbs { + for _, dbName := range dbNames { + if dbs[i].Name == dbName.Database { + availableDbs = append(availableDbs, dbs[i]) + } + } + } + return availableDbs, result.Error +} + +func (t *TenantService) GetDatabase(db *gorm.DB, databaseName string) (*oceanbase.Database, error) { + var database oceanbase.Database + result := db.Raw(GET_DATABASE_SQL, databaseName).Scan(&database) + return &database, result.Error +} + +func (t *TenantService) ListDatabasePrivileges(db *gorm.DB) ([]oceanbase.MysqlDb, error) { + dbs := make([]oceanbase.MysqlDb, 0) + result := db.Table(MYSQL_DB).Find(&dbs) + return dbs, result.Error +} + +func (t *TenantService) ListDatabasePrivilegesOfUser(db *gorm.DB, userName string) ([]oceanbase.MysqlDb, error) { + dbs := make([]oceanbase.MysqlDb, 0) + result := db.Table(MYSQL_DB).Find(&dbs, "user=?", userName) + return dbs, result.Error +} diff --git a/agent/service/tenant/enter.go b/agent/service/tenant/enter.go index 5dc9fef4..c58b3699 100644 --- a/agent/service/tenant/enter.go +++ b/agent/service/tenant/enter.go @@ -28,6 +28,9 @@ const ( DBA_OB_UNIT_CONFIGS = "oceanbase.DBA_OB_UNIT_CONFIGS" DBA_OB_CLUSTER_EVENT_HISTORY = "oceanbase.DBA_OB_CLUSTER_EVENT_HISTORY" DBA_RECYCLEBIN = "oceanbase.DBA_RECYCLEBIN" + DBA_OB_USERS = "oceanbase.DBA_OB_USERS" + DBA_OB_DATABASES = "oceanbase.DBA_OB_DATABASES" + DBA_OBJECTS = "oceanbase.DBA_OBJECTS" CDB_OB_SYS_VARIABLES = "oceanbase.CDB_OB_SYS_VARIABLES" CDB_OB_ARCHIVELOG = "oceanbase.CDB_OB_ARCHIVELOG" @@ -42,8 +45,13 @@ const ( GV_OB_PARAMETERS = "oceanbase.GV$OB_PARAMETERS" GV_OB_SERVERS = "oceanbase.GV$OB_SERVERS" + GV_OB_SESSION = "oceanbase.GV$OB_SESSION" MYSQL_TIME_ZONE = "mysql.time_zone" + MYSQL_USER = "mysql.user" + MYSQL_DB = "mysql.db" + + INFOMATION_SCHEMA_COLLATIONS = "information_schema.collations" ) const ( diff --git a/agent/service/tenant/tenant.go b/agent/service/tenant/tenant.go index 76bef2f4..fbe41cfe 100644 --- a/agent/service/tenant/tenant.go +++ b/agent/service/tenant/tenant.go @@ -18,6 +18,7 @@ package tenant import ( "fmt" + "strconv" "strings" "github.com/go-sql-driver/mysql" @@ -28,6 +29,7 @@ import ( "github.com/oceanbase/obshell/agent/errors" "github.com/oceanbase/obshell/agent/meta" oceanbasedb "github.com/oceanbase/obshell/agent/repository/db/oceanbase" + bo "github.com/oceanbase/obshell/agent/repository/model/bo" "github.com/oceanbase/obshell/agent/repository/model/oceanbase" ) @@ -237,7 +239,13 @@ func (t *TenantService) SetTenantVariables(tenantName string, variables map[stri variablesSq := "" for k, v := range variables { if val, ok := v.(string); ok { - variablesSq += fmt.Sprintf(", "+k+"= `%v`", val) + if number, err := strconv.Atoi(val); err == nil { + variablesSq += fmt.Sprintf(", "+k+"= %v", number) + } else if float, err := strconv.ParseFloat(val, 64); err == nil { + variablesSq += fmt.Sprintf(", "+k+"= %v", float) + } else { + variablesSq += fmt.Sprintf(", "+k+"= `%v`", val) + } } else { variablesSq += fmt.Sprintf(", "+k+"= %v", v) } @@ -254,6 +262,19 @@ func (t *TenantService) LockTenant(name string) error { return db.Exec(fmt.Sprintf(SQL_LOCK_TENANT, name)).Error } +func (t *TenantService) IsTenantLocked(name string) (bool, error) { + db, err := oceanbasedb.GetInstance() + if err != nil { + return false, err + } + var count int64 + err = db.Table(DBA_OB_TENANTS).Where("TENANT_NAME = ? AND LOCKED = 'YES'", name).Count(&count).Error + if err != nil { + return false, err + } + return count > 0, nil +} + func (t *TenantService) UnlockTenant(name string) error { db, err := oceanbasedb.GetInstance() if err != nil { @@ -313,6 +334,29 @@ func (t *TenantService) ModifyTenantRootPassword(tenantName string, oldPwd strin return nil } +func (t *TenantService) SetTenantVariablesWithTenant(tenantName, password string, variables map[string]interface{}) error { + tempDb, err := oceanbasedb.LoadGormWithTenant(tenantName, password) + if err != nil { + return errors.Occur(errors.ErrUnexpected, err.Error()) + } + defer func() { + db, _ := tempDb.DB() + if db != nil { + db.Close() + } + }() + variablesSql := "" + for k, v := range variables { + if val, ok := v.(string); ok { + variablesSql += fmt.Sprintf(", GLOBAL "+k+"= `%v`", val) + } else { + variablesSql += fmt.Sprintf(", GLOBAL "+k+"= %v", v) + } + } + sqlText := fmt.Sprintf("SET %s", variablesSql[1:]) + return tempDb.Exec(sqlText).Error +} + func (t *TenantService) AlterTenantPrimaryZone(tenantName string, primaryZone string) error { db, err := oceanbasedb.GetInstance() if err != nil { @@ -342,6 +386,25 @@ func (t *TenantService) GetTenantsOverView() (overviews []oceanbase.DbaObTenant, return } +func (t *TenantService) GetTenantsOverViewByMode(mode string) (overviews []oceanbase.DbaObTenant, err error) { + db, err := oceanbasedb.GetInstance() + if err != nil { + return nil, err + } + if mode == "" { + err = db.Table(DBA_OB_TENANTS). + Where("TENANT_TYPE != 'META' AND IN_RECYCLEBIN = 'NO'"). + Scan(&overviews). + Error + return + } + err = db.Table(DBA_OB_TENANTS). + Where("TENANT_TYPE != 'META' AND IN_RECYCLEBIN = 'NO' AND COMPATIBILITY_MODE = ?", mode). + Scan(&overviews). + Error + return +} + func (t *TenantService) GetTenantParameters(tenantName string, filter string) (parameters []oceanbase.GvObParameter, err error) { db, err := oceanbasedb.GetInstance() if err != nil { @@ -378,6 +441,10 @@ func (t *TenantService) GetTenantVariables(tenantName string, filter string) (va tenantIdQuery := db.Table(DBA_OB_TENANTS).Select("TENANT_ID").Where("TENANT_NAME = ?", tenantName) err = db.Table(CDB_OB_SYS_VARIABLES). Where("TENANT_ID = (?) AND NAME LIKE ?", tenantIdQuery, filter).Scan(&variables).Error + if err != nil { + return nil, err + } + return } @@ -389,6 +456,10 @@ func (t *TenantService) GetTenantVariable(tenantName string, variableName string tenantIdQuery := db.Table(DBA_OB_TENANTS).Select("TENANT_ID").Where("TENANT_NAME = ?", tenantName) err = db.Table(CDB_OB_SYS_VARIABLES). Where("TENANT_ID = (?) AND NAME = ?", tenantIdQuery, variableName).Scan(&variable).Error + if err != nil { + return nil, err + } + return } @@ -430,15 +501,6 @@ func (t *TenantService) IsTenantActiveAgent(tenantName string, ip string, rpcPor return count > 0, err } -func (t *TenantService) GetObServerCapacityByZone(zone string) (servers []oceanbase.ObServerCapacity, err error) { - db, err := oceanbasedb.GetInstance() - if err != nil { - return nil, err - } - err = db.Table(GV_OB_SERVERS).Where("ZONE = ?", zone).Scan(&servers).Error - return -} - func (t *TenantService) IsTimeZoneTableEmpty() (bool, error) { db, err := oceanbasedb.GetInstance() if err != nil { @@ -488,6 +550,23 @@ func (s *TenantService) GetAllUserTenants() (res []oceanbase.DbaObTenant, err er return } +func (s *TenantService) GetAllNotMetaTenantIdToNameMap() (res map[int]string, err error) { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return nil, err + } + var tenants []oceanbase.DbaObTenant + err = oceanbaseDb.Table(DBA_OB_TENANTS).Where(" TENANT_TYPE != ? ", constant.TENANT_TYPE_META).Scan(&tenants).Error + if err != nil { + return nil, err + } + res = make(map[int]string) + for _, tenant := range tenants { + res[tenant.TenantID] = tenant.TenantName + } + return +} + func (s *TenantService) GetTenantByID(id int) (res *oceanbase.DbaObTenant, err error) { oceanbaseDb, err := oceanbasedb.GetInstance() if err != nil { @@ -653,3 +732,75 @@ func (s *TenantService) LoadModuleData(tenantName string, moduleName string) err return tx.Exec(sql).Error }) } + +func (s *TenantService) GetTenantCompaction(tenantId int) (compaction *oceanbase.CdbObMajorCompaction, err error) { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return nil, err + } + err = oceanbaseDb.Model(oceanbase.CdbObMajorCompaction{}).Where("tenant_id = ?", tenantId).Scan(&compaction).Error + return +} + +func (s *TenantService) GetAllMajorCompactions() (compactions []oceanbase.CdbObMajorCompaction, err error) { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return nil, err + } + err = oceanbaseDb.Model(oceanbase.CdbObMajorCompaction{}).Scan(&compactions).Error + return +} + +func (s *TenantService) TenantMajorCompaction(tenantName string) error { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return err + } + return oceanbaseDb.Exec(fmt.Sprintf("ALTER SYSTEM MAJOR FREEZE TENANT = %s", tenantName)).Error +} + +func (s *TenantService) ClearTenantCompactionError(tenantName string) error { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return err + } + return oceanbaseDb.Exec(fmt.Sprintf("ALTER SYSTEM CLEAR MERGE ERROR TENANT = %s", tenantName)).Error +} + +func (s *TenantService) GetSlowSqlRank(top int, startTime int64, endTime int64) (res []bo.TenantSlowSqlCount, err error) { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return nil, err + } + sql := + "select tenant_id, tenant_name, count(distinct db_id, sql_id) as count " + + " from oceanbase.GV$OB_SQL_AUDIT where" + + " char_length(tenant_name) != 0 and elapsed_time > ? " + + " and (request_time + elapsed_time) > ? and (request_time + elapsed_time) < ?" + + " and tenant_name NOT LIKE '%$%'" + + " group by tenant_name" + + " order by count desc limit ?" + err = oceanbaseDb.Raw(sql, constant.SLOW_SQL_THRESHOLD, startTime, endTime, top).Find(&res).Error + return +} + +func (s *TenantService) GetTenantDataDiskUsageMap() (dataDiskUsageMap map[int]int64, err error) { + oceanbaseDb, err := oceanbasedb.GetInstance() + if err != nil { + return nil, err + } + sql := "select coalesce(t1.tenant_id, -1) as tenant_id, sum(data_disk_in_use) as data_disk_in_use from (select t1.unit_id, t1.svr_ip, t1.svr_port, t2.tenant_id, t1.data_disk_in_use from (select unit_id, svr_ip, svr_port, sum(data_disk_in_use) as data_disk_in_use from oceanbase.gv$ob_units group by unit_id ) t1 join oceanbase.dba_ob_units t2 on t1.unit_id = t2.unit_id) t1 join oceanbase.dba_ob_tenants t2 on t1.tenant_id = t2.tenant_id where tenant_type <>'meta' group by tenant_id" + var results []struct { + TenantId int `gorm:"column:tenant_id"` + DataDiskInUse int64 `gorm:"column:data_disk_in_use"` + } + err = oceanbaseDb.Raw(sql).Scan(&results).Error + if err != nil { + return nil, err + } + dataDiskUsageMap = make(map[int]int64) + for _, result := range results { + dataDiskUsageMap[result.TenantId] = result.DataDiskInUse + } + return dataDiskUsageMap, nil +} diff --git a/agent/service/tenant/user.go b/agent/service/tenant/user.go new file mode 100644 index 00000000..fef70c7e --- /dev/null +++ b/agent/service/tenant/user.go @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tenant + +import ( + "fmt" + "strings" + + "github.com/oceanbase/obshell/agent/repository/model/oceanbase" + "github.com/oceanbase/obshell/param" + "gorm.io/gorm" +) + +func (t *TenantService) IsUserExist(db *gorm.DB, userName string) (bool, error) { + var count int64 + err := db.Table(DBA_OB_USERS).Where("USER_NAME = ?", userName).Count(&count).Error + return count > 0, err +} + +func (t *TenantService) CreateUser(db *gorm.DB, userName, password, hostName string) error { + sql := fmt.Sprintf("CREATE USER IF NOT EXISTS `%s`@`%s` IDENTIFIED BY '%s'", userName, hostName, strings.ReplaceAll(password, "'", "'\"'\"'")) + return db.Exec(sql).Error +} + +func (t *TenantService) GrantGlobalPrivilegesWithHost(db *gorm.DB, userName, hostName string, privileges []string) error { + realPrivileges := convertPrivileges(privileges) + sql := fmt.Sprintf("GRANT %s ON *.* TO `%s`@`%s`", strings.Join(realPrivileges, ","), userName, hostName) + return db.Exec(sql).Error +} + +func (t *TenantService) GrantDbPrivilegesWithHost(db *gorm.DB, userName, hostName string, privilege param.DbPrivilegeParam) error { + if len(privilege.Privileges) > 0 { + realPrivileges := convertPrivileges(privilege.Privileges) + sql := fmt.Sprintf("GRANT %s ON `%s`.* TO `%s`@`%s`", strings.Join(realPrivileges, ","), privilege.DbName, userName, hostName) + return db.Exec(sql).Error + } + return nil +} + +func convertPrivileges(privileges []string) []string { + realPrivileges := make([]string, 0) + for _, privilege := range privileges { + realPrivileges = append(realPrivileges, strings.ReplaceAll(privilege, "_", " ")) + } + return realPrivileges +} + +func (t *TenantService) GrantGlobalPrivileges(db *gorm.DB, userName string, privileges []string) error { + realPrivileges := convertPrivileges(privileges) + if len(realPrivileges) > 0 { + sql := fmt.Sprintf("GRANT %s ON *.* TO `%s`", strings.Join(realPrivileges, ", "), userName) + return db.Exec(sql).Error + } + return nil +} + +func (t *TenantService) GrantDbPrivileges(db *gorm.DB, userName string, param *param.DbPrivilegeParam) error { + if param != nil && len(param.Privileges) > 0 { + realPrivileges := convertPrivileges(param.Privileges) + sql := fmt.Sprintf("GRANT %s ON `%s`.* TO `%s`", strings.Join(realPrivileges, ", "), param.DbName, userName) + return db.Exec(sql).Error + } + return nil +} + +func (t *TenantService) RevokeGlobalPrivileges(db *gorm.DB, userName string, privileges []string) error { + realPrivileges := convertPrivileges(privileges) + if len(realPrivileges) > 0 { + sql := fmt.Sprintf("REVOKE %s ON *.* FROM `%s`", strings.Join(realPrivileges, ", "), userName) + return db.Exec(sql).Error + } + return nil +} + +func (t *TenantService) RevokeDbPrivileges(db *gorm.DB, userName string, param *param.DbPrivilegeParam) error { + if param != nil && len(param.Privileges) > 0 { + realPrivileges := convertPrivileges(param.Privileges) + sql := fmt.Sprintf("REVOKE %s ON %s.* FROM `%s`", strings.Join(realPrivileges, ", "), param.DbName, userName) + return db.Exec(sql).Error + } + return nil +} + +func (t *TenantService) DropUser(db *gorm.DB, userName string) error { + sql := fmt.Sprintf("DROP USER `%s`", userName) + return db.Exec(sql).Error +} + +func (t *TenantService) LockUser(db *gorm.DB, userName string) error { + sql := fmt.Sprintf("ALTER USER `%s` ACCOUNT LOCK", userName) + return db.Exec(sql).Error +} + +func (t *TenantService) GetUserSessionStats(db *gorm.DB, userName string) ([]oceanbase.SessionStats, error) { + sessionStats := make([]oceanbase.SessionStats, 0) + result := db.Table(GV_OB_SESSION).Where("user=?", userName).Select("COUNT(*) as COUNT, STATE").Group("STATE").Scan(&sessionStats) + return sessionStats, result.Error +} + +func (t *TenantService) ChangeUserPassword(db *gorm.DB, userName, password string) error { + sql := fmt.Sprintf("ALTER USER `%s` IDENTIFIED BY '%s'", userName, password) + return db.Exec(sql).Error +} + +func (t *TenantService) UnlockUser(db *gorm.DB, userName string) error { + sql := fmt.Sprintf("ALTER USER `%s` ACCOUNT UNLOCK", userName) + return db.Exec(sql).Error +} + +func (t *TenantService) ListUsers(db *gorm.DB) ([]oceanbase.MysqlUser, error) { + users := make([]oceanbase.MysqlUser, 0) + result := db.Table(MYSQL_USER).Find(&users) + return users, result.Error +} + +func (t *TenantService) GetUser(db *gorm.DB, userName string) (*oceanbase.MysqlUser, error) { + var user oceanbase.MysqlUser + result := db.Table(MYSQL_USER).First(&user, "user=?", userName) + return &user, result.Error +} diff --git a/client/cmd/cluster/enter.go b/client/cmd/cluster/enter.go index a7edd740..23d667ef 100644 --- a/client/cmd/cluster/enter.go +++ b/client/cmd/cluster/enter.go @@ -53,15 +53,17 @@ const ( // CMD_INIT represents the "init" command used to initialize the cluster. CMD_INIT = "init" // Flags for the "init" command. - FLAG_PASSWORD = "rootpassword" - FLAG_PASSWORD_ALIAS = "rp" - FLAG_CLUSTER_NAME = "cluster_name" - FLAG_CLUSTER_NAME_SH = "n" - FLAG_CLUSTER_ID = "cluster_id" - FLAG_CLUSTER_ID_SH = "i" - FLAG_RS_LIST = "rs_list" - FLAG_RS_LIST_ALIAS = "rs" - FLAG_IMPORT_SCRIPT = "import_script" + FLAG_PASSWORD = "rootpassword" + FLAG_PASSWORD_ALIAS = "rp" + FLAG_CLUSTER_NAME = "cluster_name" + FLAG_CLUSTER_NAME_SH = "n" + FLAG_CLUSTER_ID = "cluster_id" + FLAG_CLUSTER_ID_SH = "i" + FLAG_RS_LIST = "rs_list" + FLAG_RS_LIST_ALIAS = "rs" + FLAG_IMPORT_SCRIPT = "import_script" + FLAG_CREATE_PROXYRO_USER = "create_proxyro_user" + FLAG_PROXYRO_PASSWORD = "proxyro_password" // CMD_START represents the "start" command used to start observers. CMD_START = "start" diff --git a/client/cmd/cluster/init.go b/client/cmd/cluster/init.go index e7c7c8d6..3ed242af 100644 --- a/client/cmd/cluster/init.go +++ b/client/cmd/cluster/init.go @@ -36,9 +36,11 @@ import ( ) type ClusterInitFlags struct { - password string - verbose bool - importScript bool + password string + verbose bool + importScript bool + createProxyroUser bool + proxyroPassword string ObserverConfigFlags } @@ -77,6 +79,8 @@ func newInitCmd() *cobra.Command { initCmd.VarsPs(&opts.optStr, []string{FLAG_OPT_STR, FLAG_OPT_STR_SH}, "", "Additional parameters for the observer, use the format key=value for each configuration, separated by commas.", false) initCmd.VarsPs(&opts.rsList, []string{FLAG_RS_LIST, FLAG_RS_LIST_ALIAS}, "", "Root service list", false) initCmd.VarsPs(&opts.importScript, []string{FLAG_IMPORT_SCRIPT}, false, "Import the observer's scripts for sys tenant.", false) + initCmd.VarsPs(&opts.createProxyroUser, []string{FLAG_CREATE_PROXYRO_USER}, false, "Create the default user 'proxyro'.", false) + initCmd.VarsPs(&opts.proxyroPassword, []string{FLAG_PROXYRO_PASSWORD}, "", "Password for the default user 'proxyro'.", false) initCmd.VarsPs(&opts.verbose, []string{clientconst.FLAG_VERBOSE, clientconst.FLAG_VERBOSE_SH}, false, "Activate verbose output", false) @@ -108,7 +112,9 @@ func clusterInit(cmd *cobra.Command, flags *ClusterInitFlags) error { func buildInitParams(flags *ClusterInitFlags) *param.ObInitParam { return ¶m.ObInitParam{ - ImportScript: flags.importScript, + ImportScript: flags.importScript, + CreateProxyroUser: flags.createProxyroUser, + ProxyroPassword: flags.proxyroPassword, } } diff --git a/client/cmd/cluster/join.go b/client/cmd/cluster/join.go index dfce73fc..d52644c6 100644 --- a/client/cmd/cluster/join.go +++ b/client/cmd/cluster/join.go @@ -17,7 +17,6 @@ package cluster import ( - "regexp" "strconv" "strings" @@ -29,6 +28,7 @@ import ( "github.com/oceanbase/obshell/agent/errors" "github.com/oceanbase/obshell/agent/executor/ob" ocsagentlog "github.com/oceanbase/obshell/agent/log" + "github.com/oceanbase/obshell/agent/meta" "github.com/oceanbase/obshell/client/command" clientconst "github.com/oceanbase/obshell/client/constant" cmdlib "github.com/oceanbase/obshell/client/lib/cmd" @@ -93,7 +93,7 @@ func agentJoin(cmd *cobra.Command, flags *AgentJoinFlags) error { } stdio.StopLoading() - targetAgent, err := NewAgentByString(flags.server) + targetAgent, err := meta.ConvertAddressToAgentInfo(flags.server) if err != nil { return err } @@ -172,11 +172,7 @@ func isValidRsList(rsList string) bool { servers := strings.Split(rsList, ";") for _, server := range servers { if server != "" { - arr := strings.Split(server, ":") - if len(arr) != 3 { - return false - } - if !isValidIp(arr[0]) || !isValidPortStr(arr[1]) || !isValidPortStr(arr[2]) { + if _, err := meta.ConvertAddressToAgentInfo(server); err != nil { return false } } @@ -184,26 +180,6 @@ func isValidRsList(rsList string) bool { return true } -func isValidIp(ip string) bool { - ipRegexp := regexp.MustCompile(`^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$`) - return ipRegexp.MatchString(ip) -} - -func isValidPortStr(port string) bool { - if port == "" { - return true - } - p, err := strconv.Atoi(port) - if err != nil { - return false - } - return isValidPort(p) -} - -func isValidPort(port int) bool { - return port > 1024 && port < 65536 -} - func isValidLogLevel(level string) bool { if level == "" { return true @@ -221,14 +197,14 @@ func checkServerConfigFlags(config map[string]string) error { stdio.Verbose("Check whether the configs is valid") if mysqlPort, ok := config[constant.CONFIG_MYSQL_PORT]; ok { stdio.Verbosef("Check mysql port: %s", mysqlPort) - if !isValidPortStr(mysqlPort) { + if !utils.IsValidPort(mysqlPort) { return errors.Errorf("Invalid port: %s. Port number should be in the range [1024, 65535].", mysqlPort) } } if rpcPort, ok := config[constant.CONFIG_RPC_PORT]; ok { stdio.Verbosef("Check rpc port: %s", rpcPort) - if !isValidPortStr(rpcPort) { + if !utils.IsValidPort(rpcPort) { return errors.Errorf("Invalid port: %s. Port number should be in the range [1024, 65535].", rpcPort) } } diff --git a/client/cmd/cluster/remove.go b/client/cmd/cluster/remove.go index 9627fc54..0fc9cb7e 100644 --- a/client/cmd/cluster/remove.go +++ b/client/cmd/cluster/remove.go @@ -25,6 +25,7 @@ import ( "github.com/oceanbase/obshell/agent/errors" "github.com/oceanbase/obshell/agent/lib/http" ocsagentlog "github.com/oceanbase/obshell/agent/log" + "github.com/oceanbase/obshell/agent/meta" "github.com/oceanbase/obshell/client/command" clientconst "github.com/oceanbase/obshell/client/constant" cmdlib "github.com/oceanbase/obshell/client/lib/cmd" @@ -71,7 +72,7 @@ func newRemoveCmd() *cobra.Command { } func agentRemove(flags *AgentRemoveFlags) error { - targetAgent, err := NewAgentByString(flags.server) + targetAgent, err := meta.ConvertAddressToAgentInfo(flags.server) if err != nil { return err } diff --git a/client/cmd/cluster/scale_in.go b/client/cmd/cluster/scale_in.go index f86ef128..79b175d4 100644 --- a/client/cmd/cluster/scale_in.go +++ b/client/cmd/cluster/scale_in.go @@ -27,6 +27,7 @@ import ( "github.com/oceanbase/obshell/agent/errors" "github.com/oceanbase/obshell/agent/lib/http" ocsagentlog "github.com/oceanbase/obshell/agent/log" + "github.com/oceanbase/obshell/agent/meta" "github.com/oceanbase/obshell/client/command" clientconst "github.com/oceanbase/obshell/client/constant" "github.com/oceanbase/obshell/client/global" @@ -110,7 +111,7 @@ func clusterScaleIn(cmd *cobra.Command, flags *ClusterScaleInFlags) (err error) } func deleteServer(server string, forceKill bool) (*task.DagDetailDTO, error) { - targetAgentInfo, err := NewAgentByString(server) + targetAgentInfo, err := meta.ConvertAddressToAgentInfo(server) if err != nil { return nil, err } diff --git a/client/cmd/cluster/scale_out.go b/client/cmd/cluster/scale_out.go index 4f3e6193..0768b9dd 100644 --- a/client/cmd/cluster/scale_out.go +++ b/client/cmd/cluster/scale_out.go @@ -18,8 +18,6 @@ package cluster import ( "fmt" - "strconv" - "strings" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -107,7 +105,7 @@ func clusterScaleOut(cmd *cobra.Command, flags *ClusterScaleOutFlags) (err error return err } - targetAgentInfo, err := NewAgentByString(flags.agent) + targetAgentInfo, err := meta.ConvertAddressToAgentInfo(flags.agent) if err != nil { return err } @@ -173,29 +171,3 @@ func buildScaleOutParam(flags *ClusterScaleOutFlags) (*param.ScaleOutParam, erro func scaleOutCmdExample() string { return ` obshell cluster scale-out -s 192.168.1.1:2886 -z zone1 --rp ****` } - -func NewAgentByString(str string) (*meta.AgentInfo, error) { - stdio.Verbosef("Parse target agent info from string: %s", str) - info := strings.Split(str, ":") - if !isValidIp(info[0]) { - return nil, errors.Errorf("Invalid ip address: %s", info[0]) - } - //If the observer provides a port number, use the port number, - //otherwise use the default port number 2886 - agent := &meta.AgentInfo{ - Ip: info[0], - Port: constant.DEFAULT_AGENT_PORT, - } - if len(info) > 1 { - if info[1] == "" { - return nil, errors.Errorf("Invalid server format: '%s:'", info[0]) - } - port, err := strconv.Atoi(info[1]) - if err != nil || !isValidPortStr(info[1]) { - return nil, errors.Errorf("Invalid port: %s. Port number should be in the range [1024, 65535].", info[1]) - } - agent.Port = port - } - stdio.Verbosef("Parsed target agent info: %v", agent) - return agent, nil -} diff --git a/client/cmd/cluster/start.go b/client/cmd/cluster/start.go index e08bdcb3..72d9c0e6 100644 --- a/client/cmd/cluster/start.go +++ b/client/cmd/cluster/start.go @@ -121,7 +121,7 @@ func clusterStart(flags *ClusterStartFlags) (err error) { } if flags.server == "" && flags.zone == "" && !flags.global { - flags.server = fmt.Sprintf("%s:%d", agentStatus.Agent.GetIp(), agentStatus.Agent.GetPort()) + flags.server = agentStatus.Agent.String() } stdio.Verbosef("current my agent is %s", agentStatus.Agent.GetIdentity()) diff --git a/client/cmd/cluster/stop.go b/client/cmd/cluster/stop.go index f12d6f0f..c9ae302f 100644 --- a/client/cmd/cluster/stop.go +++ b/client/cmd/cluster/stop.go @@ -116,7 +116,7 @@ func clusterStop(flags *ClusterStopFlags) (err error) { } if flags.server == "" && flags.zone == "" && !flags.global { - flags.server = fmt.Sprintf("%s:%d", agentStatus.Agent.GetIp(), agentStatus.Agent.GetPort()) + flags.server = agentStatus.Agent.String() } if err = CheckAllAgentMaintenance(); err != nil { @@ -169,11 +169,9 @@ func callEmerTypeApi(uri string, param interface{}) (err error) { signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) go func() { sig := <-sigChan - stdio.StopLoading() stdio.Printf("\nReceived signal: %v", sig) stdio.Info("try to cancel the task, please wait...") if err := dagHandler.CancelDag(); err != nil { - stdio.StopLoading() stdio.Warnf("Failed to cancel the task: %s", err.Error()) os.Exit(1) } diff --git a/client/cmd/cluster/take_over.go b/client/cmd/cluster/take_over.go index 4f830948..c959256d 100644 --- a/client/cmd/cluster/take_over.go +++ b/client/cmd/cluster/take_over.go @@ -24,10 +24,6 @@ import ( log "github.com/sirupsen/logrus" - "github.com/oceanbase/obshell/client/global" - "github.com/oceanbase/obshell/client/lib/http" - "github.com/oceanbase/obshell/client/lib/stdio" - "github.com/oceanbase/obshell/client/utils/api" "github.com/oceanbase/obshell/agent/cmd/admin" "github.com/oceanbase/obshell/agent/cmd/daemon" "github.com/oceanbase/obshell/agent/constant" @@ -36,6 +32,10 @@ import ( "github.com/oceanbase/obshell/agent/lib/path" "github.com/oceanbase/obshell/agent/meta" "github.com/oceanbase/obshell/agent/repository/db/oceanbase" + "github.com/oceanbase/obshell/client/global" + "github.com/oceanbase/obshell/client/lib/http" + "github.com/oceanbase/obshell/client/lib/stdio" + "github.com/oceanbase/obshell/client/utils/api" ) func handleIfInTakeoverProcess() error { @@ -98,38 +98,34 @@ func getServersForEmecStart(flags *ClusterStartFlags) (servers []string, err err } // getServersByInputAndConf takes a ClusterStartFlags structure and a list of server addresses paired with their RPC ports, -func getServersByInputAndConf(flags *ClusterStartFlags, serversWithRpcPort [][2]string) (servers []string, err error) { +func getServersByInputAndConf(flags *ClusterStartFlags, serversWithRpcPort []meta.AgentInfoInterface) (servers []string, err error) { if getScopeType(&flags.scopeFlags) == ob.SCOPE_GLOBAL { for _, server := range serversWithRpcPort { - servers = append(servers, server[0]) + servers = append(servers, server.GetIp()) } return } // If Server scope is specified, perform detailed validation. - var items []string inputServers := strings.Split(strings.TrimSpace(flags.server), ",") for _, inputServer := range inputServers { - items = strings.Split(inputServer, ":") - if len(items) != 2 { - return nil, errors.Errorf("invalid server format: %s", inputServer) - } - if items[1] != fmt.Sprint(constant.DEFAULT_AGENT_PORT) { - return nil, errors.Errorf("unsupported port: %s in emergency case", items[1]) + inputServerInfo, err := meta.ConvertAddressToAgentInfo(inputServer) + if err != nil { + return nil, errors.Errorf("invalid server '%s'", inputServerInfo) } // Check if the server with the default port is present in the configuration. var found bool for _, server := range serversWithRpcPort { - if server[0] == items[0] { + if server.GetIp() == inputServerInfo.GetIp() { found = true break } } if !found { - return nil, errors.Errorf("server %s is not in the ob conf", items[0]) + return nil, errors.Errorf("server %s is not in the ob conf", inputServerInfo.GetIp()) } - servers = append(servers, items[0]) + servers = append(servers, inputServerInfo.GetIp()) } log.Info("servers to start ", servers) return @@ -226,7 +222,8 @@ func sshStartRemoteAgentForTakeOver(server string, agentPort int, sshFlags SSHFl } defer SSHClient.Close() - cmd := fmt.Sprintf(`export OB_ROOT_PASSWORD='%s';%s cluster start -s '%s:%d'`, os.Getenv(constant.OB_ROOT_PASSWORD), path.ObshellBinPath(), server, agentPort) + agentInfo := meta.NewAgentInfo(server, agentPort) + cmd := fmt.Sprintf(`export OB_ROOT_PASSWORD='%s';%s cluster start -s '%s'`, os.Getenv(constant.OB_ROOT_PASSWORD), path.ObshellBinPath(), agentInfo.String()) if msg, err := SSHClient.Exec(cmd); err != nil { errCh <- errors.Wrapf(err, "failed to start remote agent on %s, error msg: %s", server, string(msg)) return diff --git a/client/cmd/cluster/upgrade.go b/client/cmd/cluster/upgrade.go index 984262e0..ddf3a395 100644 --- a/client/cmd/cluster/upgrade.go +++ b/client/cmd/cluster/upgrade.go @@ -207,7 +207,7 @@ func obUpgrade(params *param.ObUpgradeParam) (err error) { func uploadPkgsByNameInDir(params *param.ObUpgradeParam, pkgDir string, pkgs map[string]*rpm.Package) (err error) { stdio.Verbose("Uploading OceanBase packages to the cluster") - myOBVersion, _ := binary.GetMyOBVersion() + myOBVersion, _, _ := binary.GetMyOBVersion() return UploadPkgsByNameAndVersionInDir(pkgDir, pkgs, myOBVersion, params.Version, params.Release, false) } @@ -266,7 +266,7 @@ func getTargetVersion(opts *clusterUpgradeFlags, pkgs map[string]*rpm.Package) ( } stdio.Verbosef("The target version is %s", targetBuildVersion) - myOBVersion, err := binary.GetMyOBVersion() + myOBVersion, _, err := binary.GetMyOBVersion() if err != nil { return "", err } diff --git a/client/cmd/recyclebin/tenant/enter.go b/client/cmd/recyclebin/tenant/enter.go index 6cf64d21..5d06e4e6 100644 --- a/client/cmd/recyclebin/tenant/enter.go +++ b/client/cmd/recyclebin/tenant/enter.go @@ -34,7 +34,7 @@ const ( FLAG_NEW_NAME_SH = "n" FLAG_NEW_NAME = "new_name" - // obshell recyclebin tenatn show + // obshell recyclebin tenant show CMD_SHOW = "show" ) diff --git a/client/cmd/tenant/show.go b/client/cmd/tenant/show.go index d2ab8ee5..922d678f 100644 --- a/client/cmd/tenant/show.go +++ b/client/cmd/tenant/show.go @@ -35,7 +35,7 @@ import ( ) var shortHeader = []string{"Name", "Id", "Mode", "Locality", "Primary Zone", "Status", "Locked"} -var longHeader = []string{"Name", "Id", "Mode", "Locality", "Primary Zone", "Status", "Unit Num(Each Zone)", "Unit Config", "Locked", "Whitelist", "Create Time"} +var longHeader = []string{"Name", "Id", "Mode", "Locality", "Primary Zone", "Status", "Unit Num(Each Zone)", "Unit Config", "Locked", "Readonly", "Whitelist", "Create Time"} type tenantShowFlags struct { showDetail bool @@ -99,7 +99,11 @@ func tenantShow(showDetails bool, name ...string) error { for _, pool := range info.Pools { unitConfigs += fmt.Sprintf("%s(%s);", pool.ZoneList, pool.Unit.Name) } - data = append(data, []string{tenant.TenantName, fmt.Sprint(tenant.TenantID), tenant.Mode, tenant.Locality, tenant.PrimaryZone, tenant.Status, fmt.Sprint(info.Pools[0].UnitNum), unitConfigs, tenant.Locked, info.Whitelist, tenant.CreatedTime.Format(time.DateTime)}) + readOnly := "false" + if info.ReadOnly { + readOnly = "true" + } + data = append(data, []string{tenant.TenantName, fmt.Sprint(tenant.TenantID), tenant.Mode, tenant.Locality, tenant.PrimaryZone, tenant.Status, fmt.Sprint(info.Pools[0].UnitNum), unitConfigs, tenant.Locked, readOnly, info.Whitelist, tenant.CreatedTime.Format(time.DateTime)}) } } } diff --git a/client/cmd/tenant/variable/enter.go b/client/cmd/tenant/variable/enter.go index d44408d5..a1319032 100644 --- a/client/cmd/tenant/variable/enter.go +++ b/client/cmd/tenant/variable/enter.go @@ -42,6 +42,8 @@ const ( // obshell tenant variable set CMD_SET = "set" + + FLAG_TENANT_PASSWORD = "tenant_password" ) func NewVariableCmd() *cobra.Command { @@ -112,6 +114,7 @@ func showVariable(cmd *cobra.Command, tenant string, variable string) error { func newSetCmd() *cobra.Command { var verbose bool + var tenantPassword string setCmd := command.NewCommand(&cobra.Command{ Use: CMD_SET, Short: "Set speciaic variables.", @@ -130,7 +133,7 @@ func newSetCmd() *cobra.Command { cmd.SilenceUsage = true ocsagentlog.InitLogger(config.DefaultClientLoggerConifg()) stdio.SetVerboseMode(verbose) - if err := setVariable(cmd, args[0], args[1]); err != nil { + if err := setVariable(cmd, args[0], args[1], tenantPassword); err != nil { stdio.LoadFailedWithoutMsg() stdio.Error(err.Error()) return err @@ -141,17 +144,19 @@ func newSetCmd() *cobra.Command { }) setCmd.Annotations = map[string]string{clientconst.ANNOTATION_ARGS: " "} setCmd.VarsPs(&verbose, []string{clientconst.FLAG_VERBOSE, clientconst.FLAG_VERBOSE_SH}, false, "Activate verbose output", false) + setCmd.VarsPs(&tenantPassword, []string{FLAG_TENANT_PASSWORD}, "", "Tenant password", false) return setCmd.Command } -func setVariable(cmd *cobra.Command, tenant string, str string) error { +func setVariable(cmd *cobra.Command, tenant string, str string, tenantPassword string) error { variables, err := parameter.BuildVariableOrParameterMap(str) if err != nil { cmd.SilenceUsage = false return err } params := param.SetTenantVariablesParam{ - Variables: variables, + Variables: variables, + TenantPassword: tenantPassword, } stdio.StartLoading("set tenant variables") if err := api.CallApiWithMethod(http.PUT, constant.URI_TENANT_API_PREFIX+"/"+tenant+constant.URI_VARIABLES, params, nil); err != nil { diff --git a/client/cmd/unit/show.go b/client/cmd/unit/show.go index 39a31671..e881f781 100644 --- a/client/cmd/unit/show.go +++ b/client/cmd/unit/show.go @@ -59,7 +59,7 @@ func newShowCmd() *cobra.Command { return showCmd.Command } -func transferCapacity(capacity int) string { +func transferCapacity(capacity int64) string { var cap = []string{"B", "KB", "MB", "GB", "TB", "PB"} i := 0 for capacity >= 1024 { diff --git a/client/lib/http/ssh.go b/client/lib/http/ssh.go index ab355974..f4620e47 100644 --- a/client/lib/http/ssh.go +++ b/client/lib/http/ssh.go @@ -17,16 +17,17 @@ package http import ( - "fmt" "io" "os" osuser "os/user" "path/filepath" "strconv" - "github.com/oceanbase/obshell/utils" "github.com/pkg/errors" "golang.org/x/crypto/ssh" + + "github.com/oceanbase/obshell/agent/meta" + "github.com/oceanbase/obshell/utils" ) const DEFALUT_SSH_PORT = 22 @@ -218,5 +219,7 @@ func newClient(config *SSHClient, auth ...ssh.AuthMethod) (*ssh.Client, error) { Auth: auth, HostKeyCallback: ssh.InsecureIgnoreHostKey(), } - return ssh.Dial("tcp", fmt.Sprintf("%s:%d", config.Host, config.Port), conf) + + server := meta.NewAgentInfo(config.Host, config.Port) + return ssh.Dial("tcp", server.String(), conf) } diff --git a/cmd/main.go b/cmd/main.go index 4359bc91..341962c8 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -71,6 +71,7 @@ func main() { } agentcmd.PreHandler() + if err := cmds.Execute(); err != nil { os.Exit(-1) } diff --git a/frontend/.eslintignore b/frontend/.eslintignore new file mode 100755 index 00000000..2e5e01a0 --- /dev/null +++ b/frontend/.eslintignore @@ -0,0 +1,5 @@ +test/fixtures +.umi +.umi-production +src/locale +public diff --git a/frontend/.eslintrc b/frontend/.eslintrc new file mode 100755 index 00000000..6731917e --- /dev/null +++ b/frontend/.eslintrc @@ -0,0 +1,40 @@ +{ + "extends": [ + "prettier" + ], + "plugins": [ + "react-hooks" + ], + "rules": { + "react/jsx-boolean-value": 0, + "no-nested-ternary": [ + 0 + ], + "react/no-unused-state": [ + 1 + ], + "react/jsx-no-target-blank": 0, + "no-return-assign": "off", + "no-param-reassign": "warn", + "no-new": "off", + "no-template-curly-in-string": "off", + "no-use-before-define": "off", + "no-unused-expressions": "off", + "no-debugger": "error", + "@typescript-eslint/no-use-before-define": "off", + "@typescript-eslint/no-loop-func": [ + 1 + ], + "@typescript-eslint/no-this-alias": [ + 1 + ], + // 检查 Hook 的规则 + "react-hooks/rules-of-hooks": "error", + // 不检查 effect 的依赖,否则 name.join(',') 这样的 dep 会 lint 不通过 + "react-hooks/exhaustive-deps": "off", + "@typescript-eslint/no-invalid-this": "off" + }, + "globals": { + "__": true + } +} \ No newline at end of file diff --git a/frontend/.fast-spm-local.json b/frontend/.fast-spm-local.json new file mode 100644 index 00000000..c5f29e5b --- /dev/null +++ b/frontend/.fast-spm-local.json @@ -0,0 +1,79 @@ +{ + "src/component/AobException": [ + { + "name": "异常页-返回首页", + "spm": "ca48180.da30493" + }, + { + "name": "异常页-返回首页", + "spm": "ca48180.da30493" + } + ], + "src/component/BatchOperationBar": [], + "src/component/Chart": [], + "src/component/CheckboxPopover": [], + "src/component/ContentWithInfo": [], + "src/component/ContentWithIcon": [], + "src/component/ComparisonMetricChart": [], + "src/component/ContentWithQuestion": [], + "src/component/DatabasePrivilegeTransfer": [], + "src/component/FilterDropdown": [], + "src/component/Empty": [], + "src/component/FormEditTable": [], + "src/component/FormTable": [], + "src/component/FormEditZoneReplicaTable": [], + "src/component/FormPrimaryZone": [], + "src/component/FormZoneReplicaTable": [], + "src/component/GlobalLoading": [], + "src/component/FullScreen": [], + "src/component/GraphToolbar": [], + "src/component/Icon": [], + "src/component/HighlightWithLineNumbers": [], + "src/component/MetricResourceChart": [], + "src/component/MetricChart": [ + { + "name": "监控卡片-下钻", + "spm": "ca48181.da30494" + }, + { + "name": "监控卡片-下钻", + "spm": "ca48181.da30494" + } + ], + "src/component/MetricCard": [], + "src/component/MetricTopChart": [], + "src/component/ModifyClusterParameterDrawer": [], + "src/component/MonitorSearch": [], + "src/component/MyCard": [], + "src/component/MyDrawer": [], + "src/component/MyProgress": [], + "src/component/NoAuth": [], + "src/component/OCPRangePicker": [], + "src/component/ObClusterDeployMode": [], + "src/component/PageLoading": [], + "src/component/PageCard": [], + "src/component/RangeInput": [], + "src/component/ParameterTemplate": [], + "src/component/RangeTimeDropdown": [], + "src/component/Result": [], + "src/component/ResourcePoolSelect": [], + "src/component/ScheduleModeAndDayList": [], + "src/component/TaskBubble": [], + "src/component/UnitSpec": [], + "src/component/TenantMonitorTop5": [], + "src/component/UnitSpecSelect": [], + "src/component/WaterLevel": [], + "src/component/WhitelistInput": [], + "src/component/common": [], + "src/page/Diagnosis": [], + "src/page/Cluster": [], + "src/page/Error": [], + "src/page/Layout": [], + "src/page/Login": [], + "src/page/Monitor": [], + "src/page/Log": [], + "src/page/Result": [], + "src/page/Property": [], + "src/page/Tenant": [], + "src/page/Task": [] +} \ No newline at end of file diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 00000000..c19d0634 --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,23 @@ +pids +logs +node_modules +npm-debug.log +coverage/ +build/ +run +.DS_Store +.nyc_output +.umi +.umi-production +speed-measure.json +unprocessed-code.txt +unprocessed-code.ts.txt +yarn.lock +.node +.ignore +dist +unuseful-locale-key.txt +docs.zip +config/config.local.ts +.env +package-lock.json diff --git a/frontend/.nvmrc b/frontend/.nvmrc new file mode 100644 index 00000000..5692975b --- /dev/null +++ b/frontend/.nvmrc @@ -0,0 +1 @@ +16.19.1 \ No newline at end of file diff --git a/frontend/.prettierignore b/frontend/.prettierignore new file mode 100644 index 00000000..0d5b703a --- /dev/null +++ b/frontend/.prettierignore @@ -0,0 +1,15 @@ +node_modules +.umi +.umi-production +locale +# 通过 OneAPI 自动生成的 service 代码不需要通过 prettier 进行格式化 +src/service/ocp-express +mock +.node +.cloudide +_package +dist +dist-awr +dist-ash +public +.secignore diff --git a/frontend/.prettierrc b/frontend/.prettierrc new file mode 100644 index 00000000..065e0130 --- /dev/null +++ b/frontend/.prettierrc @@ -0,0 +1,6 @@ +{ + "singleQuote": true, + "trailingComma": "es5", + "printWidth": 100, + "arrowParens": "avoid" +} diff --git a/frontend/.stylelintrc b/frontend/.stylelintrc new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/frontend/.stylelintrc @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/frontend/config/config.tester.ts b/frontend/config/config.tester.ts new file mode 100755 index 00000000..c19fdd28 --- /dev/null +++ b/frontend/config/config.tester.ts @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { defineConfig } from 'umi'; + +export default defineConfig({ + define: { + 'process.env.ENV': 'tester', + }, +}); diff --git a/frontend/config/config.ts b/frontend/config/config.ts new file mode 100755 index 00000000..0bdd3b5f --- /dev/null +++ b/frontend/config/config.ts @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { defineConfig } from 'umi'; +import AntdMomentWebpackPlugin from '@ant-design/moment-webpack-plugin'; +import routes from './routes'; + +const ocp = { + // target: 'http://11.124.9.175:5102', // OBShell 接口地址 + target: 'http://11.161.204.49:30871/', // OBShell 接口地址 +}; + +export default defineConfig({ + routes, + singular: true, + nodeModulesTransform: { + type: 'none', + exclude: [], + }, + // 需要关闭 title 配置,避免与 useDocumentTitle 的逻辑冲突 + // 冲突的具体表现为: 切换路由时,父组件设置的文档标题会自动重置为配置的 title + title: false, + favicon: '/assets/logo/ocp_express_favicon.svg', + // 接口代理配置 + proxy: { + '/api/v1': { + ...ocp, + }, + '/api/v2': { + ...ocp, + }, + services: { + ...ocp, + }, + }, + + antd: { + disableBabelPluginImport: true, + }, + dva: { + disableModelsReExport: true, + }, + mfsu: {}, + locale: { + default: 'zh-CN', + // disable antd locale import in umi plugin-locale to avoid build error + // issue: https://github.com/oceanbase/ocp-express/pull/22 + antd: false, + title: false, + }, + // esbuild: {}, + dynamicImport: { + loading: '@/component/PageLoading', + }, + // 开启运行时 publicPath + runtimePublicPath: true, + chainWebpack: (config, { env }) => { + if (env === 'production') { + config.optimization.delete('noEmitOnErrors'); + config.plugins.delete('optimize-css'); + + // 因为删除原来适配webpack4的css压缩插件,css压缩可以用 mini-css-extract-plugin + config.optimization.minimize(true); + // config.optimization.minimizer(`css-esbuildMinify`).use(CSSMinimizerWebpackPlugin); + } + // 添加 AntdMomentWebpackPlugin 插件 + config.plugin('antd-moment').use(AntdMomentWebpackPlugin, [ + { + // 关闭 dayjs alias,避免 antd 以外的 dayjs 被 alias 成 moment + disableDayjsAlias: true, + }, + ]); + // 静态资源的文件限制调整为 1GB,避免视频等大文件资源阻塞项目启动 + config.performance.maxAssetSize(1000000000); + return config; + }, + plugins: ['./config/plugin.must.ts'], + // headScripts: [ + // `!function(modules){function __webpack_require__(moduleId){if(installedModules[moduleId])return installedModules[moduleId].exports;var module=installedModules[moduleId]={exports:{},id:moduleId,loaded:!1};return modules[moduleId].call(module.exports,module,module.exports,__webpack_require__),module.loaded=!0,module.exports}var installedModules={};return __webpack_require__.m=modules,__webpack_require__.c=installedModules,__webpack_require__.p="",__webpack_require__(0)}([function(module,exports){"use strict";!function(){if(!window.Tracert){for(var Tracert={_isInit:!0,_readyToRun:[],_guid:function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(c){var r=16*Math.random()|0,v="x"===c?r:3&r|8;return v.toString(16)})},get:function(key){if("pageId"===key){if(window._tracert_loader_cfg=window._tracert_loader_cfg||{},window._tracert_loader_cfg.pageId)return window._tracert_loader_cfg.pageId;var metaa=document.querySelectorAll("meta[name=data-aspm]"),spma=metaa&&metaa[0].getAttribute("content"),spmb=document.body&&document.body.getAttribute("data-aspm"),pageId=spma&&spmb?spma+"."+spmb+"_"+Tracert._guid()+"_"+Date.now():"-_"+Tracert._guid()+"_"+Date.now();return window._tracert_loader_cfg.pageId=pageId,pageId}return this[key]},call:function(){var argsList,args=arguments;try{argsList=[].slice.call(args,0)}catch(ex){var argsLen=args.length;argsList=[];for(var i=0;i { + const isConsoleLog = /^console\.log\(/gi.test(path.parentPath.toString()); + const isSpm = /^spm\=/g.test(path.parentPath.toString()); + const isDataSpm = /^data\-aspm\-desc\=/g.test(path.parentPath.toString()); + + let isFormattedMessage = false; + // 识别 标签的文字层级 + try { + isFormattedMessage = /^\ { + const start = content.indexOf('{') + 1; + const end = content.lastIndexOf('}'); + return content.substring(start, end); +}; + +/** + * To relative path + * @param {string} absolutePath absolute path, like: /Users/puss/work/ioc/vue-loader/index.js + * @param {string} cwd cwd, like: /Users/puss/work/ioc/ + * @param {string} splitter splitter, win \ , linux / + * @return {string} path , like: vue-loader/index.js + */ +export function toRelativePath(absolutePath, cwd, splitter) { + return absolutePath.replace(cwd + splitter, ''); +} + +export default (api: IApi) => { + const { utils } = api; + const { chalk, rimraf } = utils; + api.registerCommand({ + name: 'ob-must', + fn: async ({ args = {} }) => { + if (!args._[0]) { + console.log(chalk.green('replace all Chinese into i18n formatMessage')); + } + const fileType = args.file || 'ts'; // --提取的文件类型,默认 ts, 会同时提取 js, jsx, ts, tsx 文件 + const sourcePath = args.path || 'src'; // 默认提取的文件目录 + const outputPath = api.config.singular ? 'src/locale' : 'src/locales'; // 生成的翻译文件目录,用户不可配 + const { exclude } = args; // 排除文件,支持多个 + + if (!existsSync(sourcePath)) { + console.log(chalk.red('提取源目录不存在!可以使用 -path=xxx 指定提取路径')); + return; + } + + if (!['js', 'ts', 'html', 'vue'].includes(fileType)) { + console.log(chalk.red('指定文件类型错误,支持的类型包括:js, ts, html 和 vue')); + return; + } + + const { name: pkgName, version } = require(join(api.cwd, 'package.json')); + + const JSX_OPTIONS = { + cwd: api.cwd, + name: pkgName, + sourcePath: sourcePath, // 源文件地址 + fileType, // 提取类型, 会同时读取文件后缀为 js|jsx|ts|tsx 的文件 + // 需要手动开启,才会上传到美杜莎 + isNeedUploadCopyToMedusa: true, + // 上传到美杜莎 + medusa: { + // 美杜莎上对应的应用名 + appName: 'ocp-express', + // 将当前的 OCP 版本作为提取文案的 tag,便于翻译同学识别 + tag: version, + exportType: 'upload', + }, + exclude: (path: string) => { + // 支持以逗号分隔的多个排除文件 + const excludeList = exclude?.split(',') || []; + return ( + // 不处理 .umi 下的文件 + path.includes('src/.umi') || + path.includes('src/locale') || + excludeList.some(item => path.includes(item)) + ); + }, + matchCopy: matchText, + macro: { + path: outputPath, + method: `formatMessage({id: '$key$', defaultMessage:"$defaultMessage$"})`, + // TODO: 可能切换有问题,从插件件兼容掉 + import: "import { formatMessage } from '@/util/intl'", + // 自定义文案 key 的生成: 默认逻辑可能会生成跨组件重复的 key,导致文案出现混乱 + keyGenerator: (copy, filePath, config) => { + const enCopy = copy['en-US']; + // key 分隔符 + const keySplitter = '.'; + // generate world part + const words = enCopy.split(/[^a-zA-Z]/i); + const namedWords = words + .filter(w => /^[\w|\d]+$/i.test(w)) + .map(w => w.toLowerCase().replace(/(?:^|\s)\S/g, a => a.toUpperCase())); + + if (namedWords.length === 0) { + return ''; + } + + // generate path part + const { name } = config; + const isWin = process.platform === 'win32'; + const splitter = isWin ? '\\' : '/'; + const relativeFilePath = toRelativePath(filePath, config.cwd, splitter); + const parsedPath = parse(relativeFilePath); + const dirPart = parsedPath.dir + .split(splitter) + // get the last two + .slice(-2) + .filter(p => !!p); + + let keyArray = [name]; + keyArray = keyArray.concat(dirPart); + + if (parsedPath.name && parsedPath.name !== 'index') keyArray.push(parsedPath.name); + const filePathKey = keyArray.join(keySplitter); + + return `${filePathKey}${keySplitter}${namedWords.slice(0, 8).join('')}`; + }, + }, + }; + + // 实现初版,通过时候拼接文件实现 增量 + 兼容旧版国际化 + // 后续优化可以在 must 中进行这些操作 + (async () => { + let extract; + try { + extract = require(resolveCwd('@ali/parrot-tool-must')).extract; + } catch (e) { + console.error( + chalk.red(` +需要手动安装 @ali/parrot-tool-must 依赖,请先执行以下安装命令: + + tnpm i @ali/parrot-tool-must -D + +`) + ); + process.exit(1); + } + console.log(chalk.cyan(chalk.bold('推荐先提交 git 修改记录再进行提取'))); + // 执行提取操作 + await extract.run( + JSX_OPTIONS, + // 关闭二次确认,直接进行提取和上传到美杜莎 + true + ); + + let zh_CN_source = ''; + let en_US_source = ''; + try { + // 这里处理有问题,待修复 + zh_CN_source = getContent( + JSON.stringify(require(join(api.cwd, outputPath, 'strings', 'zh-CN.json')), null, 2) + ); + en_US_source = getContent( + JSON.stringify(require(join(api.cwd, outputPath, 'strings', 'en-US.json')), null, 2) + ); + } catch { + console.log(chalk.red('没有进行任何文案替换')); + rimraf.sync(join(api.cwd, outputPath, 'strings')); + // 尝试删除 生成的 index.js + try { + unlinkSync(join(api.cwd, outputPath, fileType === 'js' ? 'index.js' : 'index.ts')); + } catch { } + return; + } + + let zh_CN; + let en_US; + try { + zh_CN = getContent( + readFileSync(join(api.cwd, outputPath, 'zh-CN.js'), { + encoding: 'utf8', + }) + ); + } catch { + zh_CN = ''; + } + try { + en_US = getContent( + readFileSync(join(api.cwd, outputPath, 'en-US.js'), { + encoding: 'utf8', + }) + ); + } catch { + en_US = ''; + } + + if (!zh_CN && !en_US) { + // 全量复制翻译 + zh_CN = `export default {${zh_CN_source}}`; + en_US = `export default {${en_US_source}}`; + } else { + // 增量插入翻译 + zh_CN = `export default {${zh_CN + ', //' + new Date().toLocaleString() + ' 新增文案' + zh_CN_source + }}`; + en_US = `export default {${en_US + ', //' + new Date().toLocaleString() + ' 新增文案' + en_US_source + }}`; + } + + try { + writeFileSync(join(api.cwd, outputPath, 'zh-CN.js'), zh_CN); + writeFileSync(join(api.cwd, outputPath, 'en-US.js'), en_US); + } catch (e) { + console.log(chalk.red('写入翻译文件失败')); + } + + // 尝试删除 生成的 index.js 或 index.ts + try { + rimraf.sync(join(api.cwd, outputPath, 'strings')); + unlinkSync(join(api.cwd, outputPath, fileType === 'js' ? 'index.js' : 'index.ts')); + } catch { + console.log(chalk.red('清理临时文件失败')); + } + + if (!api.userConfig.locale) { + console.log( + chalk.red( + [ + '检测到项目还没有开启国际化配置', + '运行前请先在配置中添加', + chalk.cyan(' locale: {}'), + ].join(EOL) + ) + ); + return; + } + })(); + }, + }); +}; diff --git a/frontend/config/routes.ts b/frontend/config/routes.ts new file mode 100644 index 00000000..caf9fb23 --- /dev/null +++ b/frontend/config/routes.ts @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default [ + { + path: '/', + component: 'Layout', + name: '系统布局', + spmb: 'b55539', + routes: [ + { + path: 'login', + component: 'Login', + name: '登录页', + spmb: 'b55540', + }, + { + path: 'tenant/result/:taskId', + component: 'Tenant/Result/Success', + name: '新建租户任务提交成功', + spmb: 'b55555', + }, + { + path: 'tenant/new', + component: 'Tenant/New', + name: '新建租户', + spmb: 'b55554', + }, + { + // 单个租户管理 + path: 'tenant/:tenantName', + component: 'Tenant/Detail', + routes: [ + { + path: '/tenant/:tenantName', + redirect: 'overview', + }, + { + path: 'overview', + component: 'Tenant/Detail/Overview', + name: '租户详情', + spmb: 'b55541', + }, + { + path: 'monitor', + component: 'Tenant/Detail/Monitor', + name: '租户性能监控', + spmb: 'b55575', + }, + { + path: 'database', + component: 'Tenant/Detail/Database', + name: '租户数据库', + spmb: 'b55542', + }, + { + path: 'user', + component: 'Tenant/Detail/User', + name: '租户用户', + spmb: 'b55543', + }, + { + path: 'user/role', + component: 'Tenant/Detail/User', + name: 'Oracle 租户角色', + spmb: 'b55544', + }, + { + path: 'user/:username', + component: 'Tenant/Detail/User/Oracle/UserOrRoleDetail', + name: 'Oracle 租户用户详情', + spmb: 'b55545', + }, + { + path: 'user/role/:roleName', + component: 'Tenant/Detail/User/Oracle/UserOrRoleDetail', + name: 'Oracle 租户角色详情', + spmb: 'b55546', + }, + { + path: 'parameter', + component: 'Tenant/Detail/Parameter', + name: '租户参数', + spmb: 'b55547', + }, + ], + }, + { + path: '/', + component: 'Layout/BasicLayout', + routes: [ + { + path: '/', + redirect: '/overview', + }, + { + path: 'overview', + component: 'Cluster/Overview', + name: '集群详情', + spmb: 'b55548', + }, + { + path: 'overview/server/:ip/:serverPort', + component: 'Cluster/Host', + name: 'OBServer 详情', + spmb: 'b55549', + }, + { + path: 'overview/unit', + component: 'Cluster/Unit', + name: 'Unit 分布', + spmb: 'b55550', + }, + { + path: 'overview/parameter', + component: 'Cluster/Parameter', + name: '参数管理', + spmb: 'b55551', + }, + { + path: 'tenant', + component: 'Tenant', + name: '租户列表', + spmb: 'b55552', + }, + { + path: 'monitor', + component: 'Monitor', + name: '集群监控', + spmb: 'b55553', + ignoreMergeRoute: true, + queryTitle: 'scope', + }, + // 创建租户改为异步任务 结果页 + { + path: 'diagnosis/session', + component: 'Diagnosis/Session', + name: '会话诊断', + spmb: 'b55576', + ignoreMergeRoute: true, + queryTitle: 'tab', + }, + { + path: 'diagnosis/sql', + component: 'Diagnosis/SQLDiagnosis', + name: 'SQL 诊断', + spmb: 'b55577', + ignoreMergeRoute: true, + queryTitle: 'tab', + }, + { + path: 'task', + component: 'Task', + name: '任务中心', + spmb: 'b55556', + }, + { + path: 'task/:taskId', + component: 'Task/Detail', + name: '任务详情', + spmb: 'b55557', + }, + { + path: 'package', + component: 'Package', + name: '软件包管理', + }, + { + path: 'property', + component: 'Property', + name: '系统配置', + spmb: 'b55558', + }, + { + path: 'log', + component: 'Log', + name: '日志服务', + spmb: 'b55559', + }, + { + path: 'error', + name: '错误页', + spmb: 'b55560', + routes: [ + { + path: '/error', + redirect: '/error/404', + }, + { + path: '403', + component: 'Error/403', + name: '403 错误', + spmb: 'b55561', + }, + { + path: '404', + component: 'Error/404', + name: '404 错误', + spmb: 'b55562', + }, + ], + }, + ], + }, + { + // 前面的路径都没有匹配到,说明是 404 页面 + // 使用 Error/404 覆盖默认的 404 路径 + component: 'Error/404', + name: '404 页面不存在', + spmb: 'b55563', + }, + ], + }, +]; diff --git a/frontend/frontend.go b/frontend/frontend.go new file mode 100644 index 00000000..314f58f9 --- /dev/null +++ b/frontend/frontend.go @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package frontend + +import ( + "embed" +) + +//go:embed dist/* +var Dist embed.FS diff --git a/frontend/jest.config.js b/frontend/jest.config.js new file mode 100644 index 00000000..6779d9cc --- /dev/null +++ b/frontend/jest.config.js @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +module.exports = { + moduleNameMapper: { + '^@/(.*)': '/src/$1', + '^@@/(.*)': '/src/.umi/$1', + // 以下配置项有先后顺序,匹配路径越准确的越需要放前面 + umi: '/node_modules/umi-request', + 'umi/(.*)': '/node_modules/$1', + 'umi/icons': '/src/.umi/plugin-icons/icons.tsx', + 'umi/(.*)$': '/node_modules/$1', + }, + setupFiles: ['/test/mock-util-intl.js'], +}; diff --git a/frontend/openapi2ts.config.ts b/frontend/openapi2ts.config.ts new file mode 100644 index 00000000..ed53297c --- /dev/null +++ b/frontend/openapi2ts.config.ts @@ -0,0 +1,9 @@ +const path = require('path'); + +export default { + // schemaPath: path.join('http://11.161.204.53:2886/', '/swagger/doc.json'), + schemaPath: path.join('http://11.161.204.49:30871/', '/swagger/doc.json'), + serversPath: './src/service', + requestLibPath: '@/util/request', + projectName: 'obshell', +}; diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 00000000..eaa34a63 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,117 @@ +{ + "name": "ocp-express", + "version": "1.0.0", + "private": true, + "repository": "git@gitlab.alipay-inc.com:oceanbase/ocp-express.git", + "scripts": { + "analyze": "ANALYZE=1 umi dev", + "build": "NODE_OPTIONS=--max_old_space_size=4096 umi build", + "build:tester": "UMI_ENV=tester NODE_OPTIONS=--max_old_space_size=8192 umi build", + "cov": "umi test --coverage", + "dev": "NODE_OPTIONS=--max_old_space_size=8192 UMI_UI=none umi dev", + "devs": "NODE_OPTIONS=--max_old_space_size=8192 UMI_UI=none MOCK=none umi dev", + "devs:tester": "UMI_ENV=tester NODE_OPTIONS=--max_old_space_size=8192 UMI_UI=none MOCK=none umi dev", + "help": "umi help", + "lint": "NODE_OPTIONS=--max_old_space_size=4096 umi lint --style --eslint.ext='.ts,.tsx,.jsx,.js'", + "lint:fix": "NODE_OPTIONS=--max_old_space_size=4096 umi lint --style --eslint.ext='.ts,.tsx,.jsx,.js' --fix", + "locale:unuseful": "babel-node --presets es2015 ./script/unuseful-locale-key.js", + "must": "NODE_OPTIONS=--max_old_space_size=4096 umi ob-must --exclude=constant/must-ignore.ts,src/global.ts", + "openapi2ts": "openapi2ts", + "pack": "umi pack", + "prettier": "prettier --write './src/**/*.{js,jsx,ts,tsx}'", + "test": "umi test", + "version": "umi -v" + }, + "lint-staged": { + "*.{js,jsx}": [ + "prettier --write" + ], + "*.ts?(x)": [ + "prettier --parser=typescript --write" + ] + }, + "dependencies": { + "@ahooksjs/use-url-state": "^3.5.1", + "@ant-design/compatible": "^1.1.2", + "@ant-design/pro-components": "^2.8.7", + "@antv/dom-util": "^2.0.4", + "@antv/g-svg": "^0.5.7", + "@antv/g6": "3.4.10", + "@oceanbase/charts": "^0.4.5", + "@oceanbase/design": "^0.4.10", + "@oceanbase/icons": "^0.4.6", + "@oceanbase/ui": "^0.4.13", + "@oceanbase/util": "^0.4.2", + "@sentry/react": "^7.120.3", + "@sentry/tracing": "^7.120.3", + "@umijs/plugin-openapi": "^1.3.3", + "@umijs/preset-react": "~1.8.32", + "ahooks": "^3.8.4", + "antd": "^5.24.8", + "antd-style": "^3.7.1", + "bignumber.js": "^9.3.0", + "classnames": "^2.5.1", + "crypto-js": "^4.2.0", + "crypto-random-string": "^5.0.0", + "file-saver": "^2.0.5", + "js-base64": "^3.7.7", + "js-cookie": "^2.2.1", + "jsencrypt-ext": "^2.1.2", + "lodash": "^4.17.21", + "moment": "^2.30.1", + "prism": "^4.1.2", + "prism-react-renderer": "^1.3.5", + "query-string": "^8.2.0", + "react-beautiful-dnd": "^12.2.0", + "react-intl": "3.12.1", + "react-scripts": "^5.0.1", + "react-split-pane": "^0.1.92", + "react-sticky-mouse-tooltip": "0.0.1", + "scroll-into-view": "^1.16.2", + "sql-formatter": "^2.3.4", + "umi": "^3.5.43", + "umi-request": "^1.4.0", + "use-deep-compare-effect": "^1.8.1", + "validator": "^13.15.0", + "xlsx": "^0.17.5" + }, + "devDependencies": { + "@ant-design/moment-webpack-plugin": "^0.0.3", + "@chenshuai2144/less2cssinjs": "^1.0.7", + "@types/crypto-js": "^4.2.2", + "@types/lodash": "^4.17.16", + "@types/react": "17.0.52", + "@types/react-dom": "17.0.2", + "@types/scroll-into-view": "^1.16.4", + "@types/sql-formatter": "^2.3.0", + "@types/validator": "^12.0.1", + "@umijs/openapi": "^1.13.0", + "@umijs/test": "^3.5.43", + "axios": "^0.30.0", + "babel-cli": "^6.26.0", + "babel-preset-es2015": "^6.24.1", + "dotenv": "^16.5.0", + "eslint": "^9.25.1", + "eslint-plugin-react-hooks": "^4.6.2", + "fs-extra": "^10.1.0", + "html-webpack-plugin": "^4.5.2", + "lint-staged": "^10.5.4", + "mini-css-extract-plugin": "^1.6.2", + "mockjs": "^1.1.0", + "prettier": "^2.8.8", + "runscript": "^1.6.0", + "script-ext-html-webpack-plugin": "^2.1.5", + "style-ext-html-webpack-plugin": "^4.1.3", + "typescript": "^4.9.5", + "yorkie": "^2.0.0" + }, + "engines": { + "install-node": "v16.14.0" + }, + "ci": { + "type": "aci" + }, + "gitHooks": { + "pre-commit": "lint-staged" + } +} diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml new file mode 100644 index 00000000..daeec015 --- /dev/null +++ b/frontend/pnpm-lock.yaml @@ -0,0 +1,25329 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@ahooksjs/use-url-state': + specifier: ^3.5.1 + version: 3.5.1(react-router@5.2.0(react@16.14.0))(react@16.14.0) + '@ant-design/compatible': + specifier: ^1.1.2 + version: 1.1.2(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(prop-types@15.8.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-components': + specifier: ^2.8.7 + version: 2.8.7(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(rc-field-form@2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@antv/dom-util': + specifier: ^2.0.4 + version: 2.0.4 + '@antv/g-svg': + specifier: ^0.5.7 + version: 0.5.7 + '@antv/g6': + specifier: 3.4.10 + version: 3.4.10 + '@oceanbase/charts': + specifier: ^0.4.5 + version: 0.4.5(@ant-design/icons@5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(reflect-metadata@0.1.14) + '@oceanbase/design': + specifier: ^0.4.10 + version: 0.4.10(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@oceanbase/icons': + specifier: ^0.4.6 + version: 0.4.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@oceanbase/ui': + specifier: ^0.4.13 + version: 0.4.13(@types/react@17.0.52)(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(date-fns@2.30.0)(encoding@0.1.13)(rc-field-form@2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@oceanbase/util': + specifier: ^0.4.2 + version: 0.4.2(react@16.14.0) + '@sentry/react': + specifier: ^7.120.3 + version: 7.120.3(react@16.14.0) + '@sentry/tracing': + specifier: ^7.120.3 + version: 7.120.3 + '@umijs/plugin-openapi': + specifier: ^1.3.3 + version: 1.3.3(chokidar@3.6.0)(encoding@0.1.13)(typescript@4.9.5)(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + '@umijs/preset-react': + specifier: ~1.8.32 + version: 1.8.32(@ant-design/icons@5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@ant-design/pro-layout@7.22.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(dva-core@2.0.4(redux@4.2.1))(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0)(redbox-react@1.6.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5))(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + ahooks: + specifier: ^3.8.4 + version: 3.8.4(react@16.14.0) + antd: + specifier: ^5.24.8 + version: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + antd-style: + specifier: ^3.7.1 + version: 3.7.1(@types/react@17.0.52)(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + bignumber.js: + specifier: ^9.3.0 + version: 9.3.0 + classnames: + specifier: ^2.5.1 + version: 2.5.1 + crypto-js: + specifier: ^4.2.0 + version: 4.2.0 + crypto-random-string: + specifier: ^5.0.0 + version: 5.0.0 + file-saver: + specifier: ^2.0.5 + version: 2.0.5 + js-base64: + specifier: ^3.7.7 + version: 3.7.7 + js-cookie: + specifier: ^2.2.1 + version: 2.2.1 + jsencrypt-ext: + specifier: ^2.1.2 + version: 2.1.2 + lodash: + specifier: ^4.17.21 + version: 4.17.21 + moment: + specifier: ^2.30.1 + version: 2.30.1 + prism: + specifier: ^4.1.2 + version: 4.1.2(react@16.14.0) + prism-react-renderer: + specifier: ^1.3.5 + version: 1.3.5(react@16.14.0) + query-string: + specifier: ^8.2.0 + version: 8.2.0 + react-beautiful-dnd: + specifier: ^12.2.0 + version: 12.2.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react-intl: + specifier: 3.12.1 + version: 3.12.1(react@16.14.0) + react-scripts: + specifier: ^5.0.1 + version: 5.0.1(@babel/plugin-syntax-flow@7.26.0(@babel/core@7.26.10))(@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.10))(@types/babel__core@7.20.5)(@types/webpack@4.41.40)(eslint@9.25.1(jiti@1.21.7))(node-notifier@8.0.2)(react@16.14.0)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5))(type-fest@2.19.0)(typescript@4.9.5) + react-split-pane: + specifier: ^0.1.92 + version: 0.1.92(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react-sticky-mouse-tooltip: + specifier: 0.0.1 + version: 0.0.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + scroll-into-view: + specifier: ^1.16.2 + version: 1.16.2 + sql-formatter: + specifier: ^2.3.4 + version: 2.3.4 + umi: + specifier: ^3.5.43 + version: 3.5.43(react-router@5.2.0(react@16.14.0)) + umi-request: + specifier: ^1.4.0 + version: 1.4.0 + use-deep-compare-effect: + specifier: ^1.8.1 + version: 1.8.1(react@16.14.0) + validator: + specifier: ^13.15.0 + version: 13.15.0 + xlsx: + specifier: ^0.17.5 + version: 0.17.5 + devDependencies: + '@ant-design/moment-webpack-plugin': + specifier: ^0.0.3 + version: 0.0.3 + '@chenshuai2144/less2cssinjs': + specifier: ^1.0.7 + version: 1.0.7(typescript@4.9.5) + '@types/crypto-js': + specifier: ^4.2.2 + version: 4.2.2 + '@types/lodash': + specifier: ^4.17.16 + version: 4.17.16 + '@types/react': + specifier: 17.0.52 + version: 17.0.52 + '@types/react-dom': + specifier: 17.0.2 + version: 17.0.2 + '@types/scroll-into-view': + specifier: ^1.16.4 + version: 1.16.4 + '@types/sql-formatter': + specifier: ^2.3.0 + version: 2.3.0 + '@types/validator': + specifier: ^12.0.1 + version: 12.0.1 + '@umijs/openapi': + specifier: ^1.13.0 + version: 1.13.0(chokidar@3.6.0)(encoding@0.1.13)(typescript@4.9.5) + '@umijs/test': + specifier: ^3.5.43 + version: 3.5.43(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + axios: + specifier: ^0.30.0 + version: 0.30.0 + babel-cli: + specifier: ^6.26.0 + version: 6.26.0 + babel-preset-es2015: + specifier: ^6.24.1 + version: 6.24.1 + dotenv: + specifier: ^16.5.0 + version: 16.5.0 + eslint: + specifier: ^9.25.1 + version: 9.25.1(jiti@1.21.7) + eslint-plugin-react-hooks: + specifier: ^4.6.2 + version: 4.6.2(eslint@9.25.1(jiti@1.21.7)) + fs-extra: + specifier: ^10.1.0 + version: 10.1.0 + html-webpack-plugin: + specifier: ^4.5.2 + version: 4.5.2(webpack@5.99.7) + lint-staged: + specifier: ^10.5.4 + version: 10.5.4 + mini-css-extract-plugin: + specifier: ^1.6.2 + version: 1.6.2(webpack@5.99.7) + mockjs: + specifier: ^1.1.0 + version: 1.1.0 + prettier: + specifier: ^2.8.8 + version: 2.8.8 + runscript: + specifier: ^1.6.0 + version: 1.6.0 + script-ext-html-webpack-plugin: + specifier: ^2.1.5 + version: 2.1.5(html-webpack-plugin@4.5.2(webpack@5.99.7))(webpack@5.99.7) + style-ext-html-webpack-plugin: + specifier: ^4.1.3 + version: 4.1.3 + typescript: + specifier: ^4.9.5 + version: 4.9.5 + yorkie: + specifier: ^2.0.0 + version: 2.0.0 + +packages: + + '@ahooksjs/use-request@2.8.15': + resolution: {integrity: sha512-xhVaM4fyIiAMdVFuuU5i3CFUdFa/IblF+fvITVMFaUEO3w/V5tVCAF6WIA3T03n1/RPuzRkA7Ao1PFtSGtGelw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 + + '@ahooksjs/use-url-state@3.5.1': + resolution: {integrity: sha512-XTrOLZKOAXahDD1Evg+aSN6qNzoh/FuvRKbUtB/0RhYvz57tyXRPbED0KXK4h2C3ZyHUKBJcVCSDcd6EsTyMyQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-router: ^5.0.0 || ^6.0.0 + + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + + '@amap/amap-jsapi-loader@1.0.1': + resolution: {integrity: sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw==} + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@ant-design/charts@1.4.3': + resolution: {integrity: sha512-Y0CJYtug+2Bjl2zvuehE39sxBITxWI49VnLl/O7olD+bwkXeY2QEDjB457dBIn+XIHizCWyWBW+wDIECvfFahw==} + peerDependencies: + '@ant-design/icons': ^4.6.0 + antd: ^4.6.3 + lodash: ^4.17.20 + react: '>=16.8.4' + react-dom: '>=16.8.4' + + '@ant-design/colors@4.0.5': + resolution: {integrity: sha512-3mnuX2prnWOWvpFTS2WH2LoouWlOgtnIpc6IarWN6GOzzLF8dW/U8UctuvIPhoboETehZfJ61XP+CGakBEPJ3Q==} + + '@ant-design/colors@6.0.0': + resolution: {integrity: sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==} + + '@ant-design/colors@7.2.0': + resolution: {integrity: sha512-bjTObSnZ9C/O8MB/B4OUtd/q9COomuJAR2SYfhxLyHvCKn4EKwCN3e+fWGMo7H5InAyV0wL17jdE9ALrdOW/6A==} + + '@ant-design/compatible@1.1.2': + resolution: {integrity: sha512-Qsx5Qw97eiSgcxyQDlY45QSbvGn0gUdpX8XFImPvzZpKwabqQ2HnXXuUlb8RbrkURswaPIoyLEGKDPeogIaURA==} + peerDependencies: + antd: 3.x + react: '>=16.0.0' + react-dom: '>=16.0.0' + + '@ant-design/cssinjs-utils@1.1.3': + resolution: {integrity: sha512-nOoQMLW1l+xR1Co8NFVYiP8pZp3VjIIzqV6D6ShYF2ljtdwWJn5WSsH+7kvCktXL/yhEtWURKOfH5Xz/gzlwsg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@ant-design/cssinjs@1.23.0': + resolution: {integrity: sha512-7GAg9bD/iC9ikWatU9ym+P9ugJhi/WbsTWzcKN6T4gU0aehsprtke1UAaaSxxkjjmkJb3llet/rbUSLPgwlY4w==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + + '@ant-design/fast-color@2.0.6': + resolution: {integrity: sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==} + engines: {node: '>=8.x'} + + '@ant-design/flowchart@1.2.2': + resolution: {integrity: sha512-bzHZ81qqHjWIrXcCMInDB6eMTzbswaVCOAdUTCQJ+B45aybkVsU9LMCKquyOwRM7U7PWNfPC9S/lAlx2i2BvBQ==} + peerDependencies: + '@ant-design/icons': ^4.6.0 + antd: ^4.6.3 + lodash: ^4.17.20 + react: '>=16.8.4' + react-dom: '>=16.8.4' + + '@ant-design/graphs@1.4.1': + resolution: {integrity: sha512-Qyj7Lnfo0gmbaMzm+9AdrS3fjkg2sFU/ZKaFl7xhgEf5LnX+N/KffIvoT8FsBmrZ9ni3onwlHs1dtYa5QdVhtQ==} + peerDependencies: + react: '>=16.8.4' + react-dom: '>=16.8.4' + + '@ant-design/icons-svg@4.4.2': + resolution: {integrity: sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==} + + '@ant-design/icons@4.8.3': + resolution: {integrity: sha512-HGlIQZzrEbAhpJR6+IGdzfbPym94Owr6JZkJ2QCCnOkPVIWMO2xgIVcOKnl8YcpijIo39V7l2qQL5fmtw56cMw==} + engines: {node: '>=8'} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + + '@ant-design/icons@5.6.1': + resolution: {integrity: sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==} + engines: {node: '>=8'} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + + '@ant-design/maps@1.0.8': + resolution: {integrity: sha512-q9Lv14Ekp7j24R9agrTXIINKc1/zslLXfTIWNuoZ0hUq7w1doyEhtLTsuF0n1wcgdKGjAX3wBKQRaVlgz+u8lw==} + peerDependencies: + react: '>=16.8.4' + react-dom: '>=16.8.4' + + '@ant-design/moment-webpack-plugin@0.0.3': + resolution: {integrity: sha512-MLm1FUpg02fP615ShQnCUN9la2E4RylDxKyolkGqAWTIHO4HyGM0A5x71AMALEyP/bC+UEEWBGSQ+D4/8hQ+ww==} + + '@ant-design/plots@1.2.6': + resolution: {integrity: sha512-fFzB9DxRSPQa47S3WypRk4Rh+P8vBUuY/DT+IXgUrlKJtvVZUFnuYfjypX3Q/Pie2PEbI6gmskzXLxVF+3Ztvw==} + peerDependencies: + react: '>=16.8.4' + react-dom: '>=16.8.4' + + '@ant-design/pro-card@2.9.7': + resolution: {integrity: sha512-uDDYowmYH1ldRfG8Mb4QOwcEEz6ptRBQDLO1tkVADCRkdOMwz82xlZneR4uVuFyKcuNmgHzarYNncozBKhFuaA==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + react: '>=17.0.0' + + '@ant-design/pro-components@2.8.7': + resolution: {integrity: sha512-QhibkPsUJryEjI1QmwUn+XCngGHidu0ekvricL6TIEvPgP+AUAca29XutN5+Mmn8Xfja1ca9HFTHTgFoV74Z7Q==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + react: '>=17.0.0' + react-dom: '>=17.0.0' + + '@ant-design/pro-descriptions@2.6.7': + resolution: {integrity: sha512-fgn2d0kDWUODGDWKpgziZuuqPlmIoKxQFJY9Yg4nbaRp8GDDKZeSSqgvW+OxjpYM8dxq31fiz1dZlZnOPoYKpg==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + react: '>=17.0.0' + + '@ant-design/pro-field@3.0.4': + resolution: {integrity: sha512-nJSng/6/pPZFdiFeTtZcBQLNrHg9tIeiKFR1+zzbnQbI3qBOFP9aBZS/+LwkQZcI2G71vrRgz2x5OhHb7AX0wQ==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + react: '>=17.0.0' + + '@ant-design/pro-form@2.31.7': + resolution: {integrity: sha512-0TCtIC/ynbLPoes8sLBFwFbi0tkeNmSU6the2EcyKIKDLfWHDbfkLM1OSFrzv3QD+H8OgFWMkTSOjhMOKSsOBg==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + rc-field-form: '>=1.22.0' + react: '>=17.0.0' + react-dom: '>=17.0.0' + + '@ant-design/pro-layout@7.22.4': + resolution: {integrity: sha512-X2WO4L2itXemX4zhS+0NG+8kXQD5SX9sG+zjx/15BmIO3FvsUGqOHgoCg0vhd424EiyPj7WtdMZJ39G1xdgDwA==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + react: '>=17.0.0' + react-dom: '>=17.0.0' + + '@ant-design/pro-list@2.6.7': + resolution: {integrity: sha512-6k/En7pioMgepho/1HMf2DAnkSTZiat1lDg2ggCok2lhSgqXzir7x22ewJQRgPvEiVb6/qqaFQNd7a8dnrFj1w==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + react: '>=17.0.0' + react-dom: '>=17.0.0' + + '@ant-design/pro-provider@2.15.4': + resolution: {integrity: sha512-DBX0JNUNOYXAucVqd/zTdqtXckCDqr2Lo85KIku2YzWdhptDPDZRTNqL04JShjGejDl8fzwQ8yREHgVUfzn6Gg==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + react: '>=17.0.0' + react-dom: '>=17.0.0' + + '@ant-design/pro-skeleton@2.2.1': + resolution: {integrity: sha512-3M2jNOZQZWEDR8pheY00OkHREfb0rquvFZLCa6DypGmiksiuuYuR9Y4iA82ZF+mva2FmpHekdwbje/GpbxqBeg==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + react: '>=17.0.0' + react-dom: '>=17.0.0' + + '@ant-design/pro-table@3.19.0': + resolution: {integrity: sha512-nL25734d5q5oqtmG7Apn2TNJUnJE8m9dkopXMQdoNZnv8qeRQLBH+i5cZT1yh7FIO8z6QLXleg+KnR/cI7VRRw==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + rc-field-form: '>=1.22.0' + react: '>=17.0.0' + react-dom: '>=17.0.0' + + '@ant-design/pro-utils@2.17.0': + resolution: {integrity: sha512-hHKUISjMEoS+E5ltJWyvNTrlEA3IimZNxtDrEhorRIbgVYAlmEN5Mj/ESSofzDM3+UlxiI5+A/Y6IHkByTfDEA==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + react: '>=17.0.0' + react-dom: '>=17.0.0' + + '@ant-design/react-slick@1.0.2': + resolution: {integrity: sha512-Wj8onxL/T8KQLFFiCA4t8eIRGpRR+UPgOdac2sYzonv+i0n3kXHmvHLLiOYL655DQx2Umii9Y9nNgL7ssu5haQ==} + peerDependencies: + react: '>=16.9.0' + + '@ant-design/react-slick@1.1.2': + resolution: {integrity: sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==} + peerDependencies: + react: '>=16.9.0' + + '@antv/adjust@0.2.5': + resolution: {integrity: sha512-MfWZOkD9CqXRES6MBGRNe27Q577a72EIwyMnE29wIlPliFvJfWwsrONddpGU7lilMpVKecS3WAzOoip3RfPTRQ==} + + '@antv/algorithm@0.1.26': + resolution: {integrity: sha512-DVhcFSQ8YQnMNW34Mk8BSsfc61iC1sAnmcfYoXTAshYHuU50p/6b7x3QYaGctDNKWGvi1ub7mPcSY0bK+aN0qg==} + + '@antv/async-hook@2.2.9': + resolution: {integrity: sha512-4BUp2ZUaTi2fYL67Ltkf6eV912rYJeSBokGhd5fhhnpUkMA1LEI1mg97Pqmx3yC50VEQ+LKXZxj9ePZs80ECfw==} + + '@antv/attr@0.3.5': + resolution: {integrity: sha512-wuj2gUo6C8Q2ASSMrVBuTcb5LcV+Tc0Egiy6bC42D0vxcQ+ta13CLxgMmHz8mjD0FxTPJDXSciyszRSC5TdLsg==} + + '@antv/color-util@2.0.6': + resolution: {integrity: sha512-KnPEaAH+XNJMjax9U35W67nzPI+QQ2x27pYlzmSIWrbj4/k8PGrARXfzDTjwoozHJY8qG62Z+Ww6Alhu2FctXQ==} + + '@antv/component@0.8.35': + resolution: {integrity: sha512-VnRa5X77nBPI952o2xePEEMSNZ6g2mcUDrQY8mVL2kino/8TFhqDq5fTRmDXZyWyIYd4ulJTz5zgeSwAnX/INQ==} + + '@antv/coord@0.3.1': + resolution: {integrity: sha512-rFE94C8Xzbx4xmZnHh2AnlB3Qm1n5x0VT3OROy257IH6Rm4cuzv1+tZaUBATviwZd99S+rOY9telw/+6C9GbRw==} + + '@antv/dom-util@2.0.4': + resolution: {integrity: sha512-2shXUl504fKwt82T3GkuT4Uoc6p9qjCKnJ8gXGLSW4T1W37dqf9AV28aCfoVPHp2BUXpSsB+PAJX2rG/jLHsLQ==} + + '@antv/event-emitter@0.1.3': + resolution: {integrity: sha512-4ddpsiHN9Pd4UIlWuKVK1C4IiZIdbwQvy9i7DUSI3xNJ89FPUFt8lxDYj8GzzfdllV0NkJTRxnG+FvLk0llidg==} + + '@antv/g-base@0.4.7': + resolution: {integrity: sha512-wKSpS3/M1slU92iOgi2QV4MCd82J1d2PyPcQArqSFRUZU0KnVMIl95v79dG0Be4YvFaZ3bVrT6Ns1Czr8oplhA==} + + '@antv/g-base@0.5.16': + resolution: {integrity: sha512-jP06wggTubDPHXoKwFg3/f1lyxBX9ywwN3E/HG74Nd7DXqOXQis8tsIWW+O6dS/h9vyuXLd1/wDWkMMm3ZzXdg==} + + '@antv/g-canvas@0.4.15': + resolution: {integrity: sha512-+Du37T7dhU1F8GiaWu+EMtBDHoYOg8UzCoVBFD+cUEs/joLaOVkup3drvGC/6MSyLiI32y/ZHuuc08pZIP7PzA==} + + '@antv/g-canvas@0.5.17': + resolution: {integrity: sha512-sXYJMWTOlb/Ycb6sTKu00LcJqInXJY4t99+kSM40u2OfqrXYmaXDjHR7D2V0roMkbK/QWiWS9UnEidCR1VtMOA==} + + '@antv/g-device-api@1.6.13': + resolution: {integrity: sha512-lTvlSHYDZyWJnAR1W8DOQLwUo32VpRopbS/BPQqStcOV6FqaC+u5YjT50KbJ+oBWcorpzfknhICRwEA3Xm8t9Q==} + + '@antv/g-math@0.1.9': + resolution: {integrity: sha512-KHMSfPfZ5XHM1PZnG42Q2gxXfOitYveNTA7L61lR6mhZ8Y/aExsYmHqaKBsSarU0z+6WLrl9C07PQJZaw0uljQ==} + + '@antv/g-svg@0.4.7': + resolution: {integrity: sha512-+lqlBK+qylP4t/vyUgEaPthp1XmTiImfkPl/ZmRp3L1knH64OI9XTfOGGuBUFAt3JBt7VHKf6t0L/MCf0BR88Q==} + + '@antv/g-svg@0.5.7': + resolution: {integrity: sha512-jUbWoPgr4YNsOat2Y/rGAouNQYGpw4R0cvlN0YafwOyacFFYy2zC8RslNd6KkPhhR3XHNSqJOuCYZj/YmLUwYw==} + + '@antv/g-webgpu-core@0.5.6': + resolution: {integrity: sha512-DPiH3GkAUiT0Q+LAKeImpI+IOQ/gP2w6HstYKivpFIpBPIvZ/9equM3icVrn1iDfDkZANVXQ1PppcO3xBv1ZTw==} + + '@antv/g-webgpu-core@0.7.2': + resolution: {integrity: sha512-xUMmop7f3Rs34zFYKXLqHhDR1CQTeDl/7vI7Sn3X/73BqJc3X3HIIRvm83Fg2CjVACaOzw4WeLRXNaOCp9fz9w==} + + '@antv/g-webgpu-engine@0.5.6': + resolution: {integrity: sha512-D311qYUefdEFwLayutIHqucrAY3cAGH3BdnXS37nq+0nsglrHcNP0Ab1YTinn9RihLoY3yXFTLzrYkJHJbZXDg==} + + '@antv/g-webgpu-engine@0.7.2': + resolution: {integrity: sha512-lx8Y93IW2cnJvdoDRKyMmTdYqSC1pOmF0nyG3PGGyA0NI9vBYVgO0KTF6hkyWjdTWVq7XDZyf/h8CJridLh3lg==} + + '@antv/g-webgpu@0.5.5': + resolution: {integrity: sha512-TxtBniINFq1jFGEPo46xjJfrbJbUqkFd5wmsRs3tcg/7J7xoldOP1kEadpI3AJG9knMYdE92VpILw1VPd6DgzQ==} + + '@antv/g-webgpu@0.7.2': + resolution: {integrity: sha512-kw+oYGsdvj5qeUfy5DPb/jztZBV+2fmqBd3Vv8NlKatfBmv8AirYX/CCW74AUSdWm99rEiLyxFB1VdRZ6b/wnQ==} + + '@antv/g2@4.2.11': + resolution: {integrity: sha512-QiqxLLYDWkv9c4oTcXscs6NMxBuWZ1JCarHPZ27J43IN2BV+qUKw8yce0A8CBR8fCILEFqQAfS00Szqpye036Q==} + + '@antv/g2plot@2.4.33': + resolution: {integrity: sha512-f3Fx3IL2nC3jZR2InoY5tSpouA06Lpa7vAHehkFPwmwaSV6gVGfmp08z/LGg6EAaqPP7I58c/UrGZVTD+61qzw==} + + '@antv/g6-core@0.8.24': + resolution: {integrity: sha512-rgI3dArAD8uoSz2+skS4ctN4x/Of33ivTIKaEYYvClxgkLZWVz9zvocy+5AWcVPBHZsAXkZcdh9zndIoWY/33A==} + + '@antv/g6-element@0.8.25': + resolution: {integrity: sha512-bPsI+dS9rdp80O/XyV0iy6QiusyOgO/diCIsGQuLHs6rBqjLtDA5yu9JDo49mPA3JblJV0MYjbgL8Exou7Ecqw==} + peerDependencies: + '@antv/g6': 4.8.25 + + '@antv/g6-pc@0.8.25': + resolution: {integrity: sha512-HZ2QyDbgsUQpQBFqrA8Zcvm/rAKN4n3I7XEeWCODZgyhQ8kz2f3qdzrRXDPmMyclexi0JF9DarCs8a2rzhV5YA==} + + '@antv/g6-plugin@0.8.25': + resolution: {integrity: sha512-TAincRgNzrZNGBt1TvzfQV0Ob6OO3+WCcTrCZb4PzRoOessAiMsNm0S7x+7NFm30DJVC8Ud2M7M2V9DjhVd8Wg==} + peerDependencies: + '@antv/g6': 4.8.25 + + '@antv/g6@3.4.10': + resolution: {integrity: sha512-SsPffvyFpPQ1764XOCkadlIFT7DlX7Y6EBLPD4obU8tXV3udk+yFf+qw4OzgZjN+3/eEYQOZgzVSPRpr8TTkyw==} + + '@antv/g6@4.8.25': + resolution: {integrity: sha512-8mdTnN9QMVNQZtlXmftL8fvRsa4L+GajK58Zp51wyrGLFyjeop8R0QSkCALW45DWP2TaQeZAPtjhQUU/wf5hIg==} + + '@antv/gl-matrix@2.7.1': + resolution: {integrity: sha512-oOWcVNlpELIKi9x+Mm1Vwbz8pXfkbJKykoCIOJ/dNK79hSIANbpXJ5d3Rra9/wZqK6MC961B7sybFhPlLraT3Q==} + + '@antv/graphlib@1.2.0': + resolution: {integrity: sha512-hhJOMThec51nU4Fe5p/viLlNIL71uDEgYFzKPajWjr2715SFG1HAgiP6AVylIeqBcAZ04u3Lw7usjl/TuI5RuQ==} + + '@antv/hierarchy@0.6.14': + resolution: {integrity: sha512-V3uknf7bhynOqQDw2sg+9r9DwZ9pc6k/EcqyTFdfXB1+ydr7urisP0MipIuimucvQKN+Qkd+d6w601r1UIroqQ==} + + '@antv/l7-component@2.22.5': + resolution: {integrity: sha512-rkvz17V2os7VTwD8qP1ooxtiTglTA+KvQq3XTlCKbNujdTH3KQ5hXzJtuZm8ZVE2iRczJVSMeM8FKSKoZM4SQQ==} + + '@antv/l7-core@2.22.5': + resolution: {integrity: sha512-L3iRkjFTmQ4AIQQylhAbV81p9shZyZ4w+3vzDmqm7+vHdFFVprn8eRrUH+o2/li7nYGE5cL8w/GeYvzZhHMlFg==} + + '@antv/l7-layers@2.22.5': + resolution: {integrity: sha512-k++HXple1PmpusUkuEmUAMfxfyARSloMOIqDY7nKfxJBd9rCxkvcsJS+ypHt9Zj29sSvBKvSfLNMOF0yFP+7fQ==} + + '@antv/l7-map@2.22.5': + resolution: {integrity: sha512-EAVZRNHy7zWWLXNnshllqRMIywAgaXIbIDw1VGqVC236VsAqvRaCx8Moy88RG+hU7SPET0+RnQrWK4WYGbR2+A==} + + '@antv/l7-maps@2.22.5': + resolution: {integrity: sha512-HzCRvArZg5u00jDs2H7xQmJxnWDCDrG9dIVHxI2DQBGUr22CtMnY/T4g7plb7uwTzzqtvfferDAF8i4ik/GtuA==} + + '@antv/l7-renderer@2.22.5': + resolution: {integrity: sha512-AEyNC6cq3cPARcOgbrSyQOcobvrm3ibEoBAqpuRsvg2/fc3kp4wsmgESQcfq1efaoS2HElYGUJbIFSWHCWB07Q==} + + '@antv/l7-scene@2.22.5': + resolution: {integrity: sha512-Qd+Ls37Hu68oz9/IFELmq//EXJvHiqef54rp2agwCt/+qsHLheeuLdc5AnL3LcVRGtJ5adrFb/9Hz+3I7FAtnQ==} + + '@antv/l7-source@2.22.5': + resolution: {integrity: sha512-AxplpwJztCJxpulJz8cuiG2zXUvD5fQb97rLNfTcOpCck7gKdSx19QuonYWjyiJC/gHz7EeyYvMjrneFWW5fIw==} + + '@antv/l7-utils@2.22.5': + resolution: {integrity: sha512-A7jItppeAcKOfuizqOf3iXRGePEZCrjw/BlwULgLbgj/dzh03CA2sfAgVWkSce4Jkv6xdCNE/fYOsT8oWw3o5g==} + + '@antv/l7@2.22.5': + resolution: {integrity: sha512-J3paaGznerwSarr88DXJDWwI8zJz8H/nB9kgZJPAm/uu5rj6oPYCtXHlwa+sdGiYImRU60CcS+qc/8HC833NzA==} + + '@antv/l7plot-component@0.0.11': + resolution: {integrity: sha512-aIl9K6I5MwMIU+Xxq/oOKXn0roAg5c73RjCXNmbTu8kxFEUUvCqU/35EDtfhWY7JKJeKnWRcl0fgDmTrD0t4iA==} + + '@antv/l7plot@0.5.11': + resolution: {integrity: sha512-nSHyTzmbvQ8bq4eiD8L5hAPSZxZhmXRZ+j2Zi59iFy8hcR/XxV0N5RN8BkewiL1Zj7IPYXFtkAvBieEznae2UQ==} + peerDependencies: + '@antv/l7': ^2.21.0 + + '@antv/layout@0.1.31': + resolution: {integrity: sha512-iz9i19dOJGiZr5xBWI5sfG+2K3QVMNAGOBrbjWKH2RGLvGpf2TSFySidhz0siDrcQA46cDsjLmGstezQdgeGzA==} + + '@antv/layout@0.3.25': + resolution: {integrity: sha512-d29Aw1PXoAavMRZy7iTB9L5rMBeChFEX0BJ9ELP4TI35ySdCu07YbmPo9ju9OH/6sG2/NB3o85Ayxrre3iwX/g==} + + '@antv/matrix-util@2.0.7': + resolution: {integrity: sha512-bogifQY8jplWtSTZsPqBOdBlDdkM7IwDqYL8eMYL8OaSyOPCS7l9bnEQjQ9qTAwfCd7wHTuPoCnCpbiR8BYFvQ==} + + '@antv/matrix-util@3.0.4': + resolution: {integrity: sha512-BAPyu6dUliHcQ7fm9hZSGKqkwcjEDVLVAstlHULLvcMZvANHeLXgHEgV7JqcAV/GIhIz8aZChIlzM1ZboiXpYQ==} + + '@antv/matrix-util@3.1.0-beta.3': + resolution: {integrity: sha512-W2R6Za3A6CmG51Y/4jZUM/tFgYSq7vTqJL1VD9dKrvwxS4sE0ZcXINtkp55CdyBwJ6Cwm8pfoRpnD4FnHahN0A==} + + '@antv/path-util@2.0.15': + resolution: {integrity: sha512-R2VLZ5C8PLPtr3VciNyxtjKqJ0XlANzpFb5sE9GE61UQqSRuSVSzIakMxjEPrpqbgc+s+y8i+fmc89Snu7qbNw==} + + '@antv/path-util@3.0.1': + resolution: {integrity: sha512-tpvAzMpF9Qm6ik2YSMqICNU5tco5POOW7S4XoxZAI/B0L26adU+Md/SmO0BBo2SpuywKvzPH3hPT3xmoyhr04Q==} + + '@antv/scale@0.3.18': + resolution: {integrity: sha512-GHwE6Lo7S/Q5fgaLPaCsW+CH+3zl4aXpnN1skOiEY0Ue9/u+s2EySv6aDXYkAqs//i0uilMDD/0/4n8caX9U9w==} + + '@antv/util@2.0.17': + resolution: {integrity: sha512-o6I9hi5CIUvLGDhth0RxNSFDRwXeywmt6ExR4+RmVAzIi48ps6HUy+svxOCayvrPBN37uE6TAc2KDofRo0nK9Q==} + + '@antv/util@3.3.10': + resolution: {integrity: sha512-basGML3DFA3O87INnzvDStjzS+n0JLEhRnRsDzP9keiXz8gT1z/fTdmJAZFOzMMWxy+HKbi7NbSt0+8vz/OsBQ==} + + '@antv/x6-react-components@1.1.20': + resolution: {integrity: sha512-HpQqjPCUo+jfcbfW2sr9oxuXMCxWnXxWvE8jXKJzvrlMNZ3kgfxNqMCRxwGi2QTCxLB3g/KYi5/n8kze8ui1/Q==} + peerDependencies: + antd: '>=4.4.2 || >=5.0.0-beta.0' + react: '>=16.8.6 || >=17.0.0' + react-dom: '>=16.8.6 || >=17.0.0' + + '@antv/x6-react-shape@1.6.6': + resolution: {integrity: sha512-+SIvQWeGhfH9miKDQvJT497iVDs/CcMwcgbNKbPV6qTUaSUeXjz/bZy8knbQ5t9XtkVYeQXZP7swiKK2xMI0UQ==} + peerDependencies: + '@antv/x6': ^1.x + react: '>=16.8.6 || >=17.0.0' + react-dom: '>=16.8.6 || >=17.0.0' + + '@antv/x6@1.35.1': + resolution: {integrity: sha512-XLFSGbcT/MOI883YKql9J/CqHUCPZxgwfel+sNN1eQbHA+JXYsGt0t9+IJ1qieaYAlxjgio5up+S9I0n+8QL/A==} + + '@antv/xflow-core@1.1.52': + resolution: {integrity: sha512-62CZeOLMXvDpKOqbq/8zoDt7MUjOkGh9dKBDbxL744UgZCN5Fx4SE+qRhK5purGixTq35XzZ+b9G5wdAX4rLjw==} + peerDependencies: + '@ant-design/icons': ^4.6.0 + '@antv/x6': ^1.30.1 + '@antv/x6-react-components': ^1.1.15 + '@antv/x6-react-shape': ^1.2.5 + antd: ^4.6.3 + lodash: ^4.17.20 + react: ^16.8.0 || ^17.0.0 + react-dom: ^16.8.0 || ^17.0.0 + + '@antv/xflow-extension@1.1.52': + resolution: {integrity: sha512-pPpx00xwucAkl5+QyxxWiOaRpKGnu0Z1+IDUEYuDvEKxms7+Ml0nDc4+CnDi1e1wr4hB3QgxgLOb0JpUTgBCfg==} + peerDependencies: + '@ant-design/icons': ^4.6.0 + '@antv/x6': ^1.30.1 + '@antv/x6-react-components': ^1.1.15 + '@antv/x6-react-shape': ^1.2.5 + antd: ^4.6.3 + classnames: ^2.2.6 + react: ^16.8.0 || ^17.0.0 + react-dom: ^16.8.0 || ^17.0.0 + reflect-metadata: ^0.1.13 + + '@antv/xflow-hook@1.0.52': + resolution: {integrity: sha512-qyheVO5bwhDjKGSldf3pkneowf8ZCydIIrX4n8LRTFpvVhVF9cPoXG9e6+1LhIFvSEaLAJcYBH4gNqAjRrbUYw==} + + '@antv/xflow-hook@1.1.52': + resolution: {integrity: sha512-wQfJgCxZG/PYH4DhpcfOi8Js0gHlVmTMHYVJ4DZMvGPcuhEhic0vOtyd9cie0YPzWPufw6lBKtn3/0FY3yHapg==} + + '@antv/xflow@1.1.52': + resolution: {integrity: sha512-B2IApV4vG2DmMubbfXGjE+oKi2eXvPuijdHhbxwQheIWcm+VtVQscaFvwUexb4CHH5tBSnjtUeKrhRIkXop70w==} + peerDependencies: + '@ant-design/icons': ^4.6.0 + antd: ^4.6.3 + lodash: ^4.17.20 + react: ^16.8.0 || ^17.0.0 + react-dom: ^16.8.0 || ^17.0.0 + + '@apideck/better-ajv-errors@0.3.6': + resolution: {integrity: sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==} + engines: {node: '>=10'} + peerDependencies: + ajv: '>=8' + + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.26.8': + resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.18.6': + resolution: {integrity: sha512-cQbWBpxcbbs/IUredIPkHiAGULLV8iwgNRMFzvbhEXISp4f3rUUXE5+TIw6KwUWUR3DwyI6gmBRnmAtYaWehwQ==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.26.10': + resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==} + engines: {node: '>=6.9.0'} + + '@babel/eslint-parser@7.27.0': + resolution: {integrity: sha512-dtnzmSjXfgL/HDgMcmsLSzyGbEosi4DrGWoCNfuI+W4IkVJw6izpTe7LtOdwAXnkDqw5yweboYCTkM2rQizCng==} + engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} + peerDependencies: + '@babel/core': ^7.11.0 + eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 + + '@babel/generator@7.27.0': + resolution: {integrity: sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.25.9': + resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.27.0': + resolution: {integrity: sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.27.0': + resolution: {integrity: sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-create-regexp-features-plugin@7.27.0': + resolution: {integrity: sha512-fO8l08T76v48BhpNRW/nQ0MxfnSdoSKUJBMjubOAYffsVuGG5qOfMq7N6Es7UJvi7Y8goXXo07EfcHZXDPuELQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-define-polyfill-provider@0.6.4': + resolution: {integrity: sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + '@babel/helper-member-expression-to-functions@7.25.9': + resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.25.9': + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.26.0': + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.25.9': + resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.26.5': + resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-remap-async-to-generator@7.25.9': + resolution: {integrity: sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-replace-supers@7.26.5': + resolution: {integrity: sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.25.9': + resolution: {integrity: sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.25.9': + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.25.9': + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-wrap-function@7.25.9': + resolution: {integrity: sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.27.0': + resolution: {integrity: sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.27.0': + resolution: {integrity: sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9': + resolution: {integrity: sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9': + resolution: {integrity: sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9': + resolution: {integrity: sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9': + resolution: {integrity: sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9': + resolution: {integrity: sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-proposal-class-properties@7.18.6': + resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-decorators@7.25.9': + resolution: {integrity: sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-nullish-coalescing-operator@7.18.6': + resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-numeric-separator@7.18.6': + resolution: {integrity: sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-optional-chaining@7.21.0': + resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-private-methods@7.18.6': + resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': + resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-private-property-in-object@7.21.11': + resolution: {integrity: sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-async-generators@7.8.4': + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-bigint@7.8.3': + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-properties@7.12.13': + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-static-block@7.14.5': + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-decorators@7.25.9': + resolution: {integrity: sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-flow@7.26.0': + resolution: {integrity: sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-assertions@7.26.0': + resolution: {integrity: sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.26.0': + resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-json-strings@7.8.3': + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.25.9': + resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-numeric-separator@7.10.4': + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-object-rest-spread@7.8.3': + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3': + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-private-property-in-object@7.14.5': + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-top-level-await@7.14.5': + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.25.9': + resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6': + resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-arrow-functions@7.25.9': + resolution: {integrity: sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-generator-functions@7.26.8': + resolution: {integrity: sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-to-generator@7.25.9': + resolution: {integrity: sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoped-functions@7.26.5': + resolution: {integrity: sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoping@7.27.0': + resolution: {integrity: sha512-u1jGphZ8uDI2Pj/HJj6YQ6XQLZCNjOlprjxB5SVz6rq2T6SwAR+CdrWK0CP7F+9rDVMXdB0+r6Am5G5aobOjAQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-properties@7.25.9': + resolution: {integrity: sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-static-block@7.26.0': + resolution: {integrity: sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + + '@babel/plugin-transform-classes@7.25.9': + resolution: {integrity: sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-computed-properties@7.25.9': + resolution: {integrity: sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-destructuring@7.25.9': + resolution: {integrity: sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-dotall-regex@7.25.9': + resolution: {integrity: sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-keys@7.25.9': + resolution: {integrity: sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9': + resolution: {integrity: sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-dynamic-import@7.25.9': + resolution: {integrity: sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-exponentiation-operator@7.26.3': + resolution: {integrity: sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-export-namespace-from@7.25.9': + resolution: {integrity: sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-flow-strip-types@7.26.5': + resolution: {integrity: sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-for-of@7.26.9': + resolution: {integrity: sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-function-name@7.25.9': + resolution: {integrity: sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-json-strings@7.25.9': + resolution: {integrity: sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-literals@7.25.9': + resolution: {integrity: sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-logical-assignment-operators@7.25.9': + resolution: {integrity: sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-member-expression-literals@7.25.9': + resolution: {integrity: sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-amd@7.25.9': + resolution: {integrity: sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-commonjs@7.26.3': + resolution: {integrity: sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-systemjs@7.25.9': + resolution: {integrity: sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-umd@7.25.9': + resolution: {integrity: sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-named-capturing-groups-regex@7.25.9': + resolution: {integrity: sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-new-target@7.25.9': + resolution: {integrity: sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-nullish-coalescing-operator@7.26.6': + resolution: {integrity: sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-numeric-separator@7.25.9': + resolution: {integrity: sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-rest-spread@7.25.9': + resolution: {integrity: sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-super@7.25.9': + resolution: {integrity: sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-catch-binding@7.25.9': + resolution: {integrity: sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-chaining@7.25.9': + resolution: {integrity: sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-parameters@7.25.9': + resolution: {integrity: sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-methods@7.25.9': + resolution: {integrity: sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-property-in-object@7.25.9': + resolution: {integrity: sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-property-literals@7.25.9': + resolution: {integrity: sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-constant-elements@7.25.9': + resolution: {integrity: sha512-Ncw2JFsJVuvfRsa2lSHiC55kETQVLSnsYGQ1JDDwkUeWGTL/8Tom8aLTnlqgoeuopWrbbGndrc9AlLYrIosrow==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-display-name@7.25.9': + resolution: {integrity: sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-development@7.25.9': + resolution: {integrity: sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx@7.25.9': + resolution: {integrity: sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-pure-annotations@7.25.9': + resolution: {integrity: sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regenerator@7.27.0': + resolution: {integrity: sha512-LX/vCajUJQDqE7Aum/ELUMZAY19+cDpghxrnyt5I1tV6X5PyC86AOoWXWFYFeIvauyeSA6/ktn4tQVn/3ZifsA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regexp-modifiers@7.26.0': + resolution: {integrity: sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-reserved-words@7.25.9': + resolution: {integrity: sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-runtime@7.26.10': + resolution: {integrity: sha512-NWaL2qG6HRpONTnj4JvDU6th4jYeZOJgu3QhmFTCihib0ermtOJqktA5BduGm3suhhVe9EMP9c9+mfJ/I9slqw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-shorthand-properties@7.25.9': + resolution: {integrity: sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-spread@7.25.9': + resolution: {integrity: sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-sticky-regex@7.25.9': + resolution: {integrity: sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-template-literals@7.26.8': + resolution: {integrity: sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typeof-symbol@7.27.0': + resolution: {integrity: sha512-+LLkxA9rKJpNoGsbLnAgOCdESl73vwYn+V6b+5wHbrE7OGKVDPHIQvbFSzqE6rwqaCw2RE+zdJrlLkcf8YOA0w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.27.0': + resolution: {integrity: sha512-fRGGjO2UEGPjvEcyAZXRXAS8AfdaQoq7HnxAbJoAoW10B9xOKesmmndJv+Sym2a+9FHWZ9KbyyLCe9s0Sn5jtg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-escapes@7.25.9': + resolution: {integrity: sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-property-regex@7.25.9': + resolution: {integrity: sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-regex@7.25.9': + resolution: {integrity: sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-sets-regex@7.25.9': + resolution: {integrity: sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/preset-env@7.26.9': + resolution: {integrity: sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-modules@0.1.6-no-external-plugins': + resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 + + '@babel/preset-react@7.26.3': + resolution: {integrity: sha512-Nl03d6T9ky516DGK2YMxrTqvnpUW63TnJMOMonj+Zae0JiPC5BC9xPMSL6L8fiSpA5vP88qfygavVQvnLp+6Cw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-typescript@7.27.0': + resolution: {integrity: sha512-vxaPFfJtHhgeOVXRKuHpHPAOgymmy8V8I65T1q53R7GCZlefKeCaTyDs3zOPHTTbmquvNlQYC5klEvWsBAtrBQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime-corejs2@7.27.0': + resolution: {integrity: sha512-89TgomkhiBKJ1QN/zPJbSW6M3T9caLoSDYsHFNlTI2Q+T12w8ehZeEnx54I79gB0kmM+etCC5Lfgv95rYUJPdQ==} + engines: {node: '>=6.9.0'} + + '@babel/runtime@7.18.6': + resolution: {integrity: sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ==} + engines: {node: '>=6.9.0'} + + '@babel/runtime@7.27.0': + resolution: {integrity: sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.27.0': + resolution: {integrity: sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.27.0': + resolution: {integrity: sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.27.0': + resolution: {integrity: sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + + '@bloomberg/record-tuple-polyfill@0.0.3': + resolution: {integrity: sha512-sBnCqW0nqofE47mxFnw+lvx6kzsQstwaQMVkh66qm/A6IlsnH7WsyGuVXTou8RF2wL4W7ybOoHPvP2WgIo6rhQ==} + + '@chenshuai2144/less2cssinjs@1.0.7': + resolution: {integrity: sha512-D8uyoEBp964Wi4DIbp6UmZmjdKsX/WlDyJY0YhEnl66VVRSZsIY16FBGAxTOixafgXBBBvaNdbIrJ82xP7FzfQ==} + hasBin: true + + '@chenshuai2144/sketch-color@1.0.9': + resolution: {integrity: sha512-obzSy26cb7Pm7OprWyVpgMpIlrZpZ0B7vbrU0RMbvRg0YAI890S5Xy02Aj1Nhl4+KTbi1lVYHt6HQP8Hm9s+1w==} + peerDependencies: + react: '>=16.12.0' + + '@cnakazawa/watch@1.0.4': + resolution: {integrity: sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==} + engines: {node: '>=0.1.95'} + hasBin: true + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@csstools/convert-colors@1.4.0': + resolution: {integrity: sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==} + engines: {node: '>=4.0.0'} + + '@csstools/normalize.css@12.1.1': + resolution: {integrity: sha512-YAYeJ+Xqh7fUou1d1j9XHl44BmsuThiTr4iNrgCQ3J27IbhXsxXDGZ1cXv8Qvs99d4rBbLiSKy3+WZiet32PcQ==} + + '@csstools/postcss-cascade-layers@1.1.1': + resolution: {integrity: sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-color-function@1.1.1': + resolution: {integrity: sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-font-format-keywords@1.0.1': + resolution: {integrity: sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-hwb-function@1.0.2': + resolution: {integrity: sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-ic-unit@1.0.1': + resolution: {integrity: sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-is-pseudo-class@2.0.7': + resolution: {integrity: sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-nested-calc@1.0.0': + resolution: {integrity: sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-normalize-display-values@1.0.1': + resolution: {integrity: sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-oklab-function@1.1.1': + resolution: {integrity: sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-progressive-custom-properties@1.3.0': + resolution: {integrity: sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.3 + + '@csstools/postcss-stepped-value-functions@1.0.1': + resolution: {integrity: sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-text-decoration-shorthand@1.0.0': + resolution: {integrity: sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-trigonometric-functions@1.0.2': + resolution: {integrity: sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==} + engines: {node: ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-unset-value@1.0.2': + resolution: {integrity: sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/selector-specificity@2.2.0': + resolution: {integrity: sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss-selector-parser: ^6.0.10 + + '@ctrl/tinycolor@3.6.1': + resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} + engines: {node: '>=10'} + + '@ctrl/tinycolor@4.1.0': + resolution: {integrity: sha512-WyOx8cJQ+FQus4Mm4uPIZA64gbk3Wxh0so5Lcii0aJifqwoVOlfFtorjLE0Hen4OYyHZMXDWqMmaQemBhgxFRQ==} + engines: {node: '>=14'} + + '@dagrejs/graphlib@2.1.4': + resolution: {integrity: sha512-QCg9sL4uhjn468FDEsb/S9hS2xUZSrv/+dApb1Ze5VKO96pTXKNJZ6MGhIpgWkc1TVhbVGH9/7rq/Mf8/jWicw==} + + '@dnd-kit/accessibility@3.1.1': + resolution: {integrity: sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==} + peerDependencies: + react: '>=16.8.0' + + '@dnd-kit/core@6.3.1': + resolution: {integrity: sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@dnd-kit/modifiers@6.0.1': + resolution: {integrity: sha512-rbxcsg3HhzlcMHVHWDuh9LCjpOVAgqbV78wLGI8tziXY3+qcMQ61qVXIvNKQFuhj75dSfD+o+PYZQ/NUk2A23A==} + peerDependencies: + '@dnd-kit/core': ^6.0.6 + react: '>=16.8.0' + + '@dnd-kit/sortable@7.0.2': + resolution: {integrity: sha512-wDkBHHf9iCi1veM834Gbk1429bd4lHX4RpAwT0y2cHLf246GAvU2sVw/oxWNpPKQNQRQaeGXhAVgrOl1IT+iyA==} + peerDependencies: + '@dnd-kit/core': ^6.0.7 + react: '>=16.8.0' + + '@dnd-kit/utilities@3.2.2': + resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==} + peerDependencies: + react: '>=16.8.0' + + '@emotion/babel-plugin@11.13.5': + resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} + + '@emotion/cache@11.14.0': + resolution: {integrity: sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==} + + '@emotion/css@11.13.5': + resolution: {integrity: sha512-wQdD0Xhkn3Qy2VNcIzbLP9MR8TafI0MJb7BEAXKp+w4+XqErksWR4OXomuDzPsN4InLdGhVe6EYcn2ZIUCpB8w==} + + '@emotion/hash@0.8.0': + resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==} + + '@emotion/hash@0.9.2': + resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} + + '@emotion/memoize@0.9.0': + resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} + + '@emotion/react@11.14.0': + resolution: {integrity: sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==} + peerDependencies: + '@types/react': '*' + react: '>=16.8.0' + peerDependenciesMeta: + '@types/react': + optional: true + + '@emotion/serialize@1.3.3': + resolution: {integrity: sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==} + + '@emotion/sheet@1.4.0': + resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==} + + '@emotion/unitless@0.10.0': + resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==} + + '@emotion/unitless@0.7.5': + resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} + + '@emotion/use-insertion-effect-with-fallbacks@1.2.0': + resolution: {integrity: sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==} + peerDependencies: + react: '>=16.8.0' + + '@emotion/utils@1.4.2': + resolution: {integrity: sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==} + + '@emotion/weak-memoize@0.4.0': + resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} + + '@eslint-community/eslint-utils@4.6.1': + resolution: {integrity: sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.20.0': + resolution: {integrity: sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.2.1': + resolution: {integrity: sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.13.0': + resolution: {integrity: sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.25.1': + resolution: {integrity: sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.2.8': + resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@exodus/schemasafe@1.3.0': + resolution: {integrity: sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==} + + '@formatjs/intl-displaynames@1.2.10': + resolution: {integrity: sha512-GROA2RP6+7Ouu0WnHFF78O5XIU7pBfI19WM1qm93l6MFWibUk67nCfVCK3VAYJkLy8L8ZxjkYT11VIAfvSz8wg==} + + '@formatjs/intl-listformat@1.4.8': + resolution: {integrity: sha512-WNMQlEg0e50VZrGIkgD5n7+DAMGt3boKi1GJALfhFMymslJb5i+5WzWxyj/3a929Z6MAFsmzRIJjKuv+BxKAOQ==} + + '@formatjs/intl-pluralrules@1.5.9': + resolution: {integrity: sha512-37E1ZG+Oqo3qrpUfumzNcFTV+V+NCExmTkkQ9Zw4FSlvJ4WhbbeYdieVapUVz9M0cLy8XrhCkfuM/Kn03iKReg==} + + '@formatjs/intl-relativetimeformat@4.5.16': + resolution: {integrity: sha512-IQ0haY97oHAH5OYUdykNiepdyEWj3SAT+Fp9ZpR85ov2JNiFx+12WWlxlVS8ehdyncC2ZMt/SwFIy2huK2+6/A==} + + '@formatjs/intl-unified-numberformat@3.3.7': + resolution: {integrity: sha512-KnWgLRHzCAgT9eyt3OS34RHoyD7dPDYhRcuKn+/6Kv2knDF8Im43J6vlSW6Hm1w63fNq3ZIT1cFk7RuVO3Psag==} + deprecated: We have renamed the package to @formatjs/intl-numberformat + + '@formatjs/intl-utils@2.3.0': + resolution: {integrity: sha512-KWk80UPIzPmUg+P0rKh6TqspRw0G6eux1PuJr+zz47ftMaZ9QDwbGzHZbtzWkl5hgayM/qrKRutllRC7D/vVXQ==} + deprecated: the package is rather renamed to @formatjs/ecma-abstract with some changes in functionality (primarily selectUnit is removed and we don't plan to make any further changes to this package + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@humanwhocodes/retry@0.4.2': + resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==} + engines: {node: '>=18.18'} + + '@icons/material@0.2.4': + resolution: {integrity: sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==} + peerDependencies: + react: '*' + + '@inline-svg-unique-id/react@1.2.3': + resolution: {integrity: sha512-Tf6u4pTdkeN4BLuh4aHNFDrKxUoiNbCglou3IDem7x0KRCt/rrhRgLljx85X2k5aAUdLvDhQcpeKVePFarF+8w==} + peerDependencies: + react: ^17.0.0 || ^18.0.0 + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@istanbuljs/load-nyc-config@1.1.0': + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jest/console@26.6.2': + resolution: {integrity: sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g==} + engines: {node: '>= 10.14.2'} + + '@jest/console@27.5.1': + resolution: {integrity: sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/console@28.1.3': + resolution: {integrity: sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + '@jest/core@26.6.3': + resolution: {integrity: sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw==} + engines: {node: '>= 10.14.2'} + + '@jest/core@27.5.1': + resolution: {integrity: sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/environment@26.6.2': + resolution: {integrity: sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA==} + engines: {node: '>= 10.14.2'} + + '@jest/environment@27.5.1': + resolution: {integrity: sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/fake-timers@26.6.2': + resolution: {integrity: sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA==} + engines: {node: '>= 10.14.2'} + + '@jest/fake-timers@27.5.1': + resolution: {integrity: sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/globals@26.6.2': + resolution: {integrity: sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA==} + engines: {node: '>= 10.14.2'} + + '@jest/globals@27.5.1': + resolution: {integrity: sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/reporters@26.6.2': + resolution: {integrity: sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw==} + engines: {node: '>= 10.14.2'} + + '@jest/reporters@27.5.1': + resolution: {integrity: sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/schemas@28.1.3': + resolution: {integrity: sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + '@jest/source-map@26.6.2': + resolution: {integrity: sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA==} + engines: {node: '>= 10.14.2'} + + '@jest/source-map@27.5.1': + resolution: {integrity: sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/test-result@26.6.2': + resolution: {integrity: sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==} + engines: {node: '>= 10.14.2'} + + '@jest/test-result@27.5.1': + resolution: {integrity: sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/test-result@28.1.3': + resolution: {integrity: sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + '@jest/test-sequencer@26.6.3': + resolution: {integrity: sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw==} + engines: {node: '>= 10.14.2'} + + '@jest/test-sequencer@27.5.1': + resolution: {integrity: sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/transform@26.6.2': + resolution: {integrity: sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==} + engines: {node: '>= 10.14.2'} + + '@jest/transform@27.5.1': + resolution: {integrity: sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/types@26.6.2': + resolution: {integrity: sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==} + engines: {node: '>= 10.14.2'} + + '@jest/types@27.5.1': + resolution: {integrity: sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/types@28.1.3': + resolution: {integrity: sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/source-map@0.3.6': + resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@juggle/resize-observer@3.4.0': + resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==} + + '@leichtgewicht/ip-codec@2.0.5': + resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} + + '@ljharb/resumer@0.0.1': + resolution: {integrity: sha512-skQiAOrCfO7vRTq53cxznMpks7wS1va95UCidALlOVWqvBAzwPVErwizDwoMqNVMEn1mDq0utxZd02eIrvF1lw==} + engines: {node: '>= 0.4'} + + '@ljharb/through@2.3.14': + resolution: {integrity: sha512-ajBvlKpWucBB17FuQYUShqpqy8GRgYEpJW0vWJbUu1CV9lWyrDCapy0lScU8T8Z6qn49sSwJB3+M+evYIdGg+A==} + engines: {node: '>= 0.4'} + + '@mapbox/geojson-rewind@0.5.2': + resolution: {integrity: sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA==} + hasBin: true + + '@mapbox/geojson-types@1.0.2': + resolution: {integrity: sha512-e9EBqHHv3EORHrSfbR9DqecPNn+AmuAoQxV6aL8Xu30bJMJR1o8PZLZzpk1Wq7/NfCbuhmakHTPYRhoqLsXRnw==} + + '@mapbox/jsonlint-lines-primitives@2.0.2': + resolution: {integrity: sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==} + engines: {node: '>= 0.6'} + + '@mapbox/mapbox-gl-supported@1.5.0': + resolution: {integrity: sha512-/PT1P6DNf7vjEEiPkVIRJkvibbqWtqnyGaBz3nfRdcxclNSnSdaLU5tfAgcD7I8Yt5i+L19s406YLl1koLnLbg==} + peerDependencies: + mapbox-gl: '>=0.32.1 <2.0.0' + + '@mapbox/martini@0.2.0': + resolution: {integrity: sha512-7hFhtkb0KTLEls+TRw/rWayq5EeHtTaErgm/NskVoXmtgAQu/9D299aeyj6mzAR/6XUnYRp2lU+4IcrYRFjVsQ==} + + '@mapbox/point-geometry@0.1.0': + resolution: {integrity: sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==} + + '@mapbox/tiny-sdf@1.2.5': + resolution: {integrity: sha512-cD8A/zJlm6fdJOk6DqPUV8mcpyJkRz2x2R+/fYcWDYG3oWbG7/L7Yl/WqQ1VZCjnL9OTIMAn6c+BC5Eru4sQEw==} + + '@mapbox/tiny-sdf@2.0.6': + resolution: {integrity: sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA==} + + '@mapbox/unitbezier@0.0.0': + resolution: {integrity: sha512-HPnRdYO0WjFjRTSwO3frz1wKaU649OBFPX3Zo/2WZvuRi6zMiRGui8SnPQiQABgqCf8YikDe5t3HViTVw1WUzA==} + + '@mapbox/unitbezier@0.0.1': + resolution: {integrity: sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==} + + '@mapbox/vector-tile@1.3.1': + resolution: {integrity: sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==} + + '@mapbox/whoots-js@3.1.0': + resolution: {integrity: sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==} + engines: {node: '>=6.0.0'} + + '@maplibre/maplibre-gl-style-spec@19.3.3': + resolution: {integrity: sha512-cOZZOVhDSulgK0meTsTkmNXb1ahVvmTmWmfx9gRBwc6hq98wS9JP35ESIoNq3xqEan+UN+gn8187Z6E4NKhLsw==} + hasBin: true + + '@mrmlnc/readdir-enhanced@2.2.1': + resolution: {integrity: sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==} + engines: {node: '>=4'} + + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': + resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@1.1.3': + resolution: {integrity: sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==} + engines: {node: '>= 6'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@oceanbase/aliyun-theme@0.1.6': + resolution: {integrity: sha512-4IRij4j1Cw2NbnBpbg3Cb6aoYjG2E2FzSk11uDKY8IBrAMV+2lByMoM8j2gJZ1shqIyiYYorw/UawYW8BljILw==} + + '@oceanbase/charts@0.4.5': + resolution: {integrity: sha512-zLxVAicamclSlVGrjg4IELscenDe8mHyZW/NfZbkP8mbRpDDXjPdnW/ajSyD1jOi/nbYTyZj5rrnBkC9E8S6DA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@oceanbase/design@0.4.10': + resolution: {integrity: sha512-D1NRXxVCqtoEGWUBZzUsNSPbIEcqqphiS7ZICL22eu50DjVS6YWhjMSAWtS6aiXhwZ9JZIz8gp0XXbtR1zUMOg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@oceanbase/icons-svg@1.0.10': + resolution: {integrity: sha512-oMaynh08/RoTVKK4Us6GISIog0iLViLBs6jYh7Jyu0CnTml1hSOhnga/qQWmnLr/MaHWhdgaXqF9L4UZW4hPSw==} + + '@oceanbase/icons@0.4.6': + resolution: {integrity: sha512-mQu7wSduCRko8ZTd3viROZJDdkTB6O0Ytbkm3HJBy2sMXke59y5yAfNN8fF73iPXnVIDO5XP0nnlg0VF4RKRuA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@oceanbase/ui@0.4.13': + resolution: {integrity: sha512-HRrL7SQ+cr7NCtkJvsNzSBf6FM3Ef1CHFzhfISWoPneUAqFi1JtRP9LjoQJJbp9aWWUISYLSM08ayU9MV68YZw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@oceanbase/util@0.4.2': + resolution: {integrity: sha512-YvGD6TBVO66sfO/qw+/hNs0PMo9Pjowc7xR50UxRTktChUl2BlDTfmWzmnxFuyAg7U+HRMOKxkpXzjQo5yhtFQ==} + peerDependencies: + react: '>=16.9.0' + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pmmmwh/react-refresh-webpack-plugin@0.5.16': + resolution: {integrity: sha512-kLQc9xz6QIqd2oIYyXRUiAp79kGpFBm3fEM9ahfG1HI0WI5gdZ2OVHWdmZYnwODt7ISck+QuQ6sBPrtvUBML7Q==} + engines: {node: '>= 10.13'} + peerDependencies: + '@types/webpack': 4.x || 5.x + react-refresh: '>=0.10.0 <1.0.0' + sockjs-client: ^1.4.0 + type-fest: '>=0.17.0 <5.0.0' + webpack: '>=4.43.0 <6.0.0' + webpack-dev-server: 3.x || 4.x || 5.x + webpack-hot-middleware: 2.x + webpack-plugin-serve: 0.x || 1.x + peerDependenciesMeta: + '@types/webpack': + optional: true + sockjs-client: + optional: true + type-fest: + optional: true + webpack-dev-server: + optional: true + webpack-hot-middleware: + optional: true + webpack-plugin-serve: + optional: true + + '@probe.gl/env@3.6.0': + resolution: {integrity: sha512-4tTZYUg/8BICC3Yyb9rOeoKeijKbZHRXBEKObrfPmX4sQmYB15ZOUpoVBhAyJkOYVAM8EkPci6Uw5dLCwx2BEQ==} + + '@probe.gl/log@3.6.0': + resolution: {integrity: sha512-hjpyenpEvOdowgZ1qMeCJxfRD4JkKdlXz0RC14m42Un62NtOT+GpWyKA4LssT0+xyLULCByRAtG2fzZorpIAcA==} + + '@probe.gl/stats@3.6.0': + resolution: {integrity: sha512-JdALQXB44OP4kUBN/UrQgzbJe4qokbVF4Y8lkIA8iVCFnjVowWIgkD/z/0QO65yELT54tTrtepw1jScjKB+rhQ==} + + '@qixian.cs/path-to-regexp@6.1.0': + resolution: {integrity: sha512-2jIiLiVZB1jnY7IIRQKtoV8Gnr7XIhk4mC88ONGunZE3hYt5IHUG4BE/6+JiTBjjEWQLBeWnZB8hGpppkufiVw==} + + '@rc-component/async-validator@5.0.4': + resolution: {integrity: sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==} + engines: {node: '>=14.x'} + + '@rc-component/color-picker@2.0.1': + resolution: {integrity: sha512-WcZYwAThV/b2GISQ8F+7650r5ZZJ043E57aVBFkQ+kSY4C6wdofXgB0hBx+GPGpIU0Z81eETNoDUJMr7oy/P8Q==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/context@1.4.0': + resolution: {integrity: sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/mini-decimal@1.1.0': + resolution: {integrity: sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==} + engines: {node: '>=8.x'} + + '@rc-component/mutate-observer@1.1.0': + resolution: {integrity: sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/portal@1.1.2': + resolution: {integrity: sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/qrcode@1.0.0': + resolution: {integrity: sha512-L+rZ4HXP2sJ1gHMGHjsg9jlYBX/SLN2D6OxP9Zn3qgtpMWtO2vUfxVFwiogHpAIqs54FnALxraUy/BCO1yRIgg==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/tour@1.15.1': + resolution: {integrity: sha512-Tr2t7J1DKZUpfJuDZWHxyxWpfmj8EZrqSgyMZ+BCdvKZ6r1UDsfU46M/iWAAFBy961Ssfom2kv5f3UcjIL2CmQ==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/trigger@2.2.6': + resolution: {integrity: sha512-/9zuTnWwhQ3S3WT1T8BubuFTT46kvnXgaERR9f4BTKyn61/wpf/BvbImzYBubzJibU707FxwbKszLlHjcLiv1Q==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rgrove/parse-xml@2.0.4': + resolution: {integrity: sha512-344bRXnUMu1tWqq1GJO2nCSqJRGTzcNLErcG2HZbVhUo90R5xQ6YdsCqtuT0KaFyN/mlxWqt2SdHSRNzwDvT5g==} + engines: {node: '>=6.0.0'} + + '@rollup/plugin-babel@5.3.1': + resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==} + engines: {node: '>= 10.0.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@types/babel__core': ^7.1.9 + rollup: ^1.20.0||^2.0.0 + peerDependenciesMeta: + '@types/babel__core': + optional: true + + '@rollup/plugin-node-resolve@11.2.1': + resolution: {integrity: sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==} + engines: {node: '>= 10.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0 + + '@rollup/plugin-replace@2.4.2': + resolution: {integrity: sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==} + peerDependencies: + rollup: ^1.20.0 || ^2.0.0 + + '@rollup/pluginutils@3.1.0': + resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} + engines: {node: '>= 8.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0 + + '@rtsao/scc@1.1.0': + resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + + '@rushstack/eslint-patch@1.11.0': + resolution: {integrity: sha512-zxnHvoMQVqewTJr/W4pKjF0bMGiKJv1WX7bSrkl46Hg0QjESbzBROWK0Wg4RphzSOS5Jiy7eFimmM3UgMrMZbQ==} + + '@sentry-internal/feedback@7.120.3': + resolution: {integrity: sha512-ewJJIQ0mbsOX6jfiVFvqMjokxNtgP3dNwUv+4nenN+iJJPQsM6a0ocro3iscxwVdbkjw5hY3BUV2ICI5Q0UWoA==} + engines: {node: '>=12'} + + '@sentry-internal/replay-canvas@7.120.3': + resolution: {integrity: sha512-s5xy+bVL1eDZchM6gmaOiXvTqpAsUfO7122DxVdEDMtwVq3e22bS2aiGa8CUgOiJkulZ+09q73nufM77kOmT/A==} + engines: {node: '>=12'} + + '@sentry-internal/tracing@7.120.3': + resolution: {integrity: sha512-Ausx+Jw1pAMbIBHStoQ6ZqDZR60PsCByvHdw/jdH9AqPrNE9xlBSf9EwcycvmrzwyKspSLaB52grlje2cRIUMg==} + engines: {node: '>=8'} + + '@sentry/browser@7.120.3': + resolution: {integrity: sha512-i9vGcK9N8zZ/JQo1TCEfHHYZ2miidOvgOABRUc9zQKhYdcYQB2/LU1kqlj77Pxdxf4wOa9137d6rPrSn9iiBxg==} + engines: {node: '>=8'} + + '@sentry/core@7.120.3': + resolution: {integrity: sha512-vyy11fCGpkGK3qI5DSXOjgIboBZTriw0YDx/0KyX5CjIjDDNgp5AGgpgFkfZyiYiaU2Ww3iFuKo4wHmBusz1uA==} + engines: {node: '>=8'} + + '@sentry/integrations@7.120.3': + resolution: {integrity: sha512-6i/lYp0BubHPDTg91/uxHvNui427df9r17SsIEXa2eKDwQ9gW2qRx5IWgvnxs2GV/GfSbwcx4swUB3RfEWrXrQ==} + engines: {node: '>=8'} + + '@sentry/react@7.120.3': + resolution: {integrity: sha512-BcpoK9dwblfb20xwjn/1DRtplvPEXFc3XCRkYSnTfnfZNU8yPOcVX4X2X0I8R+/gsg+MWiFOdEtXJ3FqpJiJ4Q==} + engines: {node: '>=8'} + peerDependencies: + react: 15.x || 16.x || 17.x || 18.x + + '@sentry/replay@7.120.3': + resolution: {integrity: sha512-CjVq1fP6bpDiX8VQxudD5MPWwatfXk8EJ2jQhJTcWu/4bCSOQmHxnnmBM+GVn5acKUBCodWHBN+IUZgnJheZSg==} + engines: {node: '>=12'} + + '@sentry/tracing@7.120.3': + resolution: {integrity: sha512-B7bqyYFgHuab1Pn7w5KXsZP/nfFo4VDBDdSXDSWYk5+TYJ3IDruO3eJFhOrircfsz4YwazWm9kbeZhkpsHDyHg==} + engines: {node: '>=8'} + + '@sentry/types@7.120.3': + resolution: {integrity: sha512-C4z+3kGWNFJ303FC+FxAd4KkHvxpNFYAFN8iMIgBwJdpIl25KZ8Q/VdGn0MLLUEHNLvjob0+wvwlcRBBNLXOow==} + engines: {node: '>=8'} + + '@sentry/utils@7.120.3': + resolution: {integrity: sha512-UDAOQJtJDxZHQ5Nm1olycBIsz2wdGX8SdzyGVHmD8EOQYAeDZQyIlQYohDe9nazdIOQLZCIc3fU0G9gqVLkaGQ==} + engines: {node: '>=8'} + + '@sinclair/typebox@0.24.51': + resolution: {integrity: sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==} + + '@sinonjs/commons@1.8.6': + resolution: {integrity: sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==} + + '@sinonjs/fake-timers@6.0.1': + resolution: {integrity: sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==} + + '@sinonjs/fake-timers@8.1.0': + resolution: {integrity: sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==} + + '@surma/rollup-plugin-off-main-thread@2.2.3': + resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==} + + '@svgr/babel-plugin-add-jsx-attribute@5.4.0': + resolution: {integrity: sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==} + engines: {node: '>=10'} + + '@svgr/babel-plugin-remove-jsx-attribute@5.4.0': + resolution: {integrity: sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==} + engines: {node: '>=10'} + + '@svgr/babel-plugin-remove-jsx-empty-expression@5.0.1': + resolution: {integrity: sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==} + engines: {node: '>=10'} + + '@svgr/babel-plugin-replace-jsx-attribute-value@5.0.1': + resolution: {integrity: sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==} + engines: {node: '>=10'} + + '@svgr/babel-plugin-svg-dynamic-title@5.4.0': + resolution: {integrity: sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==} + engines: {node: '>=10'} + + '@svgr/babel-plugin-svg-em-dimensions@5.4.0': + resolution: {integrity: sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==} + engines: {node: '>=10'} + + '@svgr/babel-plugin-transform-react-native-svg@5.4.0': + resolution: {integrity: sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==} + engines: {node: '>=10'} + + '@svgr/babel-plugin-transform-svg-component@5.5.0': + resolution: {integrity: sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==} + engines: {node: '>=10'} + + '@svgr/babel-preset@5.5.0': + resolution: {integrity: sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==} + engines: {node: '>=10'} + + '@svgr/core@5.5.0': + resolution: {integrity: sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==} + engines: {node: '>=10'} + + '@svgr/hast-util-to-babel-ast@5.5.0': + resolution: {integrity: sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==} + engines: {node: '>=10'} + + '@svgr/plugin-jsx@5.5.0': + resolution: {integrity: sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==} + engines: {node: '>=10'} + + '@svgr/plugin-svgo@5.5.0': + resolution: {integrity: sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==} + engines: {node: '>=10'} + + '@svgr/webpack@5.5.0': + resolution: {integrity: sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==} + engines: {node: '>=10'} + + '@tootallnate/once@1.1.2': + resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} + engines: {node: '>= 6'} + + '@trysound/sax@0.2.0': + resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} + engines: {node: '>=10.13.0'} + + '@tsconfig/node10@1.0.11': + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + + '@turf/bbox-polygon@6.5.0': + resolution: {integrity: sha512-+/r0NyL1lOG3zKZmmf6L8ommU07HliP4dgYToMoTxqzsWzyLjaj/OzgQ8rBmv703WJX+aS6yCmLuIhYqyufyuw==} + + '@turf/bbox@6.5.0': + resolution: {integrity: sha512-RBbLaao5hXTYyyg577iuMtDB8ehxMlUqHEJiMs8jT1GHkFhr6sYre3lmLsPeYEi/ZKj5TP5tt7fkzNdJ4GIVyw==} + + '@turf/clone@6.5.0': + resolution: {integrity: sha512-mzVtTFj/QycXOn6ig+annKrM6ZlimreKYz6f/GSERytOpgzodbQyOgkfwru100O1KQhhjSudKK4DsQ0oyi9cTw==} + + '@turf/helpers@6.5.0': + resolution: {integrity: sha512-VbI1dV5bLFzohYYdgqwikdMVpe7pJ9X3E+dlr425wa2/sMJqYDhTO++ec38/pcPvPE6oD9WEEeU3Xu3gza+VPw==} + + '@turf/invariant@6.5.0': + resolution: {integrity: sha512-Wv8PRNCtPD31UVbdJE/KVAWKe7l6US+lJItRR/HOEW3eh+U/JwRCSUl/KZ7bmjM/C+zLNoreM2TU6OoLACs4eg==} + + '@turf/meta@6.5.0': + resolution: {integrity: sha512-RrArvtsV0vdsCBegoBtOalgdSOfkBrTJ07VkpiCnq/491W67hnMWmDu7e6Ztw0C3WldRYTXkg3SumfdzZxLBHA==} + + '@turf/polygon-to-line@6.5.0': + resolution: {integrity: sha512-5p4n/ij97EIttAq+ewSnKt0ruvuM+LIDzuczSzuHTpq4oS7Oq8yqg5TQ4nzMVuK41r/tALCk7nAoBuw3Su4Gcw==} + + '@turf/union@6.5.0': + resolution: {integrity: sha512-igYWCwP/f0RFHIlC2c0SKDuM/ObBaqSljI3IdV/x71805QbIvY/BYGcJdyNcgEA6cylIGl/0VSlIbpJHZ9ldhw==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.20.7': + resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==} + + '@types/body-parser@1.19.5': + resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + + '@types/bonjour@3.5.13': + resolution: {integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==} + + '@types/connect-history-api-fallback@1.5.4': + resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==} + + '@types/connect@3.4.38': + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + + '@types/crypto-js@4.2.2': + resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==} + + '@types/d3-timer@1.0.12': + resolution: {integrity: sha512-Tv9tkA4y3UvGQnrHyYAQhf5x/297FuYwotS4UW2TpwLblvRahbyL8r9HFYTJLPfPRqS63hwlqRItjKGmKtJxNg==} + + '@types/d3-timer@2.0.3': + resolution: {integrity: sha512-jhAJzaanK5LqyLQ50jJNIrB8fjL9gwWZTgYjevPvkDLMU+kTAZkYsobI59nYoeSrH1PucuyJEi247Pb90t6XUg==} + + '@types/eslint-scope@3.7.7': + resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} + + '@types/eslint@8.56.12': + resolution: {integrity: sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==} + + '@types/eslint@9.6.1': + resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} + + '@types/estree@0.0.39': + resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} + + '@types/estree@1.0.7': + resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + + '@types/express-serve-static-core@4.19.6': + resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} + + '@types/express-serve-static-core@5.0.6': + resolution: {integrity: sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==} + + '@types/express@4.17.21': + resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + + '@types/geojson@7946.0.16': + resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} + + '@types/glob@7.2.0': + resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} + + '@types/graceful-fs@4.1.9': + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + + '@types/history@4.7.11': + resolution: {integrity: sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==} + + '@types/history@5.0.0': + resolution: {integrity: sha512-hy8b7Y1J8OGe6LbAjj3xniQrj3v6lsivCcrmf4TzSgPzLkhIeKgc5IZnT7ReIqmEuodjfO8EYAuoFvIrHi/+jQ==} + deprecated: This is a stub types definition. history provides its own type definitions, so you do not need this installed. + + '@types/hoist-non-react-statics@3.3.6': + resolution: {integrity: sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==} + + '@types/html-minifier-terser@5.1.2': + resolution: {integrity: sha512-h4lTMgMJctJybDp8CQrxTUiiYmedihHWkjnF/8Pxseu2S6Nlfcy8kwboQ8yejh456rP2yWoEVm1sS/FVsfM48w==} + + '@types/html-minifier-terser@6.1.0': + resolution: {integrity: sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==} + + '@types/http-errors@2.0.4': + resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + + '@types/http-proxy@1.17.16': + resolution: {integrity: sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==} + + '@types/invariant@2.2.37': + resolution: {integrity: sha512-IwpIMieE55oGWiXkQPSBY1nw1nFs6bsKXTFskNY8sdS17K24vyEBRQZEwlRS7ZmXCWnJcQtbxWzly+cODWGs2A==} + + '@types/isomorphic-fetch@0.0.35': + resolution: {integrity: sha512-DaZNUvLDCAnCTjgwxgiL1eQdxIKEpNLOlTNtAgnZc50bG2copGhRrFN9/PxPBuJe+tZVLCbQ7ls0xveXVRPkvw==} + + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/js-cookie@2.2.7': + resolution: {integrity: sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/json5@0.0.29': + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + + '@types/lodash@4.17.16': + resolution: {integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==} + + '@types/mapbox__point-geometry@0.1.4': + resolution: {integrity: sha512-mUWlSxAmYLfwnRBmgYV86tgYmMIICX4kza8YnE/eIlywGe2XoOxlpVnXWwir92xRLjwyarqwpu2EJKD2pk0IUA==} + + '@types/mapbox__vector-tile@1.3.4': + resolution: {integrity: sha512-bpd8dRn9pr6xKvuEBQup8pwQfD4VUyqO/2deGjfpe6AwC8YRlyEipvefyRJUSiCJTZuCb8Pl1ciVV5ekqJ96Bg==} + + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + + '@types/minimatch@5.1.2': + resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + + '@types/node-forge@1.3.11': + resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} + + '@types/node@18.19.87': + resolution: {integrity: sha512-OIAAu6ypnVZHmsHCeJ+7CCSub38QNBS9uceMQeg7K5Ur0Jr+wG9wEOEvvMbhp09pxD5czIUy/jND7s7Tb6Nw7A==} + + '@types/node@22.15.3': + resolution: {integrity: sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==} + + '@types/normalize-package-data@2.4.4': + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + + '@types/parse-json@4.0.2': + resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + + '@types/pbf@3.0.5': + resolution: {integrity: sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==} + + '@types/prettier@2.7.3': + resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} + + '@types/prop-types@15.7.14': + resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} + + '@types/q@1.5.8': + resolution: {integrity: sha512-hroOstUScF6zhIi+5+x0dzqrHA1EJi+Irri6b1fxolMTqqHIV/Cg77EtnQcZqZCu8hR3mX2BzIxN4/GzI68Kfw==} + + '@types/qs@6.9.18': + resolution: {integrity: sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==} + + '@types/range-parser@1.2.7': + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + + '@types/react-dom@16.9.25': + resolution: {integrity: sha512-ZK//eAPhwft9Ul2/Zj+6O11YR6L4JX0J2sVeBC9Ft7x7HFN7xk7yUV/zDxqV6rjvqgl6r8Dq7oQImxtyf/Mzcw==} + peerDependencies: + '@types/react': ^16.0.0 + + '@types/react-dom@17.0.2': + resolution: {integrity: sha512-Icd9KEgdnFfJs39KyRyr0jQ7EKhq8U6CcHRMGAS45fp5qgUvxL3ujUCfWFttUK2UErqZNj97t9gsVPNAqcwoCg==} + + '@types/react-helmet@6.1.11': + resolution: {integrity: sha512-0QcdGLddTERotCXo3VFlUSWO3ztraw8nZ6e3zJSgG7apwV5xt+pJUS8ewPBqT4NYB1optGLprNQzFleIY84u/g==} + + '@types/react-redux@7.1.34': + resolution: {integrity: sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==} + + '@types/react-router-config@5.0.2': + resolution: {integrity: sha512-WOSetDV3YPxbkVJAdv/bqExJjmcdCi/vpCJh3NfQOy1X15vHMSiMioXIcGekXDJJYhqGUMDo9e337mh508foAA==} + + '@types/react-router-dom@5.1.7': + resolution: {integrity: sha512-D5mHD6TbdV/DNHYsnwBTv+y73ei+mMjrkGrla86HthE4/PVvL1J94Bu3qABU+COXzpL23T1EZapVVpwHuBXiUg==} + + '@types/react-router-dom@5.3.3': + resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==} + + '@types/react-router@5.1.12': + resolution: {integrity: sha512-0bhXQwHYfMeJlCh7mGhc0VJTRm0Gk+Z8T00aiP4702mDUuLs9SMhnd2DitpjWFjdOecx2UXtICK14H9iMnziGA==} + + '@types/react-router@5.1.20': + resolution: {integrity: sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==} + + '@types/react@16.14.63': + resolution: {integrity: sha512-s83gano0fRBVEw3ejdLpjgvU83F0LIeeuXqdxfPZF/Sc2bhr60tEqCK1zZ+aLirBwRSD6V5zCtOsEjcwKow3JQ==} + + '@types/react@17.0.52': + resolution: {integrity: sha512-vwk8QqVODi0VaZZpDXQCmEmiOuyjEFPY7Ttaw5vjM112LOq37yz1CDJGrRJwA1fYEq4Iitd5rnjd1yWAc/bT+A==} + + '@types/resolve@1.17.1': + resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} + + '@types/retry@0.12.0': + resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + + '@types/scheduler@0.16.8': + resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==} + + '@types/scheduler@0.26.0': + resolution: {integrity: sha512-WFHp9YUJQ6CKshqoC37iOlHnQSmxNc795UhB26CyBBttrN9svdIrUjl/NjnNmfcwtncN0h/0PPAFWv9ovP8mLA==} + + '@types/scroll-into-view@1.16.4': + resolution: {integrity: sha512-f2Rw8aA9gj7+M6uWhNx/mRAWyC4tYsvG2uA/cMEkXUyfMXYgTRJCM8CD8kTkoQlX8STQVgTQL0SmmM1VPZQmsg==} + + '@types/semver@7.7.0': + resolution: {integrity: sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==} + + '@types/send@0.17.4': + resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + + '@types/serve-index@1.9.4': + resolution: {integrity: sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==} + + '@types/serve-static@1.15.7': + resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} + + '@types/sockjs@0.3.36': + resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} + + '@types/source-list-map@0.1.6': + resolution: {integrity: sha512-5JcVt1u5HDmlXkwOD2nslZVllBBc7HDuOICfiZah2Z0is8M8g+ddAEawbmd3VjedfDHBzxCaXLs07QEmb7y54g==} + + '@types/sql-formatter@2.3.0': + resolution: {integrity: sha512-Xh9kEOaKWhm3vYD5lUjYFFiSfpN4y3/iQCJUAVwFaQ1rVvHs4WXTa5C8E7gyF3kxwsMS8KgttW7WBAPtFlsvAg==} + + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + + '@types/supercluster@7.1.3': + resolution: {integrity: sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==} + + '@types/tapable@1.0.12': + resolution: {integrity: sha512-bTHG8fcxEqv1M9+TD14P8ok8hjxoOCkfKc8XXLaaD05kI7ohpeI956jtDOD3XHKBQrlyPughUtzm1jtVhHpA5Q==} + + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + + '@types/uglify-js@3.17.5': + resolution: {integrity: sha512-TU+fZFBTBcXj/GpDpDaBmgWk/gn96kMZ+uocaFUlV2f8a6WdMzzI44QBCmGcCiYR0Y6ZlNRiyUyKKt5nl/lbzQ==} + + '@types/validator@12.0.1': + resolution: {integrity: sha512-l57fIANZLMe8DArz+SDb+7ATXnDm15P7u2wHBw5mb0aSMd+UuvmvhouBF2hdLgQPDMJ39sh9g2MJO4GkZ0VAdQ==} + + '@types/webpack-sources@3.2.3': + resolution: {integrity: sha512-4nZOdMwSPHZ4pTEZzSp0AsTM4K7Qmu40UKW4tJDiOVs20UzYF9l+qUe4s0ftfN0pin06n+5cWWDJXH+sbhAiDw==} + + '@types/webpack@4.41.40': + resolution: {integrity: sha512-u6kMFSBM9HcoTpUXnL6mt2HSzftqb3JgYV6oxIgL2dl6sX6aCa5k6SOkzv5DuZjBTPUE/dJltKtwwuqrkZHpfw==} + + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@15.0.19': + resolution: {integrity: sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==} + + '@types/yargs@16.0.9': + resolution: {integrity: sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==} + + '@types/yargs@17.0.33': + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} + + '@typescript-eslint/eslint-plugin@5.62.0': + resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/parser': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/experimental-utils@5.62.0': + resolution: {integrity: sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + + '@typescript-eslint/parser@5.62.0': + resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/scope-manager@5.62.0': + resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@typescript-eslint/type-utils@5.62.0': + resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/types@5.62.0': + resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@typescript-eslint/typescript-estree@5.62.0': + resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/utils@5.62.0': + resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + + '@typescript-eslint/visitor-keys@5.62.0': + resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@umijs/ast@3.5.43': + resolution: {integrity: sha512-P+yperHXuPCewEhgzKRXOxhpQmcK06J2PuLs7XaeQatpUTP//omJeIAcSHV8Rr9ynuvYnz9lS1qKqjgfjmZ8bA==} + + '@umijs/babel-plugin-auto-css-modules@3.5.43': + resolution: {integrity: sha512-u1JTVqgABY3cSCWsaRumnPINZzgUE5WDTsm7BYXf5a+mdZQiv87pCU2jC6S4OabMqm3mR75gJc5wLR4sFnlkrA==} + + '@umijs/babel-plugin-import-to-await-require@3.5.43': + resolution: {integrity: sha512-PhPTS/i2yBEdZbsSp6Cj3cEcxwLOcacjzUgkH+g9vvVwMSAgMqkI1Tx57Y70LZorE4PeUNl5yeS9hGm24JAMQA==} + + '@umijs/babel-plugin-lock-core-js-3@3.5.43': + resolution: {integrity: sha512-hOb6cyCrn/4SQ2qGc6RBOG7aPtMHqyuy2iJonzFobdbkOW5nOnYfK/F3oeSJqn/amynFr3W6cUdflyg3Mn5lRQ==} + + '@umijs/babel-plugin-no-anonymous-default-export@3.5.43': + resolution: {integrity: sha512-itH+IV96AChX7zKDLEKNi6IEHL+RT8DsP8BSH3oDGWRE0OM4VlpM42N195bsMtOtdl7kCb9HUP1Bg1J/+hHwsw==} + + '@umijs/babel-preset-umi@3.5.43': + resolution: {integrity: sha512-raFsiPYy70QNKM4jSo+qdO3wkZr9PCsSSz/+CGTUPkpre5sk6ISDcuXdvEJ92viMe1Xk1+LaPcnbJqIdu7EClA==} + + '@umijs/bundler-utils@3.5.43': + resolution: {integrity: sha512-Vw1qR+4KBQx/M1NwlDrMPydyBoA/qLT+nxZKAeIwCjkJT42QSJn38OMDqsRKRPkuoL5tLN4Ss+PbXoJ5evLWoA==} + + '@umijs/bundler-webpack@3.5.43': + resolution: {integrity: sha512-Sf15PCMSbt0QMnRcNGIU+Nd6dha5aBZPdOE7IdlWLXJ9rSICNuhblD2P5L8MscwomOXYvsPKzNGI92MUyfjq5w==} + hasBin: true + + '@umijs/case-sensitive-paths-webpack-plugin@1.0.1': + resolution: {integrity: sha512-kDKJ8yTarxwxGJDInG33hOpaQRZ//XpNuuznQ/1Mscypw6kappzFmrBr2dOYave++K7JHouoANF354UpbEQw0Q==} + + '@umijs/core@3.5.43': + resolution: {integrity: sha512-YT/ZrYZl5xrffW3WyDzsrec0FMhebjDoJSA7A2X2WX8lmsIhjzrVEDeR265+t5J+OH7joB8pMMiV/tvhVPHb7w==} + + '@umijs/deps@3.5.43': + resolution: {integrity: sha512-1UugbYw+Emcq1AngzLgCvpMDdIVjpBVGwdrWDcxt3zjSR/2teRbaMdzUEqaMaqMWYVMbZKorARuyit5hZorrXQ==} + + '@umijs/openapi@1.13.0': + resolution: {integrity: sha512-hIilb15A8Md0aUBsuvX2nH24oVjue9OIBETapKbtanWqYCqUBcOvNZ5SBAtzVD1kVx80Q6oNlCRYKBsS80W31w==} + hasBin: true + + '@umijs/plugin-access@2.4.3': + resolution: {integrity: sha512-6FON4aHzVFs/vtFK5Sdnw+FBolfoYi8wV8V9Q8x2T19NwjZtjXSPjt0gtrG4jdx4LRsSV2DKLaMGoJYbNr94aA==} + peerDependencies: + '@umijs/plugin-initial-state': 2.x + '@umijs/plugin-model': 2.x + umi: 3.x + + '@umijs/plugin-analytics@0.2.2': + resolution: {integrity: sha512-dVDzUfgIdEwdCC6a5IsMYpIPI+bEZjBEqIhAvw9dic6Vk77w9RxQxyRfW11dDmdXLAwWphp22NntQNt1ejZPtg==} + peerDependencies: + umi: 3.x + + '@umijs/plugin-antd@0.13.0': + resolution: {integrity: sha512-7tooYtOylVatrzMWCJtk8JFQL90i94OD0FgZYpKBbM7keThH8prYkSkDJFIDkuGfZ6pl6BJT8ESnYLxf2OiQUw==} + peerDependencies: + umi: 3.x + + '@umijs/plugin-crossorigin@1.2.1': + resolution: {integrity: sha512-4oXNFBLOCH1FHTgFi7EDmlcjjYMthOQlrTT+mSbNeMzvl0P/WKldSJsYAUXUTg+I7vlbb5bNby4dpHKK37JcbQ==} + peerDependencies: + umi: 3.x + + '@umijs/plugin-dva@0.13.0': + resolution: {integrity: sha512-cpGq8vzN8AmyWxexWLQ+WGqfT0WMCiryvU5EcNGbx1/Ub9aICUfPBpB46cxJrxjDCjUzuVslRNb2pdgI0xXUXg==} + peerDependencies: + umi: 3.x + + '@umijs/plugin-helmet@1.1.3': + resolution: {integrity: sha512-X4GRFlvOb8DxMDm1vExfpWOvxl6bp0oZz114DyhwnMSriJ8RcHAigTjtVJHYxJpKv7P6KayN3n13J4w/XZGWMg==} + peerDependencies: + umi: 3.x + + '@umijs/plugin-initial-state@2.4.0': + resolution: {integrity: sha512-UHH5fTL9skm4771R3xvWCrjd5xiQ7OdJ83G0P1YZLhuNbh0cAFVT8SPTU8dA9o8TTAZ66IEq7axhWl1cGxVsXw==} + peerDependencies: + umi: 3.x + + '@umijs/plugin-layout@0.18.1': + resolution: {integrity: sha512-15YTcFpic0v15nFzlg6G8nvMCveBtcBL77Wr9wXYJdgR0iU7dnO7T4OqbLwgEc1uHxtGhTVibi6nSGelX56zCg==} + peerDependencies: + '@ant-design/icons': ^4.0.0 + '@ant-design/pro-layout': ^6.0.0 + '@umijs/plugin-initial-state': 2.x + '@umijs/plugin-locale': 0.x + '@umijs/plugin-model': 2.x + umi: 3.x + + '@umijs/plugin-locale@0.15.2': + resolution: {integrity: sha512-/m3ik0NKbE/PHFPKPqSBEwGi5RUB6Dz2T7jepDXhU8ycV0zUPGbDbChUx1r/3t5zveZIND1s/7A49Apb+ujUmg==} + peerDependencies: + umi: 3.x + + '@umijs/plugin-model@2.6.2': + resolution: {integrity: sha512-MKLAgYIoBkciavxTqJY6VOhvnNQv7jp+olNmXqqZ3I3WsLg7jo33NCOAA3ej103kmo9ZvD9R1aakl7e9WKsdAw==} + peerDependencies: + umi: 3.x + + '@umijs/plugin-openapi@1.3.3': + resolution: {integrity: sha512-z1gJpX1MDAO5YlJH+zsQ4bq0jgmIoy89k5lyTylVvP22M31h7sC9cAwNHmQeJMzGatYooGJu//rnThsSlRdIUg==} + peerDependencies: + umi: 3.x + + '@umijs/plugin-request@2.8.0': + resolution: {integrity: sha512-bwJg0rFbMZcizO+fHbSNz6X/U6suR84ciLIo9zLtRMuradx/yanMnz+ckh2dlZvTlGYrckkJwWgoSFxWlU8yyA==} + peerDependencies: + umi: 3.x + + '@umijs/plugin-test@1.0.2': + resolution: {integrity: sha512-EIV86Xmw/Cn8vRLXha+ct0PfY6gRRKov5lanvt1B2L5t6xAqnTd03AxmB7i1Go9vDcFxDBheuDf/nyGiT/xTFw==} + peerDependencies: + umi: 3.x + + '@umijs/preset-built-in@3.5.43': + resolution: {integrity: sha512-h9DVc5MjdUON7/xH3bxq76AHDPBTLjntDWBrW6xn+OhDT4j8/YFXrDQwaCwihCJe1eNUBLoVUjWIEIthw7g1Gg==} + peerDependencies: + react: 16.x || 17.x + + '@umijs/preset-react@1.8.32': + resolution: {integrity: sha512-f/jJRxIRzRrZ040GMdBuV3byvtbx35oWymDT5A/q/e+QmjCrs6c9XCRktGInKIhZycqI/GuA6eLaxXIKvu6b9A==} + peerDependencies: + umi: 3.x + + '@umijs/renderer-mpa@3.5.43': + resolution: {integrity: sha512-posQsrkFru/Q9Jft42w4pr/MEFsImd9DlKOV9zYil1ZM6JBS3/hKMmCeSd2Uku7+KgSS/8HSfc4qX/GyeRTzwA==} + peerDependencies: + react: 16.x || 17.x + react-dom: 16.x || 17.x + + '@umijs/renderer-react@3.5.43': + resolution: {integrity: sha512-nadGLVbc6qrEX5pd+qY4nr9Mzl7x2hhxec2JeAd2Bg0JkZYNC8H4crTfe844uLm3MvqAtAhomGhN5c0ejDEBhA==} + peerDependencies: + react: 16.x || 17.x + react-dom: 16.x || 17.x + + '@umijs/route-utils@2.2.2': + resolution: {integrity: sha512-cMk6qizy0pfpiwpVCvNQB0BKBUJEH33pDv5q5k2tSleSDw2abkJkTu2Kd5hKzoESLuFK43oGeOfcplZqm2bRxw==} + + '@umijs/route-utils@4.0.1': + resolution: {integrity: sha512-+1ixf1BTOLuH+ORb4x8vYMPeIt38n9q0fJDwhv9nSxrV46mxbLF0nmELIo9CKQB2gHfuC4+hww6xejJ6VYnBHQ==} + + '@umijs/runtime@3.5.43': + resolution: {integrity: sha512-jCmkF5QcqbqzJgtd12Hy6XthLTAcaD4feMHnzM+UqTE74N7lfD13P0brXHrGqkcLbI1NgUs+9rKYIUa56w6jpw==} + peerDependencies: + react: 16.x || 17.x + + '@umijs/server@3.5.43': + resolution: {integrity: sha512-aUSNqnO6WvhgIU6jK1+2YCNkuP6UgiEhTaT/VkSPZdCjagfov2ZfJQ0xWl8x7tocuAaBph6UvXFJWjCQvZ5pHw==} + + '@umijs/test@3.5.43': + resolution: {integrity: sha512-9jrziC5ngjrfiJFSdhNDMYcQNrnCQoph/Bu8lZsuBmBQwswN3YqVqefDc4fh4Kl1e4OisKtDfUDtUro8ZApaRQ==} + hasBin: true + + '@umijs/types@3.5.43': + resolution: {integrity: sha512-XVZuT1X+VpPYrdlDEeginBwBNZaYUDtt3WOyFvfGmBEdqD0iNx0ZgyWmJBhlfRcck5+oYkFpOzmmRIROux2zlA==} + + '@umijs/use-params@1.0.9': + resolution: {integrity: sha512-QlN0RJSBVQBwLRNxbxjQ5qzqYIGn+K7USppMoIOVlf7fxXHsnQZ2bEsa6Pm74bt6DVQxpUE8HqvdStn6Y9FV1w==} + peerDependencies: + react: '*' + + '@umijs/utils@3.5.43': + resolution: {integrity: sha512-LQrCkZEa9Fb0zhId1n6CdU489tzJp4/usHVvVcTwjah7jF48zrHXD4OClGjSxvZ63d+3950mZY5IWE9UZVhnDg==} + + '@webassemblyjs/ast@1.14.1': + resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} + + '@webassemblyjs/floating-point-hex-parser@1.13.2': + resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==} + + '@webassemblyjs/helper-api-error@1.13.2': + resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==} + + '@webassemblyjs/helper-buffer@1.14.1': + resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==} + + '@webassemblyjs/helper-numbers@1.13.2': + resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==} + + '@webassemblyjs/helper-wasm-bytecode@1.13.2': + resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==} + + '@webassemblyjs/helper-wasm-section@1.14.1': + resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==} + + '@webassemblyjs/ieee754@1.13.2': + resolution: {integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==} + + '@webassemblyjs/leb128@1.13.2': + resolution: {integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==} + + '@webassemblyjs/utf8@1.13.2': + resolution: {integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==} + + '@webassemblyjs/wasm-edit@1.14.1': + resolution: {integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==} + + '@webassemblyjs/wasm-gen@1.14.1': + resolution: {integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==} + + '@webassemblyjs/wasm-opt@1.14.1': + resolution: {integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==} + + '@webassemblyjs/wasm-parser@1.14.1': + resolution: {integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==} + + '@webassemblyjs/wast-printer@1.14.1': + resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} + + '@webgpu/glslang@0.0.15': + resolution: {integrity: sha512-niT+Prh3Aff8Uf1MVBVUsaNjFj9rJAKDXuoHIKiQbB+6IUP/3J3JIhBNyZ7lDhytvXxw6ppgnwKZdDJ08UMj4Q==} + + '@webgpu/types@0.0.31': + resolution: {integrity: sha512-cvvCMSZBT4VsRNtt0lI6XQqvOIIWw6+NRUtnPUMDVDgsI4pCZColz3qzF5QcP9wIYOHEc3jssIBse8UWONKhlQ==} + + '@webgpu/types@0.1.60': + resolution: {integrity: sha512-8B/tdfRFKdrnejqmvq95ogp8tf52oZ51p3f4QD5m5Paey/qlX4Rhhy5Y8tgFMi7Ms70HzcMMw3EQjH/jdhTwlA==} + + '@xobotyi/scrollbar-width@1.9.5': + resolution: {integrity: sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==} + + '@xtuc/ieee754@1.2.0': + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + + '@xtuc/long@4.2.2': + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + + a-sync-waterfall@1.0.1: + resolution: {integrity: sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==} + + abab@2.0.6: + resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} + deprecated: Use your platform's native atob() and btoa() methods instead + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + acorn-globals@6.0.0: + resolution: {integrity: sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn-walk@7.2.0: + resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} + engines: {node: '>=0.4.0'} + + acorn-walk@8.3.4: + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} + engines: {node: '>=0.4.0'} + + acorn@7.4.1: + resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} + engines: {node: '>=0.4.0'} + hasBin: true + + acorn@8.14.1: + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} + engines: {node: '>=0.4.0'} + hasBin: true + + add-dom-event-listener@1.1.0: + resolution: {integrity: sha512-WCxx1ixHT0GQU9hb0KI/mhgRQhnU+U3GvwY6ZvVjYq8rsihIGoaIOUbY0yMPBxLH5MDtr0kz3fisWGNcbWW7Jw==} + + address@1.2.2: + resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} + engines: {node: '>= 10.0.0'} + + adjust-sourcemap-loader@4.0.0: + resolution: {integrity: sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==} + engines: {node: '>=8.9'} + + adler-32@1.2.0: + resolution: {integrity: sha512-/vUqU/UY4MVeFsg+SsK6c+/05RZXIHZMGJA+PX5JyWI0ZRcBpupnRuPLU/NXXoFwMYCPCoxIfElM2eS+DUXCqQ==} + engines: {node: '>=0.8'} + hasBin: true + + adler-32@1.3.1: + resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==} + engines: {node: '>=0.8'} + + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + + ahooks@2.10.14: + resolution: {integrity: sha512-axWa7VoAgu7bxA56dDl0CXW4rvaQmDBiov/d3tAy0x1YNYywYMKokL8TdLgJ5zO/oXGiWmG7BxlGOQGkqE/zkQ==} + engines: {node: '>=8.0.0'} + peerDependencies: + react: ^16.8.6 || ^17.0 + + ahooks@3.8.4: + resolution: {integrity: sha512-39wDEw2ZHvypaT14EpMMk4AzosHWt0z9bulY0BeDsvc9PqJEV+Kjh/4TZfftSsotBMq52iYIOFPd3PR56e0ZJg==} + engines: {node: '>=8.0.0'} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + + ajv-errors@1.0.1: + resolution: {integrity: sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==} + peerDependencies: + ajv: '>=5.0.0' + + ajv-formats@2.1.1: + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-keywords@3.5.2: + resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} + peerDependencies: + ajv: ^6.9.1 + + ajv-keywords@5.1.0: + resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} + peerDependencies: + ajv: ^8.8.2 + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + + align-text@0.1.4: + resolution: {integrity: sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==} + engines: {node: '>=0.10.0'} + + amdefine@1.0.1: + resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==} + engines: {node: '>=0.4.2'} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-html-community@0.0.8: + resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} + engines: {'0': node >= 0.8.0} + hasBin: true + + ansi-html@0.0.9: + resolution: {integrity: sha512-ozbS3LuenHVxNRh/wdnN16QapUHzauqSomAl1jwwJRRsGwFwtj644lIhxfWu0Fy0acCij2+AEgHvjscq3dlVXg==} + engines: {'0': node >= 0.8.0} + hasBin: true + + ansi-regex@2.1.1: + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + engines: {node: '>=0.10.0'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@2.2.1: + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} + engines: {node: '>=0.10.0'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + antd-mobile@2.3.4: + resolution: {integrity: sha512-Uw02Ghc+DPzaQceJQ+5p1ZnQFafvILA0chTTen7m7c89Uzbw6Ny3zsVZDE1gfteNEIsL4JpPe0I/+aI3Q/nPAA==} + + antd-style@3.7.1: + resolution: {integrity: sha512-CQOfddVp4aOvBfCepa+Kj2e7ap+2XBINg1Kn2osdE3oQvrD7KJu/K0sfnLcFLkgCJygbxmuazYdWLKb+drPDYA==} + peerDependencies: + antd: '>=5.8.1' + react: '>=18' + + antd@4.24.16: + resolution: {integrity: sha512-zZrK4UYxHtU6tGOOf0uG/kBRx1kTvypfuSB3GqE/SBQxFhZ/TZ+yj7Z1qwI8vGfMtUUJdLeuoCAqGDa1zPsXnQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + antd@5.24.8: + resolution: {integrity: sha512-vJcW81WSRq+ymBKTiA3NE+FddmiqTAKxdWVRZU+HnLLrRrIz896svcUxXFPa7M4mH9HqyeJ5JPOHsne4sQAC1A==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + anymatch@1.3.2: + resolution: {integrity: sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==} + + anymatch@2.0.0: + resolution: {integrity: sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arch@2.2.0: + resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} + + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + arr-diff@2.0.0: + resolution: {integrity: sha512-dtXTVMkh6VkEEA7OhXnN1Ecb8aAGFdZ1LFxtOCoqj4qkyOJMt7+qs6Ahdy6p/NQCPYsRSXXivhSB/J5E9jmYKA==} + engines: {node: '>=0.10.0'} + + arr-diff@4.0.0: + resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} + engines: {node: '>=0.10.0'} + + arr-flatten@1.1.0: + resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==} + engines: {node: '>=0.10.0'} + + arr-union@3.1.0: + resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} + engines: {node: '>=0.10.0'} + + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + array-includes@3.1.8: + resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} + engines: {node: '>= 0.4'} + + array-tree-filter@2.1.0: + resolution: {integrity: sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==} + + array-union@1.0.2: + resolution: {integrity: sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==} + engines: {node: '>=0.10.0'} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + array-uniq@1.0.3: + resolution: {integrity: sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==} + engines: {node: '>=0.10.0'} + + array-unique@0.2.1: + resolution: {integrity: sha512-G2n5bG5fSUCpnsXz4+8FUkYsGPkNfLn9YvS66U5qbTIXI2Ynnlo4Bi42bWv+omKUCqz+ejzfClwne0alJWJPhg==} + engines: {node: '>=0.10.0'} + + array-unique@0.3.2: + resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==} + engines: {node: '>=0.10.0'} + + array.prototype.findlast@1.2.5: + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} + + array.prototype.findlastindex@1.2.6: + resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==} + engines: {node: '>= 0.4'} + + array.prototype.flat@1.3.3: + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} + engines: {node: '>= 0.4'} + + array.prototype.flatmap@1.3.3: + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} + engines: {node: '>= 0.4'} + + array.prototype.reduce@1.0.8: + resolution: {integrity: sha512-DwuEqgXFBwbmZSRqt3BpQigWNUoqw9Ml2dTWdF3B2zQlQX4OeUE0zyuzX0fX0IbTvjdkZbcBTU3idgpO78qkTw==} + engines: {node: '>= 0.4'} + + array.prototype.tosorted@1.1.4: + resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} + + arrify@2.0.1: + resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==} + engines: {node: '>=8'} + + as-number@1.0.0: + resolution: {integrity: sha512-HkI/zLo2AbSRO4fqVkmyf3hms0bJDs3iboHqTrNuwTiCRvdYXM7HFhfhB6Dk51anV2LM/IMB83mtK9mHw4FlAg==} + + asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + + asn1.js@4.10.1: + resolution: {integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==} + + assert@1.5.1: + resolution: {integrity: sha512-zzw1uCAgLbsKwBfFc8CX78DDg+xZeBksSO3vwVIDDN5i94eOrPsSSyiVhmsSABFDM/OcpE2aagCat9dnWQLG1A==} + + assign-symbols@1.0.0: + resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} + engines: {node: '>=0.10.0'} + + ast-types-flow@0.0.8: + resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + + async-each@1.0.6: + resolution: {integrity: sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg==} + + async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} + + async-validator@1.11.5: + resolution: {integrity: sha512-XNtCsMAeAH1pdLMEg1z8/Bb3a8cdCbui9QbJATRFHHHW5kT6+NPI3zSVQUXgikTFITzsg+kYY5NTWhM2Orwt9w==} + + async-validator@4.2.5: + resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + + atob@2.1.2: + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} + engines: {node: '>= 4.5.0'} + hasBin: true + + autoprefixer@10.4.21: + resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + + autoprefixer@9.8.8: + resolution: {integrity: sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==} + hasBin: true + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + axe-core@4.10.3: + resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==} + engines: {node: '>=4'} + + axios@0.30.0: + resolution: {integrity: sha512-Z4F3LjCgfjZz8BMYalWdMgAQUnEtKDmpwNHjh/C8pQZWde32TF64cqnSeyL3xD/aTIASRU30RHTNzRiV/NpGMg==} + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + babel-cli@6.26.0: + resolution: {integrity: sha512-wau+BDtQfuSBGQ9PzzFL3REvR9Sxnd4LKwtcHAiPjhugA7K/80vpHXafj+O5bAqJOuSefjOx5ZJnNSR2J1Qw6Q==} + hasBin: true + + babel-code-frame@6.26.0: + resolution: {integrity: sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==} + + babel-core@6.26.3: + resolution: {integrity: sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==} + + babel-generator@6.26.1: + resolution: {integrity: sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==} + + babel-helper-call-delegate@6.24.1: + resolution: {integrity: sha512-RL8n2NiEj+kKztlrVJM9JT1cXzzAdvWFh76xh/H1I4nKwunzE4INBXn8ieCZ+wh4zWszZk7NBS1s/8HR5jDkzQ==} + + babel-helper-define-map@6.26.0: + resolution: {integrity: sha512-bHkmjcC9lM1kmZcVpA5t2om2nzT/xiZpo6TJq7UlZ3wqKfzia4veeXbIhKvJXAMzhhEBd3cR1IElL5AenWEUpA==} + + babel-helper-function-name@6.24.1: + resolution: {integrity: sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q==} + + babel-helper-get-function-arity@6.24.1: + resolution: {integrity: sha512-WfgKFX6swFB1jS2vo+DwivRN4NB8XUdM3ij0Y1gnC21y1tdBoe6xjVnd7NSI6alv+gZXCtJqvrTeMW3fR/c0ng==} + + babel-helper-hoist-variables@6.24.1: + resolution: {integrity: sha512-zAYl3tqerLItvG5cKYw7f1SpvIxS9zi7ohyGHaI9cgDUjAT6YcY9jIEH5CstetP5wHIVSceXwNS7Z5BpJg+rOw==} + + babel-helper-optimise-call-expression@6.24.1: + resolution: {integrity: sha512-Op9IhEaxhbRT8MDXx2iNuMgciu2V8lDvYCNQbDGjdBNCjaMvyLf4wl4A3b8IgndCyQF8TwfgsQ8T3VD8aX1/pA==} + + babel-helper-regex@6.26.0: + resolution: {integrity: sha512-VlPiWmqmGJp0x0oK27Out1D+71nVVCTSdlbhIVoaBAj2lUgrNjBCRR9+llO4lTSb2O4r7PJg+RobRkhBrf6ofg==} + + babel-helper-replace-supers@6.24.1: + resolution: {integrity: sha512-sLI+u7sXJh6+ToqDr57Bv973kCepItDhMou0xCP2YPVmR1jkHSCY+p1no8xErbV1Siz5QE8qKT1WIwybSWlqjw==} + + babel-helpers@6.24.1: + resolution: {integrity: sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ==} + + babel-jest@26.6.3: + resolution: {integrity: sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==} + engines: {node: '>= 10.14.2'} + peerDependencies: + '@babel/core': ^7.0.0 + + babel-jest@27.5.1: + resolution: {integrity: sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + + babel-loader@8.4.1: + resolution: {integrity: sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==} + engines: {node: '>= 8.9'} + peerDependencies: + '@babel/core': ^7.0.0 + webpack: '>=2' + + babel-messages@6.23.0: + resolution: {integrity: sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w==} + + babel-plugin-check-es2015-constants@6.22.0: + resolution: {integrity: sha512-B1M5KBP29248dViEo1owyY32lk1ZSH2DaNNrXLGt8lyjjHm7pBqAdQ7VKUPR6EEDO323+OvT3MQXbCin8ooWdA==} + + babel-plugin-dva-hmr@0.4.2: + resolution: {integrity: sha512-QP5W0IT9LDFgoqkXD0g7wn/FMn7zO562P8qys23twXri4i3E1SGOQ3z7jqcPrqzfTZHx+Ufr+cXy9oI6OLMYZg==} + peerDependencies: + redbox-react: 1.x + + babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + + babel-plugin-jest-hoist@26.6.2: + resolution: {integrity: sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==} + engines: {node: '>= 10.14.2'} + + babel-plugin-jest-hoist@27.5.1: + resolution: {integrity: sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + babel-plugin-macros@3.1.0: + resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} + engines: {node: '>=10', npm: '>=6'} + + babel-plugin-named-asset-import@0.3.8: + resolution: {integrity: sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==} + peerDependencies: + '@babel/core': ^7.1.0 + + babel-plugin-polyfill-corejs2@0.4.13: + resolution: {integrity: sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-corejs3@0.11.1: + resolution: {integrity: sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-regenerator@0.6.4: + resolution: {integrity: sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-transform-es2015-arrow-functions@6.22.0: + resolution: {integrity: sha512-PCqwwzODXW7JMrzu+yZIaYbPQSKjDTAsNNlK2l5Gg9g4rz2VzLnZsStvp/3c46GfXpwkyufb3NCyG9+50FF1Vg==} + + babel-plugin-transform-es2015-block-scoped-functions@6.22.0: + resolution: {integrity: sha512-2+ujAT2UMBzYFm7tidUsYh+ZoIutxJ3pN9IYrF1/H6dCKtECfhmB8UkHVpyxDwkj0CYbQG35ykoz925TUnBc3A==} + + babel-plugin-transform-es2015-block-scoping@6.26.0: + resolution: {integrity: sha512-YiN6sFAQ5lML8JjCmr7uerS5Yc/EMbgg9G8ZNmk2E3nYX4ckHR01wrkeeMijEf5WHNK5TW0Sl0Uu3pv3EdOJWw==} + + babel-plugin-transform-es2015-classes@6.24.1: + resolution: {integrity: sha512-5Dy7ZbRinGrNtmWpquZKZ3EGY8sDgIVB4CU8Om8q8tnMLrD/m94cKglVcHps0BCTdZ0TJeeAWOq2TK9MIY6cag==} + + babel-plugin-transform-es2015-computed-properties@6.24.1: + resolution: {integrity: sha512-C/uAv4ktFP/Hmh01gMTvYvICrKze0XVX9f2PdIXuriCSvUmV9j+u+BB9f5fJK3+878yMK6dkdcq+Ymr9mrcLzw==} + + babel-plugin-transform-es2015-destructuring@6.23.0: + resolution: {integrity: sha512-aNv/GDAW0j/f4Uy1OEPZn1mqD+Nfy9viFGBfQ5bZyT35YqOiqx7/tXdyfZkJ1sC21NyEsBdfDY6PYmLHF4r5iA==} + + babel-plugin-transform-es2015-duplicate-keys@6.24.1: + resolution: {integrity: sha512-ossocTuPOssfxO2h+Z3/Ea1Vo1wWx31Uqy9vIiJusOP4TbF7tPs9U0sJ9pX9OJPf4lXRGj5+6Gkl/HHKiAP5ug==} + + babel-plugin-transform-es2015-for-of@6.23.0: + resolution: {integrity: sha512-DLuRwoygCoXx+YfxHLkVx5/NpeSbVwfoTeBykpJK7JhYWlL/O8hgAK/reforUnZDlxasOrVPPJVI/guE3dCwkw==} + + babel-plugin-transform-es2015-function-name@6.24.1: + resolution: {integrity: sha512-iFp5KIcorf11iBqu/y/a7DK3MN5di3pNCzto61FqCNnUX4qeBwcV1SLqe10oXNnCaxBUImX3SckX2/o1nsrTcg==} + + babel-plugin-transform-es2015-literals@6.22.0: + resolution: {integrity: sha512-tjFl0cwMPpDYyoqYA9li1/7mGFit39XiNX5DKC/uCNjBctMxyL1/PT/l4rSlbvBG1pOKI88STRdUsWXB3/Q9hQ==} + + babel-plugin-transform-es2015-modules-amd@6.24.1: + resolution: {integrity: sha512-LnIIdGWIKdw7zwckqx+eGjcS8/cl8D74A3BpJbGjKTFFNJSMrjN4bIh22HY1AlkUbeLG6X6OZj56BDvWD+OeFA==} + + babel-plugin-transform-es2015-modules-commonjs@6.26.2: + resolution: {integrity: sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==} + + babel-plugin-transform-es2015-modules-systemjs@6.24.1: + resolution: {integrity: sha512-ONFIPsq8y4bls5PPsAWYXH/21Hqv64TBxdje0FvU3MhIV6QM2j5YS7KvAzg/nTIVLot2D2fmFQrFWCbgHlFEjg==} + + babel-plugin-transform-es2015-modules-umd@6.24.1: + resolution: {integrity: sha512-LpVbiT9CLsuAIp3IG0tfbVo81QIhn6pE8xBJ7XSeCtFlMltuar5VuBV6y6Q45tpui9QWcy5i0vLQfCfrnF7Kiw==} + + babel-plugin-transform-es2015-object-super@6.24.1: + resolution: {integrity: sha512-8G5hpZMecb53vpD3mjs64NhI1au24TAmokQ4B+TBFBjN9cVoGoOvotdrMMRmHvVZUEvqGUPWL514woru1ChZMA==} + + babel-plugin-transform-es2015-parameters@6.24.1: + resolution: {integrity: sha512-8HxlW+BB5HqniD+nLkQ4xSAVq3bR/pcYW9IigY+2y0dI+Y7INFeTbfAQr+63T3E4UDsZGjyb+l9txUnABWxlOQ==} + + babel-plugin-transform-es2015-shorthand-properties@6.24.1: + resolution: {integrity: sha512-mDdocSfUVm1/7Jw/FIRNw9vPrBQNePy6wZJlR8HAUBLybNp1w/6lr6zZ2pjMShee65t/ybR5pT8ulkLzD1xwiw==} + + babel-plugin-transform-es2015-spread@6.22.0: + resolution: {integrity: sha512-3Ghhi26r4l3d0Js933E5+IhHwk0A1yiutj9gwvzmFbVV0sPMYk2lekhOufHBswX7NCoSeF4Xrl3sCIuSIa+zOg==} + + babel-plugin-transform-es2015-sticky-regex@6.24.1: + resolution: {integrity: sha512-CYP359ADryTo3pCsH0oxRo/0yn6UsEZLqYohHmvLQdfS9xkf+MbCzE3/Kolw9OYIY4ZMilH25z/5CbQbwDD+lQ==} + + babel-plugin-transform-es2015-template-literals@6.22.0: + resolution: {integrity: sha512-x8b9W0ngnKzDMHimVtTfn5ryimars1ByTqsfBDwAqLibmuuQY6pgBQi5z1ErIsUOWBdw1bW9FSz5RZUojM4apg==} + + babel-plugin-transform-es2015-typeof-symbol@6.23.0: + resolution: {integrity: sha512-fz6J2Sf4gYN6gWgRZaoFXmq93X+Li/8vf+fb0sGDVtdeWvxC9y5/bTD7bvfWMEq6zetGEHpWjtzRGSugt5kNqw==} + + babel-plugin-transform-es2015-unicode-regex@6.24.1: + resolution: {integrity: sha512-v61Dbbihf5XxnYjtBN04B/JBvsScY37R1cZT5r9permN1cp+b70DY3Ib3fIkgn1DI9U3tGgBJZVD8p/mE/4JbQ==} + + babel-plugin-transform-react-remove-prop-types@0.4.24: + resolution: {integrity: sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==} + + babel-plugin-transform-regenerator@6.26.0: + resolution: {integrity: sha512-LS+dBkUGlNR15/5WHKe/8Neawx663qttS6AGqoOUhICc9d1KciBvtrQSuc0PI+CxQ2Q/S1aKuJ+u64GtLdcEZg==} + + babel-plugin-transform-strict-mode@6.24.1: + resolution: {integrity: sha512-j3KtSpjyLSJxNoCDrhwiJad8kw0gJ9REGj8/CqL0HeRyLnvUNYV9zcqluL6QJSXh3nfsLEmSLvwRfGzrgR96Pw==} + + babel-polyfill@6.26.0: + resolution: {integrity: sha512-F2rZGQnAdaHWQ8YAoeRbukc7HS9QgdgeyJ0rQDd485v9opwuPvjpPFcOOT/WmkKTdgy9ESgSPXDcTNpzrGr6iQ==} + + babel-preset-current-node-syntax@1.1.0: + resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} + peerDependencies: + '@babel/core': ^7.0.0 + + babel-preset-es2015@6.24.1: + resolution: {integrity: sha512-XfwUqG1Ry6R43m4Wfob+vHbIVBIqTg/TJY4Snku1iIzeH7mUnwHA8Vagmv+ZQbPwhS8HgsdQvy28Py3k5zpoFQ==} + deprecated: '🙌 Thanks for using Babel: we recommend using babel-preset-env now: please read https://babeljs.io/env to update!' + + babel-preset-jest@26.6.2: + resolution: {integrity: sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ==} + engines: {node: '>= 10.14.2'} + peerDependencies: + '@babel/core': ^7.0.0 + + babel-preset-jest@27.5.1: + resolution: {integrity: sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + + babel-preset-react-app@10.1.0: + resolution: {integrity: sha512-f9B1xMdnkCIqe+2dHrJsoQFRz7reChaAHE/65SdaykPklQqhme2WaC08oD3is77x9ff98/9EazAKFDZv5rFEQg==} + + babel-register@6.26.0: + resolution: {integrity: sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A==} + + babel-runtime@6.26.0: + resolution: {integrity: sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==} + + babel-template@6.26.0: + resolution: {integrity: sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg==} + + babel-traverse@6.26.0: + resolution: {integrity: sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA==} + + babel-types@6.26.0: + resolution: {integrity: sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==} + + babylon@6.18.0: + resolution: {integrity: sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==} + hasBin: true + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base16@1.0.0: + resolution: {integrity: sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + base@0.11.2: + resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} + engines: {node: '>=0.10.0'} + + batch-processor@1.0.0: + resolution: {integrity: sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA==} + + batch@0.6.1: + resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} + + bfj@7.1.0: + resolution: {integrity: sha512-I6MMLkn+anzNdCUp9hMRyui1HaNEUCco50lxbvNS4+EyXg8lN3nJ48PjPWtbH8UVS9CuMoaKE9U2V3l29DaRQw==} + engines: {node: '>= 8.0.0'} + + big.js@5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + + bignumber.js@9.3.0: + resolution: {integrity: sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==} + + binary-extensions@1.13.1: + resolution: {integrity: sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==} + engines: {node: '>=0.10.0'} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + bindings@1.5.0: + resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + + bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + + bn.js@4.12.2: + resolution: {integrity: sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==} + + bn.js@5.2.2: + resolution: {integrity: sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==} + + body-parser@1.20.3: + resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + bonjour-service@1.3.0: + resolution: {integrity: sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@1.8.5: + resolution: {integrity: sha512-xU7bpz2ytJl1bH9cgIurjpg/n8Gohy9GTw81heDYLJQ4RU60dlyJsa+atVF2pI0yMMvKxI9HkKwjePCj5XI1hw==} + engines: {node: '>=0.10.0'} + + braces@2.3.2: + resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} + engines: {node: '>=0.10.0'} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + brorand@1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + + browser-process-hrtime@1.0.0: + resolution: {integrity: sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==} + + browserify-aes@1.2.0: + resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + + browserify-cipher@1.0.1: + resolution: {integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==} + + browserify-des@1.0.2: + resolution: {integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==} + + browserify-rsa@4.1.1: + resolution: {integrity: sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==} + engines: {node: '>= 0.10'} + + browserify-sign@4.2.3: + resolution: {integrity: sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==} + engines: {node: '>= 0.12'} + + browserify-zlib@0.2.0: + resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==} + + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + buffer-xor@1.0.3: + resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + + buffer@4.9.2: + resolution: {integrity: sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==} + + builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + + builtin-status-codes@3.0.0: + resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + bytewise-core@1.2.3: + resolution: {integrity: sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA==} + + bytewise@1.1.0: + resolution: {integrity: sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ==} + + cache-base@1.0.1: + resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} + engines: {node: '>=0.10.0'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + call-me-maybe@1.0.2: + resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==} + + caller-callsite@2.0.0: + resolution: {integrity: sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==} + engines: {node: '>=4'} + + caller-path@2.0.0: + resolution: {integrity: sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==} + engines: {node: '>=4'} + + callsites@2.0.0: + resolution: {integrity: sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==} + engines: {node: '>=4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camel-case@4.1.2: + resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} + + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + + camelcase@1.2.1: + resolution: {integrity: sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==} + engines: {node: '>=0.10.0'} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-api@3.0.0: + resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} + + caniuse-lite@1.0.30001715: + resolution: {integrity: sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==} + + capture-exit@2.0.0: + resolution: {integrity: sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==} + engines: {node: 6.* || 8.* || >= 10.*} + + case-sensitive-paths-webpack-plugin@2.4.0: + resolution: {integrity: sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==} + engines: {node: '>=4'} + + center-align@0.1.3: + resolution: {integrity: sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==} + engines: {node: '>=0.10.0'} + + cfb@1.2.2: + resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==} + engines: {node: '>=0.8'} + + chalk@1.1.3: + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} + engines: {node: '>=0.10.0'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + change-emitter@0.1.6: + resolution: {integrity: sha512-YXzt1cQ4a2jqazhcuSWEOc1K2q8g9H6eWNsyZgi640LDzRWVQ2eDe+Y/kVdftH+vYdPF2rgDb3dLdpxE1jvAxw==} + + char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + + char-regex@2.0.2: + resolution: {integrity: sha512-cbGOjAptfM2LVmWhwRFHEKTPkLwNddVmuqYZQt895yXwAsWsXObCG+YN4DGQ/JBtT4GP1a1lPPdio2z413LmTg==} + engines: {node: '>=12.20'} + + check-types@11.2.3: + resolution: {integrity: sha512-+67P1GkJRaxQD6PKK0Et9DhwQB+vGg3PM5+aavopCpZT1lj9jeqfvpgTLAWErNj8qApkkmXlu/Ug74kmhagkXg==} + + chokidar@1.7.0: + resolution: {integrity: sha512-mk8fAWcRUOxY7btlLtitj3A45jOwSAxH4tOFOoEGbVsl6cL6pPMWUy7dwZ/canfj3QEdP6FHSnf/l1c6/WkzVg==} + + chokidar@3.5.1: + resolution: {integrity: sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==} + engines: {node: '>= 8.10.0'} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + chrome-trace-event@1.0.4: + resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} + engines: {node: '>=6.0'} + + ci-info@1.6.0: + resolution: {integrity: sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==} + + ci-info@2.0.0: + resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + cipher-base@1.0.6: + resolution: {integrity: sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==} + engines: {node: '>= 0.10'} + + cjs-module-lexer@0.6.0: + resolution: {integrity: sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw==} + + cjs-module-lexer@1.4.3: + resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} + + clamp@1.0.1: + resolution: {integrity: sha512-kgMuFyE78OC6Dyu3Dy7vcx4uy97EIbVxJB/B0eJ3bUNAkwdNcxYzgKltnyADiYwsR7SEqkkUPsEUT//OVS6XMA==} + + class-utils@0.3.6: + resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} + engines: {node: '>=0.10.0'} + + classnames@2.5.1: + resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} + + clean-css@4.2.4: + resolution: {integrity: sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==} + engines: {node: '>= 4.0'} + + clean-css@5.3.3: + resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} + engines: {node: '>= 10.0'} + + clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + + cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + + cli-truncate@2.1.0: + resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} + engines: {node: '>=8'} + + clipboardy@2.3.0: + resolution: {integrity: sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==} + engines: {node: '>=8'} + + cliui@2.1.0: + resolution: {integrity: sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==} + + cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + + coa@2.0.2: + resolution: {integrity: sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==} + engines: {node: '>= 4.0'} + + codepage@1.15.0: + resolution: {integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==} + engines: {node: '>=0.8'} + + collect-v8-coverage@1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + + collection-visit@1.0.0: + resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} + engines: {node: '>=0.10.0'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@3.2.1: + resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + + colord@2.9.3: + resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} + + 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'} + + commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + + commander@13.1.0: + resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} + engines: {node: '>=18'} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + commander@5.1.0: + resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} + engines: {node: '>= 6'} + + commander@6.2.1: + resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} + engines: {node: '>= 6'} + + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + + common-tags@1.8.2: + resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} + engines: {node: '>=4.0.0'} + + commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + + component-classes@1.2.6: + resolution: {integrity: sha512-hPFGULxdwugu1QWW3SvVOCUHLzO34+a2J6Wqy0c5ASQkfi9/8nZcBB0ZohaEbXOQlCflMAEMmEWk7u7BVs4koA==} + + component-emitter@1.3.1: + resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} + + component-indexof@0.0.3: + resolution: {integrity: sha512-puDQKvx/64HZXb4hBwIcvQLaLgux8o1CbWl39s41hrIIZDl1lJiD5jc22gj3RBeGK0ovxALDYpIbyjqDUUl0rw==} + + compressible@2.0.18: + resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} + engines: {node: '>= 0.6'} + + compression@1.8.0: + resolution: {integrity: sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==} + engines: {node: '>= 0.8.0'} + + compute-scroll-into-view@1.0.20: + resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==} + + compute-scroll-into-view@3.1.1: + resolution: {integrity: sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + confusing-browser-globals@1.0.11: + resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} + + connect-history-api-fallback@2.0.0: + resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==} + engines: {node: '>=0.8'} + + connected-react-router@6.5.2: + resolution: {integrity: sha512-qzsLPZCofSI80fwy+HgxtEgSGS4ndYUUZAWaw1dqaOGPLKX/FVwIOEb7q+hjHdnZ4v5pKZcNv5GG4urjujIoyA==} + peerDependencies: + history: ^4.7.2 + react: ^16.4.0 + react-redux: ^6.0.0 || ^7.1.0 + react-router: ^4.3.1 || ^5.0.0 + redux: ^3.6.0 || ^4.0.0 + + console-browserify@1.2.0: + resolution: {integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==} + + constants-browserify@1.0.0: + resolution: {integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==} + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + contour_plot@0.0.1: + resolution: {integrity: sha512-Nil2HI76Xux6sVGORvhSS8v66m+/h5CwFkBJDO+U5vWaMdNC0yXNCsGDPbzPhvqOEU5koebhdEvD372LI+IyLw==} + + convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + + cookie@0.7.1: + resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} + engines: {node: '>= 0.6'} + + copy-descriptor@0.1.1: + resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} + engines: {node: '>=0.10.0'} + + copy-to-clipboard@3.3.3: + resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} + + core-js-compat@3.41.0: + resolution: {integrity: sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==} + + core-js-pure@3.41.0: + resolution: {integrity: sha512-71Gzp96T9YPk63aUvE5Q5qP+DryB4ZloUZPSOebGM88VNw8VNfvdA7z6kGA8iGOTEzAomsRidp4jXSmUIJsL+Q==} + + core-js@1.2.7: + resolution: {integrity: sha512-ZiPp9pZlgxpWRu0M+YWbm6+aQ84XEfH1JRXvfOc/fILWI0VKhLC2LX13X1NYq4fULzLMq7Hfh43CSo2/aIaUPA==} + deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js. + + core-js@2.6.12: + resolution: {integrity: sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==} + deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js. + + core-js@3.41.0: + resolution: {integrity: sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==} + + core-js@3.6.5: + resolution: {integrity: sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==} + deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js. + + core-js@3.8.2: + resolution: {integrity: sha512-FfApuSRgrR6G5s58casCBd9M2k+4ikuu4wbW6pJyYU7bd9zvFc9qf7vr5xmrZOhT9nn+8uwlH1oRR9jTnFoA3A==} + deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js. + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cosmiconfig@5.2.1: + resolution: {integrity: sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==} + engines: {node: '>=4'} + + cosmiconfig@6.0.0: + resolution: {integrity: sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==} + engines: {node: '>=8'} + + cosmiconfig@7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + + cosmiconfig@9.0.0: + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + cp-file@7.0.0: + resolution: {integrity: sha512-0Cbj7gyvFVApzpK/uhCtQ/9kE9UnYpxMzaq5nQQC/Dh4iaj5fxp7iEFIullrYwzj8nf0qnsI1Qsx34hAeAebvw==} + engines: {node: '>=8'} + + cpy@8.1.2: + resolution: {integrity: sha512-dmC4mUesv0OYH2kNFEidtf/skUwv4zePmGeepjyyJ0qTo5+8KhA1o99oIAwVVLzQMAeDJml74d6wPPKb6EZUTg==} + engines: {node: '>=8'} + + crc-32@1.2.2: + resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} + engines: {node: '>=0.8'} + hasBin: true + + create-ecdh@4.0.4: + resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} + + create-hash@1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + + create-hmac@1.1.7: + resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + + create-react-class@15.7.0: + resolution: {integrity: sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng==} + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + cross-fetch@3.2.0: + resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} + + cross-spawn@5.1.0: + resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + + cross-spawn@6.0.6: + resolution: {integrity: sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==} + engines: {node: '>=4.8'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + crypto-browserify@3.12.1: + resolution: {integrity: sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==} + engines: {node: '>= 0.10'} + + crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + + crypto-random-string@2.0.0: + resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} + engines: {node: '>=8'} + + crypto-random-string@5.0.0: + resolution: {integrity: sha512-KWjTXWwxFd6a94m5CdRGW/t82Tr8DoBc9dNnPCAbFI1EBweN6v1tv8y4Y1m7ndkp/nkIBRxUxAzpaBnR2k3bcQ==} + engines: {node: '>=14.16'} + + css-animation@1.6.1: + resolution: {integrity: sha512-/48+/BaEaHRY6kNQ2OIPzKf9A6g8WjZYjhiNDNuIVbsm5tXCGIAsHDjB4Xu1C4vXJtUWZo26O68OQkDpNBaPog==} + + css-blank-pseudo@0.1.4: + resolution: {integrity: sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w==} + engines: {node: '>=6.0.0'} + hasBin: true + + css-blank-pseudo@3.0.3: + resolution: {integrity: sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==} + engines: {node: ^12 || ^14 || >=16} + hasBin: true + peerDependencies: + postcss: ^8.4 + + css-box-model@1.2.1: + resolution: {integrity: sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==} + + css-declaration-sorter@6.4.1: + resolution: {integrity: sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==} + engines: {node: ^10 || ^12 || >=14} + peerDependencies: + postcss: ^8.0.9 + + css-has-pseudo@0.10.0: + resolution: {integrity: sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + css-has-pseudo@3.0.4: + resolution: {integrity: sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==} + engines: {node: ^12 || ^14 || >=16} + hasBin: true + peerDependencies: + postcss: ^8.4 + + css-in-js-utils@3.1.0: + resolution: {integrity: sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==} + + css-loader@6.11.0: + resolution: {integrity: sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==} + engines: {node: '>= 12.13.0'} + peerDependencies: + '@rspack/core': 0.x || 1.x + webpack: ^5.0.0 + peerDependenciesMeta: + '@rspack/core': + optional: true + webpack: + optional: true + + css-minimizer-webpack-plugin@3.4.1: + resolution: {integrity: sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==} + engines: {node: '>= 12.13.0'} + peerDependencies: + '@parcel/css': '*' + clean-css: '*' + csso: '*' + esbuild: '*' + webpack: ^5.0.0 + peerDependenciesMeta: + '@parcel/css': + optional: true + clean-css: + optional: true + csso: + optional: true + esbuild: + optional: true + + css-prefers-color-scheme@3.1.1: + resolution: {integrity: sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg==} + engines: {node: '>=6.0.0'} + hasBin: true + + css-prefers-color-scheme@6.0.3: + resolution: {integrity: sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==} + engines: {node: ^12 || ^14 || >=16} + hasBin: true + peerDependencies: + postcss: ^8.4 + + css-select-base-adapter@0.1.1: + resolution: {integrity: sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==} + + css-select@2.1.0: + resolution: {integrity: sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==} + + css-select@4.3.0: + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + + css-tree@1.0.0-alpha.37: + resolution: {integrity: sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==} + engines: {node: '>=8.0.0'} + + css-tree@1.1.3: + resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} + engines: {node: '>=8.0.0'} + + css-what@3.4.2: + resolution: {integrity: sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==} + engines: {node: '>= 6'} + + css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + + csscolorparser@1.0.3: + resolution: {integrity: sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==} + + cssdb@4.4.0: + resolution: {integrity: sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ==} + + cssdb@7.11.2: + resolution: {integrity: sha512-lhQ32TFkc1X4eTefGfYPvgovRSzIMofHkigfH8nWtyRL4XJLsRhJFreRvEgKzept7x1rjBuy3J/MurXLaFxW/A==} + + cssesc@2.0.0: + resolution: {integrity: sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==} + engines: {node: '>=4'} + hasBin: true + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + cssnano-preset-default@5.2.14: + resolution: {integrity: sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + cssnano-utils@3.1.0: + resolution: {integrity: sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + cssnano@5.1.15: + resolution: {integrity: sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + csso@4.2.0: + resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==} + engines: {node: '>=8.0.0'} + + cssom@0.3.8: + resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} + + cssom@0.4.4: + resolution: {integrity: sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==} + + cssstyle@2.3.0: + resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} + engines: {node: '>=8'} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + d3-array@1.2.4: + resolution: {integrity: sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==} + + d3-array@2.12.1: + resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==} + + d3-collection@1.0.7: + resolution: {integrity: sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==} + + d3-color@1.4.1: + resolution: {integrity: sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==} + + d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + + d3-dispatch@2.0.0: + resolution: {integrity: sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA==} + + d3-dsv@1.2.0: + resolution: {integrity: sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==} + hasBin: true + + d3-ease@1.0.7: + resolution: {integrity: sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==} + + d3-force@2.1.1: + resolution: {integrity: sha512-nAuHEzBqMvpFVMf9OX75d00OxvOXdxY+xECIXjW6Gv8BRrXu6gAWbv/9XKrvfJ5i5DCokDW7RYE50LRoK092ew==} + + d3-format@1.4.5: + resolution: {integrity: sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==} + + d3-hexbin@0.2.2: + resolution: {integrity: sha512-KS3fUT2ReD4RlGCjvCEm1RgMtp2NFZumdMu4DBzQK8AZv3fXRM6Xm8I4fSU07UXvH4xxg03NwWKWdvxfS/yc4w==} + + d3-hierarchy@2.0.0: + resolution: {integrity: sha512-SwIdqM3HxQX2214EG9GTjgmCc/mbSx4mQBn+DuEETubhOw6/U3fmnji4uCVrmzOydMHSO1nZle5gh6HB/wdOzw==} + + d3-interpolate@1.4.0: + resolution: {integrity: sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==} + + d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + + d3-quadtree@2.0.0: + resolution: {integrity: sha512-b0Ed2t1UUalJpc3qXzKi+cPGxeXRr4KU9YSlocN74aTzp6R/Ud43t79yLLqxHRWZfsvWXmbDWPpoENK1K539xw==} + + d3-regression@1.3.10: + resolution: {integrity: sha512-PF8GWEL70cHHWpx2jUQXc68r1pyPHIA+St16muk/XRokETzlegj5LriNKg7o4LR0TySug4nHYPJNNRz/W+/Niw==} + + d3-scale@2.2.2: + resolution: {integrity: sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==} + + d3-time-format@2.3.0: + resolution: {integrity: sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==} + + d3-time@1.1.0: + resolution: {integrity: sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==} + + d3-timer@1.0.10: + resolution: {integrity: sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==} + + d3-timer@2.0.0: + resolution: {integrity: sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA==} + + d@1.0.2: + resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} + engines: {node: '>=0.12'} + + dagre-compound@0.0.11: + resolution: {integrity: sha512-UrSgRP9LtOZCYb9e5doolZXpc7xayyszgyOs7uakTK4n4KsLegLVTRRtq01GpQd/iZjYw5fWMapx9ed+c80MAQ==} + engines: {node: '>=6.0.0'} + peerDependencies: + dagre: ^0.8.5 + + dagre@0.8.5: + resolution: {integrity: sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==} + + damerau-levenshtein@1.0.8: + resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + + data-urls@2.0.0: + resolution: {integrity: sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==} + engines: {node: '>=10'} + + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + + date-fns@2.30.0: + resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} + engines: {node: '>=0.11'} + + dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + + decimal.js@10.5.0: + resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==} + + decode-uri-component@0.2.2: + resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} + engines: {node: '>=0.10'} + + decode-uri-component@0.4.1: + resolution: {integrity: sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==} + engines: {node: '>=14.16'} + + dedent@0.7.0: + resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} + + deep-equal@1.1.2: + resolution: {integrity: sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==} + engines: {node: '>= 0.4'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + deepmerge@1.5.2: + resolution: {integrity: sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==} + engines: {node: '>=0.10.0'} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + default-gateway@6.0.3: + resolution: {integrity: sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==} + engines: {node: '>= 10'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + define-property@0.2.5: + resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} + engines: {node: '>=0.10.0'} + + define-property@1.0.0: + resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==} + engines: {node: '>=0.10.0'} + + define-property@2.0.2: + resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} + engines: {node: '>=0.10.0'} + + defined@1.0.1: + resolution: {integrity: sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + depd@1.1.2: + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + des.js@1.1.0: + resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + detect-browser@4.8.0: + resolution: {integrity: sha512-f4h2dFgzHUIpjpBLjhnDIteXv8VQiUm8XzAuzQtYUqECX/eKh67ykuiVoyb7Db7a0PUSmJa3OGXStG0CbQFUVw==} + + detect-browser@5.3.0: + resolution: {integrity: sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==} + + detect-indent@4.0.0: + resolution: {integrity: sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A==} + engines: {node: '>=0.10.0'} + + detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + + detect-node@2.1.0: + resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + + detect-port-alt@1.1.6: + resolution: {integrity: sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==} + engines: {node: '>= 4.2.1'} + hasBin: true + + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + + diff-sequences@26.6.2: + resolution: {integrity: sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==} + engines: {node: '>= 10.14.2'} + + diff-sequences@27.5.1: + resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + + diff@5.2.0: + resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} + engines: {node: '>=0.3.1'} + + diffie-hellman@5.0.3: + resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} + + dir-glob@2.2.2: + resolution: {integrity: sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==} + engines: {node: '>=4'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + + dns-packet@5.6.1: + resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} + engines: {node: '>=6'} + + doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + + dom-align@1.12.4: + resolution: {integrity: sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==} + + dom-converter@0.2.0: + resolution: {integrity: sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==} + + dom-scroll-into-view@1.2.1: + resolution: {integrity: sha512-LwNVg3GJOprWDO+QhLL1Z9MMgWe/KAFLxVWKzjRTxNSPn8/LLDIfmuG71YHznXCqaqTjvHJDYO1MEAgX6XCNbQ==} + + dom-serializer@0.2.2: + resolution: {integrity: sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==} + + dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + + dom-walk@0.1.2: + resolution: {integrity: sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==} + + domain-browser@1.2.0: + resolution: {integrity: sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==} + engines: {node: '>=0.4', npm: '>=1.2'} + + domelementtype@1.3.1: + resolution: {integrity: sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domexception@2.0.1: + resolution: {integrity: sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==} + engines: {node: '>=8'} + deprecated: Use your platform's native DOMException instead + + domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + + domutils@1.7.0: + resolution: {integrity: sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==} + + domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + + dot-case@3.0.4: + resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + + dotenv-expand@5.1.0: + resolution: {integrity: sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==} + + dotenv@10.0.0: + resolution: {integrity: sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==} + engines: {node: '>=10'} + + dotenv@16.5.0: + resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} + engines: {node: '>=12'} + + dotignore@0.1.2: + resolution: {integrity: sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw==} + hasBin: true + + draft-js@0.10.5: + resolution: {integrity: sha512-LE6jSCV9nkPhfVX2ggcRLA4FKs6zWq9ceuO/88BpXdNCS7mjRTgs0NsV6piUCJX9YxMsB9An33wnkMmU2sD2Zg==} + peerDependencies: + react: ^0.14.0 || ^15.0.0-rc || ^16.0.0-rc || ^16.0.0 + react-dom: ^0.14.0 || ^15.0.0-rc || ^16.0.0-rc || ^16.0.0 + + drange@1.1.1: + resolution: {integrity: sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==} + engines: {node: '>=4'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + + dva-core@2.0.4: + resolution: {integrity: sha512-Zh39llFyItu9HKXKfCZVf9UFtDTcypdAjGBew1S+wK8BGVzFpm1GPTdd6uIMeg7O6STtCvt2Qv+RwUut1GFynA==} + peerDependencies: + redux: 4.x + + dva-immer@0.5.2: + resolution: {integrity: sha512-xg23ktGsrdzgiU0ACl8vFm2+E2GBWbtXndXRKM9wtHDR+yMH27NfttVuAZQWvv4aaj6f5/bC+TdsZ9t7n6cAhQ==} + peerDependencies: + dva: ^2.5.0-0 + + dva-loading@3.0.25: + resolution: {integrity: sha512-RYbpSjvPj2NF+3YSc9QkDpwM1wO8uRAVfU6VGSgIxA2kA/Xd6yoY+VQM7GDRnvCvT579pESeBZBXk+8WKWOdDA==} + peerDependencies: + dva-core: ^1.1.0 || ^1.5.0-0 || ^1.6.0-0 + + dva@2.6.0-beta.23: + resolution: {integrity: sha512-noeOz3Erxpc6YLEsyyS//zGszeRYWKEvZoeCZ0LaCvWrV7Cxah9Xt/I9V1SS9eYDySaSgTUOoU+dLweQpCScAA==} + peerDependencies: + react: ^16.8.4 + react-dom: ^16.8.4 + + earcut@2.2.4: + resolution: {integrity: sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + + electron-to-chromium@1.5.143: + resolution: {integrity: sha512-QqklJMOFBMqe46k8iIOwA9l2hz57V2OKMmP5eSWcUvwx+mASAsbU+wkF1pHjn9ZVSBPrsYWr4/W/95y5SwYg2g==} + + element-resize-detector@1.2.4: + resolution: {integrity: sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg==} + + elliptic@6.6.1: + resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} + + emittery@0.10.2: + resolution: {integrity: sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==} + engines: {node: '>=12'} + + emittery@0.7.2: + resolution: {integrity: sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==} + engines: {node: '>=10'} + + emittery@0.8.1: + resolution: {integrity: sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==} + engines: {node: '>=10'} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + emojis-list@3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + + enhanced-resolve@5.18.1: + resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} + engines: {node: '>=10.13.0'} + + enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + + entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + error-stack-parser@1.3.6: + resolution: {integrity: sha512-xhuSYd8wLgOXwNgjcPeXMPL/IiiA1Huck+OPvClpJViVNNlJVtM41o+1emp7bPvlCJwCatFX2DWc05/DgfbWzA==} + + error-stack-parser@2.1.4: + resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} + + es-abstract@1.23.9: + resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} + engines: {node: '>= 0.4'} + + es-array-method-boxes-properly@1.0.0: + resolution: {integrity: sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-iterator-helpers@1.2.1: + resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} + engines: {node: '>= 0.4'} + + es-module-lexer@0.7.1: + resolution: {integrity: sha512-MgtWFl5No+4S3TmhDmCz2ObFGm6lEpTnzbQi+Dd+pw4mlTIZTmM2iAs5gRlmx5zS9luzobCSBSI90JM/1/JgOw==} + + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es-shim-unscopables@1.1.0: + resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + + es5-ext@0.10.64: + resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==} + engines: {node: '>=0.10'} + + es5-imcompatible-versions@0.1.90: + resolution: {integrity: sha512-2MPI0t/VV4j/oz1qbMekb4gCW81dewTpM2XJHKnPpZiPGu+1rVWmhTnwcq1vt8AFwWrkNF4RE7OZ9ibnKFYKwg==} + + es6-iterator@2.0.3: + resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} + + es6-promise@3.3.1: + resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} + + es6-symbol@3.1.4: + resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==} + engines: {node: '>=0.12'} + + es6-weak-map@2.0.3: + resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==} + + esbuild@0.12.15: + resolution: {integrity: sha512-72V4JNd2+48eOVCXx49xoSWHgC3/cCy96e7mbXKY+WOWghN00cCmlGnwVLRhRHorvv0dgCyuMYBZlM2xDM5OQw==} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + escodegen@1.14.3: + resolution: {integrity: sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==} + engines: {node: '>=4.0'} + hasBin: true + + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + + eslint-config-react-app@7.0.1: + resolution: {integrity: sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==} + engines: {node: '>=14.0.0'} + peerDependencies: + eslint: ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + + eslint-module-utils@2.12.0: + resolution: {integrity: sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + + eslint-plugin-flowtype@8.0.3: + resolution: {integrity: sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@babel/plugin-syntax-flow': ^7.14.5 + '@babel/plugin-transform-react-jsx': ^7.14.9 + eslint: ^8.1.0 + + eslint-plugin-import@2.31.0: + resolution: {integrity: sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + + eslint-plugin-jest@25.7.0: + resolution: {integrity: sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^4.0.0 || ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + jest: '*' + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + jest: + optional: true + + eslint-plugin-jsx-a11y@6.10.2: + resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==} + engines: {node: '>=4.0'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 + + eslint-plugin-react-hooks@4.6.2: + resolution: {integrity: sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==} + engines: {node: '>=10'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + + eslint-plugin-react@7.37.5: + resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + + eslint-plugin-testing-library@5.11.1: + resolution: {integrity: sha512-5eX9e1Kc2PqVRed3taaLnAAqPZGEX75C+M/rXzUAI3wIg/ZxzUm1OVAwfe/O+vE+6YXOLetSe9g5GKD2ecXipw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} + peerDependencies: + eslint: ^7.5.0 || ^8.0.0 + + eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + + eslint-scope@8.3.0: + resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-webpack-plugin@3.2.0: + resolution: {integrity: sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==} + engines: {node: '>= 12.13.0'} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + webpack: ^5.0.0 + + eslint@9.25.1: + resolution: {integrity: sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + esniff@2.0.1: + resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==} + engines: {node: '>=0.10'} + + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esprima@1.2.2: + resolution: {integrity: sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A==} + engines: {node: '>=0.4.0'} + hasBin: true + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@1.0.1: + resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + event-emitter@0.3.5: + resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} + + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + evp_bytestokey@1.0.3: + resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + + exec-sh@0.3.6: + resolution: {integrity: sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==} + + execa@0.8.0: + resolution: {integrity: sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA==} + engines: {node: '>=4'} + + execa@1.0.0: + resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} + engines: {node: '>=6'} + + execa@4.1.0: + resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} + engines: {node: '>=10'} + + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + exenv@1.2.2: + resolution: {integrity: sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==} + + exit-on-epipe@1.0.1: + resolution: {integrity: sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==} + engines: {node: '>=0.8'} + + exit@0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + + expand-brackets@0.1.5: + resolution: {integrity: sha512-hxx03P2dJxss6ceIeri9cmYOT4SRs3Zk3afZwWpOsRqLqprhTR8u++SlC+sFGsQr7WGFPdMF7Gjc1njDLDK6UA==} + engines: {node: '>=0.10.0'} + + expand-brackets@2.1.4: + resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} + engines: {node: '>=0.10.0'} + + expand-range@1.8.2: + resolution: {integrity: sha512-AFASGfIlnIbkKPQwX1yHaDjFvh/1gyKJODme52V6IORh69uEYgZp0o9C+qsIGNVEiuuhQU0CSSl++Rlegg1qvA==} + engines: {node: '>=0.10.0'} + + expect@26.6.2: + resolution: {integrity: sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA==} + engines: {node: '>= 10.14.2'} + + expect@27.5.1: + resolution: {integrity: sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + express@4.21.2: + resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} + engines: {node: '>= 0.10.0'} + + ext@1.7.0: + resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} + + extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + + extend-shallow@3.0.2: + resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} + engines: {node: '>=0.10.0'} + + extglob@0.3.2: + resolution: {integrity: sha512-1FOj1LOwn42TMrruOHGt18HemVnbwAmAak7krWk+wa93KXxGbK+2jpezm+ytJYDaBX0/SPLZFHKM7m+tKobWGg==} + engines: {node: '>=0.10.0'} + + extglob@2.0.4: + resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} + engines: {node: '>=0.10.0'} + + extrude-polyline@1.0.6: + resolution: {integrity: sha512-fcKIanU/v+tcdgG0+xMbS0C2VZ0/CF3qqxSjHiWfWICh0yFBezPr3SsOhgdzwE5E82plG6p1orEsfSqgldpxVg==} + + fast-deep-equal@3.1.1: + resolution: {integrity: sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@2.2.7: + resolution: {integrity: sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==} + engines: {node: '>=4.0.0'} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + + fast-shallow-equal@1.0.0: + resolution: {integrity: sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==} + + fast-uri@3.0.6: + resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} + + fastest-stable-stringify@2.0.2: + resolution: {integrity: sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==} + + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + + faye-websocket@0.11.4: + resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} + engines: {node: '>=0.8.0'} + + fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + + fbemitter@3.0.0: + resolution: {integrity: sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==} + + fbjs-css-vars@1.0.2: + resolution: {integrity: sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==} + + fbjs@0.8.18: + resolution: {integrity: sha512-EQaWFK+fEPSoibjNy8IxUtaFOMXcWsY0JaVrQoZR9zC8N2Ygf9iDITPWjUTVIax95b6I742JFLqASHfsag/vKA==} + + fbjs@3.0.5: + resolution: {integrity: sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==} + + fecha@4.2.3: + resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} + + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + file-loader@6.2.0: + resolution: {integrity: sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==} + engines: {node: '>= 10.13.0'} + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + + file-saver@2.0.5: + resolution: {integrity: sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==} + + file-uri-to-path@1.0.0: + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + + filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + + filename-regex@2.0.1: + resolution: {integrity: sha512-BTCqyBaWBTsauvnHiE8i562+EdJj+oUpkqWp2R1iCoR8f6oo8STRu3of7WJJ0TqWtxN50a5YFpzYK4Jj9esYfQ==} + engines: {node: '>=0.10.0'} + + filesize@10.1.6: + resolution: {integrity: sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==} + engines: {node: '>= 10.4.0'} + + filesize@8.0.7: + resolution: {integrity: sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==} + engines: {node: '>= 0.4.0'} + + fill-range@2.2.4: + resolution: {integrity: sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==} + engines: {node: '>=0.10.0'} + + fill-range@4.0.0: + resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} + engines: {node: '>=0.10.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + filter-obj@1.1.0: + resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} + engines: {node: '>=0.10.0'} + + filter-obj@5.1.0: + resolution: {integrity: sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==} + engines: {node: '>=14.16'} + + finalhandler@1.3.1: + resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} + engines: {node: '>= 0.8'} + + find-cache-dir@3.3.2: + resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} + engines: {node: '>=8'} + + find-root@1.1.0: + resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} + + find-up@3.0.0: + resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} + engines: {node: '>=6'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + flatten@1.0.3: + resolution: {integrity: sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==} + deprecated: flatten is deprecated in favor of utility frameworks such as lodash. + + flux@4.0.4: + resolution: {integrity: sha512-NCj3XlayA2UsapRpM7va6wU1+9rE5FIL7qoMcmxWHRzbp0yujihMBm9BBHZ1MDIk5h5o2Bl6eGiCe8rYELAmYw==} + peerDependencies: + react: ^15.0.2 || ^16.0.0 || ^17.0.0 + + fmin@0.0.2: + resolution: {integrity: sha512-sSi6DzInhl9d8yqssDfGZejChO8d2bAGIpysPsvYsxFe898z89XhCZg6CPNV3nhUhFefeC/AXZK2bAJxlBjN6A==} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + for-in@1.0.2: + resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} + engines: {node: '>=0.10.0'} + + for-own@0.1.5: + resolution: {integrity: sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==} + engines: {node: '>=0.10.0'} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + fork-ts-checker-webpack-plugin@6.5.3: + resolution: {integrity: sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==} + engines: {node: '>=10', yarn: '>=1.0.0'} + peerDependencies: + eslint: '>= 6' + typescript: '>= 2.7' + vue-template-compiler: '*' + webpack: '>= 4' + peerDependenciesMeta: + eslint: + optional: true + vue-template-compiler: + optional: true + + form-data@3.0.3: + resolution: {integrity: sha512-q5YBMeWy6E2Un0nMGWMgI65MAKtaylxfNJGJxpGh45YDciZB4epbWpaAfImil6CPAPTYB4sh0URQNDRIZG5F2w==} + engines: {node: '>= 6'} + + form-data@4.0.2: + resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} + engines: {node: '>= 6'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + frac@1.1.2: + resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==} + engines: {node: '>=0.8'} + + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + + fragment-cache@0.2.1: + resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} + engines: {node: '>=0.10.0'} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + + fs-monkey@1.0.6: + resolution: {integrity: sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==} + + fs-readdir-recursive@1.1.0: + resolution: {integrity: sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@1.2.13: + resolution: {integrity: sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==} + engines: {node: '>= 4.0'} + os: [darwin] + deprecated: Upgrade to fsevents v2 to mitigate potential security issues + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + geojson-vt@3.2.1: + resolution: {integrity: sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-own-enumerable-property-symbols@3.0.2: + resolution: {integrity: sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==} + + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stream@3.0.0: + resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} + engines: {node: '>=4'} + + get-stream@4.1.0: + resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} + engines: {node: '>=6'} + + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} + + get-value@2.0.6: + resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} + engines: {node: '>=0.10.0'} + + gl-matrix@3.4.3: + resolution: {integrity: sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==} + + gl-vec2@1.3.0: + resolution: {integrity: sha512-YiqaAuNsheWmUV0Sa8k94kBB0D6RWjwZztyO+trEYS8KzJ6OQB/4686gdrf59wld4hHFIvaxynO3nRxpk1Ij/A==} + + glob-base@0.3.0: + resolution: {integrity: sha512-ab1S1g1EbO7YzauaJLkgLp7DZVAqj9M/dvKlTt8DkXA2tiOIcSMrlVI2J1RZyB5iJVccEscjGn+kpOG9788MHA==} + engines: {node: '>=0.10.0'} + + glob-parent@2.0.0: + resolution: {integrity: sha512-JDYOvfxio/t42HKdxkAYaCiBN7oYiuxykOxKxdaUW5Qn0zaYN3gRQWolrwdnf0shM9/EP0ebuuTmyoXNr1cC5w==} + + glob-parent@3.1.0: + resolution: {integrity: sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob-to-regexp@0.3.0: + resolution: {integrity: sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==} + + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + global-modules@2.0.0: + resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} + engines: {node: '>=6'} + + global-prefix@3.0.0: + resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} + engines: {node: '>=6'} + + global@4.4.0: + resolution: {integrity: sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==} + + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@9.18.0: + resolution: {integrity: sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==} + engines: {node: '>=0.10.0'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + globby@9.2.0: + resolution: {integrity: sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==} + engines: {node: '>=6'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + graphlib@2.1.8: + resolution: {integrity: sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==} + + grid-index@1.1.0: + resolution: {integrity: sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==} + + growly@1.3.0: + resolution: {integrity: sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==} + + gzip-size@6.0.0: + resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} + engines: {node: '>=10'} + + hammerjs@2.0.8: + resolution: {integrity: sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==} + engines: {node: '>=0.8.0'} + + handle-thing@2.0.1: + resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} + + harmony-reflect@1.6.2: + resolution: {integrity: sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==} + + has-ansi@2.0.0: + resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} + engines: {node: '>=0.10.0'} + + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + + has-flag@1.0.0: + resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} + engines: {node: '>=0.10.0'} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-glob@1.0.0: + resolution: {integrity: sha512-D+8A457fBShSEI3tFCj65PAbT++5sKiFtdCdOam0gnfBgw9D277OERk+HM9qYJXmdVLZ/znez10SqHN0BBQ50g==} + engines: {node: '>=0.10.0'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + has-value@0.3.1: + resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} + engines: {node: '>=0.10.0'} + + has-value@1.0.0: + resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==} + engines: {node: '>=0.10.0'} + + has-values@0.1.4: + resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==} + engines: {node: '>=0.10.0'} + + has-values@1.0.0: + resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} + engines: {node: '>=0.10.0'} + + has@1.0.4: + resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==} + engines: {node: '>= 0.4.0'} + + hash-base@3.0.5: + resolution: {integrity: sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==} + engines: {node: '>= 0.10'} + + hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + highlight.js@11.11.1: + resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} + engines: {node: '>=12.0.0'} + + highlightjs-solidity@2.0.6: + resolution: {integrity: sha512-DySXWfQghjm2l6a/flF+cteroJqD4gI8GSdL4PtvxZSsAHie8m3yVe2JFoRg03ROKT6hp2Lc/BxXkqerNmtQYg==} + + history-with-query@4.10.4: + resolution: {integrity: sha512-JnskQK8X+PbRFHSdDAExhoJyhLnlLZL+UuHQuQhys+Se9/ukRDRBWU4JVTjsiIfbv1fcEmR3oqKW56OYmk5M5w==} + + history@4.10.1: + resolution: {integrity: sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==} + + history@5.3.0: + resolution: {integrity: sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==} + + hmac-drbg@1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + + hoist-non-react-statics@1.2.0: + resolution: {integrity: sha512-r8huvKK+m+VraiRipdZYc+U4XW43j6OFG/oIafe7GfDbRpCduRoX9JI/DRxqgtBSCeL+et6N6ibZoedHS2NyOQ==} + + hoist-non-react-statics@3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + + home-or-tmp@2.0.0: + resolution: {integrity: sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg==} + engines: {node: '>=0.10.0'} + + hoopy@0.1.4: + resolution: {integrity: sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==} + engines: {node: '>= 6.0.0'} + + hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + + hpack.js@2.1.6: + resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} + + html-encoding-sniffer@2.0.1: + resolution: {integrity: sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==} + engines: {node: '>=10'} + + html-entities@2.6.0: + resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==} + + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + + html-minifier-terser@5.1.1: + resolution: {integrity: sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==} + engines: {node: '>=6'} + hasBin: true + + html-minifier-terser@6.1.0: + resolution: {integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==} + engines: {node: '>=12'} + hasBin: true + + html-webpack-plugin@4.5.2: + resolution: {integrity: sha512-q5oYdzjKUIPQVjOosjgvCHQOv9Ett9CYYHlgvJeXG0qQvdSojnBq4vAdQBwn1+yGveAwHCoe/rMR86ozX3+c2A==} + engines: {node: '>=6.9'} + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + + html-webpack-plugin@5.6.3: + resolution: {integrity: sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg==} + engines: {node: '>=10.13.0'} + peerDependencies: + '@rspack/core': 0.x || 1.x + webpack: ^5.20.0 + peerDependenciesMeta: + '@rspack/core': + optional: true + webpack: + optional: true + + htmlparser2@6.1.0: + resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} + + http-deceiver@1.2.7: + resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} + + http-errors@1.6.3: + resolution: {integrity: sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==} + engines: {node: '>= 0.6'} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + + http-parser-js@0.5.10: + resolution: {integrity: sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==} + + http-proxy-agent@4.0.1: + resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} + engines: {node: '>= 6'} + + http-proxy-middleware@2.0.9: + resolution: {integrity: sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/express': ^4.17.13 + peerDependenciesMeta: + '@types/express': + optional: true + + http-proxy@1.18.1: + resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} + engines: {node: '>=8.0.0'} + + http2-client@1.3.5: + resolution: {integrity: sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==} + + https-browserify@1.0.0: + resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + human-signals@1.1.1: + resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} + engines: {node: '>=8.12.0'} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + hyphenate-style-name@1.1.0: + resolution: {integrity: sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + icss-utils@5.1.0: + resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + idb@7.1.1: + resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==} + + identity-obj-proxy@3.0.0: + resolution: {integrity: sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==} + engines: {node: '>=4'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@4.0.6: + resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==} + engines: {node: '>= 4'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + + immer@7.0.15: + resolution: {integrity: sha512-yM7jo9+hvYgvdCQdqvhCNRRio0SCXc8xDPzA25SvKWa7b1WVPjLwQs1VYU5JPXjcJPTqAa5NP5dqpORGYBQ2AA==} + + immer@9.0.21: + resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==} + + immutable@3.7.6: + resolution: {integrity: sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==} + engines: {node: '>=0.8.0'} + + immutable@3.8.2: + resolution: {integrity: sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg==} + engines: {node: '>=0.10.0'} + + import-cwd@2.1.0: + resolution: {integrity: sha512-Ew5AZzJQFqrOV5BTW3EIoHAnoie1LojZLXKcCQ/yTRyVZosBhK1x1ViYjHGf5pAFOq8ZyChZp6m/fSN7pJyZtg==} + engines: {node: '>=4'} + + import-fresh@2.0.0: + resolution: {integrity: sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==} + engines: {node: '>=4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + import-from@2.1.0: + resolution: {integrity: sha512-0vdnLL2wSGnhlRmzHJAg5JHjt1l2vYhzJ7tNLGbeVg0fse56tpGaH0uzH+r9Slej+BSXXEHvBKDEnVSLLE9/+w==} + engines: {node: '>=4'} + + import-local@3.2.0: + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} + engines: {node: '>=8'} + hasBin: true + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + indexes-of@1.0.1: + resolution: {integrity: sha512-bup+4tap3Hympa+JBJUG7XuOsdNQ6fxt0MHyXMKuLBKn0OqsTfvUxkUrroEX1+B2VsSHvCjiIcZVxRtYa4nllA==} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + inline-style-prefixer@7.0.1: + resolution: {integrity: sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==} + + insert-css@2.0.0: + resolution: {integrity: sha512-xGq5ISgcUP5cvGkS2MMFLtPDBtrtQPSFfC6gA6U8wHKqfjTIMZLZNxOItQnoSjdOzlXOLU/yD32RKC4SvjNbtA==} + + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + + internmap@1.0.1: + resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==} + + intersection-observer@0.12.2: + resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==} + + intersection-observer@0.7.0: + resolution: {integrity: sha512-Id0Fij0HsB/vKWGeBe9PxeY45ttRiBmhFyyt/geBdDHBYNctMRTE3dC1U3ujzz3lap+hVXlEcVaB56kZP/eEUg==} + + intl-format-cache@4.3.1: + resolution: {integrity: sha512-OEUYNA7D06agqPOYhbTkl0T8HA3QKSuwWh1HiClEnpd9vw7N+3XsQt5iZ0GUEchp5CW1fQk/tary+NsbF3yQ1Q==} + + intl-messageformat-parser@3.6.4: + resolution: {integrity: sha512-RgPGwue0mJtoX2Ax8EmMzJzttxjnva7gx0Q7mKJ4oALrTZvtmCeAw5Msz2PcjW4dtCh/h7vN/8GJCxZO1uv+OA==} + deprecated: We've written a new parser that's 6x faster and is backwards compatible. Please use @formatjs/icu-messageformat-parser + + intl-messageformat@7.8.4: + resolution: {integrity: sha512-yS0cLESCKCYjseCOGXuV4pxJm/buTfyCJ1nzQjryHmSehlptbZbn9fnlk1I9peLopZGGbjj46yHHiTAEZ1qOTA==} + + intl@1.2.5: + resolution: {integrity: sha512-rK0KcPHeBFBcqsErKSpvZnrOmWOj+EmDkyJ57e90YWaQNqbcivcqmKDlHEeNprDWOsKzPsh1BfSpPQdDvclHVw==} + + invariant@2.2.4: + resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} + + inversify-inject-decorators@3.1.0: + resolution: {integrity: sha512-/seBlVp5bXrLQS3DpKEmlgeZL6C7Tf/QITd+IMQrbBBGuCbxb7k3hRAWu9XSreNpFzLgSboz3sClLSEmGwHphw==} + + inversify@5.1.1: + resolution: {integrity: sha512-j8grHGDzv1v+8T1sAQ+3boTCntFPfvxLCkNcxB1J8qA0lUN+fAlSyYd+RXKvaPRL4AGyPxViutBEJHNXOyUdFQ==} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + ipaddr.js@2.2.0: + resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} + engines: {node: '>= 10'} + + is-accessor-descriptor@1.0.1: + resolution: {integrity: sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==} + engines: {node: '>= 0.10'} + + is-any-array@2.0.1: + resolution: {integrity: sha512-UtilS7hLRu++wb/WBAw9bNuP1Eg04Ivn1vERJck8zJthEvXCBEBpGR/33u/xLKWEQf95803oalHrVDptcAvFdQ==} + + is-arguments@1.2.0: + resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} + engines: {node: '>= 0.4'} + + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-binary-path@1.0.1: + resolution: {integrity: sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==} + engines: {node: '>=0.10.0'} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + + is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-ci@1.2.1: + resolution: {integrity: sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==} + hasBin: true + + is-ci@2.0.0: + resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==} + hasBin: true + + is-class-hotfix@0.0.6: + resolution: {integrity: sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ==} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-data-descriptor@1.0.1: + resolution: {integrity: sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-descriptor@0.1.7: + resolution: {integrity: sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==} + engines: {node: '>= 0.4'} + + is-descriptor@1.0.3: + resolution: {integrity: sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==} + engines: {node: '>= 0.4'} + + is-directory@0.3.1: + resolution: {integrity: sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==} + engines: {node: '>=0.10.0'} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-dotfile@1.0.3: + resolution: {integrity: sha512-9YclgOGtN/f8zx0Pr4FQYMdibBiTaH3sn52vjYip4ZSf6C4/6RfTEZ+MR4GvKhCxdPh21Bg42/WL55f6KSnKpg==} + engines: {node: '>=0.10.0'} + + is-equal-shallow@0.1.3: + resolution: {integrity: sha512-0EygVC5qPvIyb+gSz7zdD5/AAoS6Qrx1e//6N4yv4oNm30kqvdmG66oZFWVlQHUWe5OjP08FuTw2IdT0EOTcYA==} + engines: {node: '>=0.10.0'} + + is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + + is-extendable@1.0.1: + resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} + engines: {node: '>=0.10.0'} + + is-extglob@1.0.0: + resolution: {integrity: sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==} + engines: {node: '>=0.10.0'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + + is-finite@1.1.0: + resolution: {integrity: sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + + is-generator-function@1.1.0: + resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} + engines: {node: '>= 0.4'} + + is-glob@2.0.1: + resolution: {integrity: sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==} + engines: {node: '>=0.10.0'} + + is-glob@3.1.0: + resolution: {integrity: sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + + is-number@2.1.0: + resolution: {integrity: sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==} + engines: {node: '>=0.10.0'} + + is-number@3.0.0: + resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} + engines: {node: '>=0.10.0'} + + is-number@4.0.0: + resolution: {integrity: sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-obj@1.0.1: + resolution: {integrity: sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==} + engines: {node: '>=0.10.0'} + + is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + + is-plain-obj@3.0.0: + resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} + engines: {node: '>=10'} + + is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + + is-posix-bracket@0.1.1: + resolution: {integrity: sha512-Yu68oeXJ7LeWNmZ3Zov/xg/oDBnBK2RNxwYY1ilNJX+tKKZqgPK+qOn/Gs9jEu66KDY9Netf5XLKNGzas/vPfQ==} + engines: {node: '>=0.10.0'} + + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + + is-primitive@2.0.0: + resolution: {integrity: sha512-N3w1tFaRfk3UrPfqeRyD+GYDASU3W5VinKhlORy8EWVf/sIdDL9GAcew85XmktCfH+ngG7SRXEVDoO18WMdB/Q==} + engines: {node: '>=0.10.0'} + + is-promise@2.2.2: + resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + + is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-regexp@1.0.0: + resolution: {integrity: sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==} + engines: {node: '>=0.10.0'} + + is-root@2.1.0: + resolution: {integrity: sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==} + engines: {node: '>=6'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-stream@1.1.0: + resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} + engines: {node: '>=0.10.0'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + + is-type-of@1.4.0: + resolution: {integrity: sha512-EddYllaovi5ysMLMEN7yzHEKh8A850cZ7pykrY1aNRQGn/CDjRDE9qEWbIdt7xGEVJmjBXzU/fNnC4ABTm8tEQ==} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + + is-url@1.2.4: + resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + isarray@0.0.1: + resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isobject@2.1.0: + resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} + engines: {node: '>=0.10.0'} + + isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + + isomorphic-fetch@2.2.1: + resolution: {integrity: sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==} + + isstream@0.1.2: + resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} + + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@4.0.3: + resolution: {integrity: sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==} + engines: {node: '>=8'} + + istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + + istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + + iterator.prototype@1.1.5: + resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} + engines: {node: '>= 0.4'} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jake@10.9.2: + resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} + engines: {node: '>=10'} + hasBin: true + + javascript-stringify@2.1.0: + resolution: {integrity: sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==} + + jest-changed-files@26.6.2: + resolution: {integrity: sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ==} + engines: {node: '>= 10.14.2'} + + jest-changed-files@27.5.1: + resolution: {integrity: sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-circus@27.5.1: + resolution: {integrity: sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-cli@26.6.3: + resolution: {integrity: sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg==} + engines: {node: '>= 10.14.2'} + hasBin: true + + jest-cli@27.5.1: + resolution: {integrity: sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jest-config@26.6.3: + resolution: {integrity: sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg==} + engines: {node: '>= 10.14.2'} + peerDependencies: + ts-node: '>=9.0.0' + peerDependenciesMeta: + ts-node: + optional: true + + jest-config@27.5.1: + resolution: {integrity: sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + peerDependencies: + ts-node: '>=9.0.0' + peerDependenciesMeta: + ts-node: + optional: true + + jest-diff@26.6.2: + resolution: {integrity: sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==} + engines: {node: '>= 10.14.2'} + + jest-diff@27.5.1: + resolution: {integrity: sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-docblock@26.0.0: + resolution: {integrity: sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==} + engines: {node: '>= 10.14.2'} + + jest-docblock@27.5.1: + resolution: {integrity: sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-each@26.6.2: + resolution: {integrity: sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A==} + engines: {node: '>= 10.14.2'} + + jest-each@27.5.1: + resolution: {integrity: sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-environment-jsdom@26.6.2: + resolution: {integrity: sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q==} + engines: {node: '>= 10.14.2'} + + jest-environment-jsdom@27.5.1: + resolution: {integrity: sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-environment-node@26.6.2: + resolution: {integrity: sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag==} + engines: {node: '>= 10.14.2'} + + jest-environment-node@27.5.1: + resolution: {integrity: sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-get-type@26.3.0: + resolution: {integrity: sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==} + engines: {node: '>= 10.14.2'} + + jest-get-type@27.5.1: + resolution: {integrity: sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-haste-map@26.6.2: + resolution: {integrity: sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==} + engines: {node: '>= 10.14.2'} + + jest-haste-map@27.5.1: + resolution: {integrity: sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-jasmine2@26.6.3: + resolution: {integrity: sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==} + engines: {node: '>= 10.14.2'} + + jest-jasmine2@27.5.1: + resolution: {integrity: sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-leak-detector@26.6.2: + resolution: {integrity: sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg==} + engines: {node: '>= 10.14.2'} + + jest-leak-detector@27.5.1: + resolution: {integrity: sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-matcher-utils@26.6.2: + resolution: {integrity: sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==} + engines: {node: '>= 10.14.2'} + + jest-matcher-utils@27.5.1: + resolution: {integrity: sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-message-util@26.6.2: + resolution: {integrity: sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==} + engines: {node: '>= 10.14.2'} + + jest-message-util@27.5.1: + resolution: {integrity: sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-message-util@28.1.3: + resolution: {integrity: sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + jest-mock@26.6.2: + resolution: {integrity: sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==} + engines: {node: '>= 10.14.2'} + + jest-mock@27.5.1: + resolution: {integrity: sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-pnp-resolver@1.2.3: + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + + jest-regex-util@26.0.0: + resolution: {integrity: sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==} + engines: {node: '>= 10.14.2'} + + jest-regex-util@27.5.1: + resolution: {integrity: sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-regex-util@28.0.2: + resolution: {integrity: sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + jest-resolve-dependencies@26.6.3: + resolution: {integrity: sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg==} + engines: {node: '>= 10.14.2'} + + jest-resolve-dependencies@27.5.1: + resolution: {integrity: sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-resolve@26.6.2: + resolution: {integrity: sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ==} + engines: {node: '>= 10.14.2'} + + jest-resolve@27.5.1: + resolution: {integrity: sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-runner@26.6.3: + resolution: {integrity: sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ==} + engines: {node: '>= 10.14.2'} + + jest-runner@27.5.1: + resolution: {integrity: sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-runtime@26.6.3: + resolution: {integrity: sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==} + engines: {node: '>= 10.14.2'} + hasBin: true + + jest-runtime@27.5.1: + resolution: {integrity: sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-serializer@26.6.2: + resolution: {integrity: sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==} + engines: {node: '>= 10.14.2'} + + jest-serializer@27.5.1: + resolution: {integrity: sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-snapshot@26.6.2: + resolution: {integrity: sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og==} + engines: {node: '>= 10.14.2'} + + jest-snapshot@27.5.1: + resolution: {integrity: sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-util@26.6.2: + resolution: {integrity: sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==} + engines: {node: '>= 10.14.2'} + + jest-util@27.5.1: + resolution: {integrity: sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-util@28.1.3: + resolution: {integrity: sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + jest-validate@26.6.2: + resolution: {integrity: sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ==} + engines: {node: '>= 10.14.2'} + + jest-validate@27.5.1: + resolution: {integrity: sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-watch-typeahead@1.1.0: + resolution: {integrity: sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + jest: ^27.0.0 || ^28.0.0 + + jest-watcher@26.6.2: + resolution: {integrity: sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ==} + engines: {node: '>= 10.14.2'} + + jest-watcher@27.5.1: + resolution: {integrity: sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-watcher@28.1.3: + resolution: {integrity: sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + jest-worker@24.9.0: + resolution: {integrity: sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==} + engines: {node: '>= 6'} + + jest-worker@26.6.2: + resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} + engines: {node: '>= 10.13.0'} + + jest-worker@27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + + jest-worker@28.1.3: + resolution: {integrity: sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + jest@26.6.3: + resolution: {integrity: sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q==} + engines: {node: '>= 10.14.2'} + hasBin: true + + jest@27.5.1: + resolution: {integrity: sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jiti@1.21.7: + resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} + hasBin: true + + jquery-mousewheel@3.2.2: + resolution: {integrity: sha512-JP71xTAg08ZY3hcs9ZbYUZ5i+dkSsz4yRl/zpWkAmtzc+kMs5EfPkpkINSidiLYMaR0MTo3DfFGF9WIezMsFQQ==} + + jquery@3.7.1: + resolution: {integrity: sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==} + + js-base64@2.6.4: + resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==} + + js-base64@3.7.7: + resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==} + + js-cookie@2.2.1: + resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==} + + js-cookie@3.0.5: + resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} + engines: {node: '>=14'} + + js-tokens@3.0.2: + resolution: {integrity: sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsdom@16.7.0: + resolution: {integrity: sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==} + engines: {node: '>=10'} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + + jsencrypt-ext@2.1.2: + resolution: {integrity: sha512-tz3Mt26EjMntSXPHWxFZfNyAROVfOGAUkdvSkuorilP2HBO/Ll4jYMf39f9ajvyEkTIpNNB3CBmaa+4Xx7A5zw==} + + jsencrypt@3.3.2: + resolution: {integrity: sha512-arQR1R1ESGdAxY7ZheWr12wCaF2yF47v5qpB76TtV64H1pyGudk9Hvw8Y9tb/FiTIaaTRUyaSnm5T/Y53Ghm/A==} + + jsesc@0.5.0: + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + hasBin: true + + jsesc@1.3.0: + resolution: {integrity: sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA==} + hasBin: true + + jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-better-errors@1.0.2: + resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json-stringify-pretty-compact@3.0.0: + resolution: {integrity: sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA==} + + json2module@0.0.3: + resolution: {integrity: sha512-qYGxqrRrt4GbB8IEOy1jJGypkNsjWoIMlZt4bAsmUScCA507Hbc2p1JOhBzqn45u3PWafUgH2OnzyNU7udO/GA==} + hasBin: true + + json2mq@0.2.0: + resolution: {integrity: sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==} + + json5@0.5.1: + resolution: {integrity: sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw==} + hasBin: true + + json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + jsonpath@1.1.1: + resolution: {integrity: sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==} + + jsonpointer@5.0.1: + resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} + engines: {node: '>=0.10.0'} + + jsx-ast-utils@3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + + junk@3.1.0: + resolution: {integrity: sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==} + engines: {node: '>=8'} + + kdbush@3.0.0: + resolution: {integrity: sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==} + + kdbush@4.0.2: + resolution: {integrity: sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kind-of@3.2.2: + resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} + engines: {node: '>=0.10.0'} + + kind-of@4.0.0: + resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} + engines: {node: '>=0.10.0'} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + klona@2.0.6: + resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} + engines: {node: '>= 8'} + + language-subtag-registry@0.3.23: + resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} + + language-tags@1.0.9: + resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} + engines: {node: '>=0.10'} + + launch-editor@2.10.0: + resolution: {integrity: sha512-D7dBRJo/qcGX9xlvt/6wUYzQxjh5G1RvZPgPv8vi4KRU99DVQL/oW7tnVOCCTm2HGeo3C5HvGE5Yrh6UBoZ0vA==} + + lazy-cache@1.0.4: + resolution: {integrity: sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==} + engines: {node: '>=0.10.0'} + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + levn@0.3.0: + resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} + engines: {node: '>= 0.8.0'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lie@3.1.1: + resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==} + + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + lint-staged@10.5.4: + resolution: {integrity: sha512-EechC3DdFic/TdOPgj/RB3FicqE6932LTHCUm0Y2fsD9KGlLB+RwJl2q1IYBIvEsKzDOgn0D4gll+YxG5RsrKg==} + hasBin: true + + listr2@3.14.0: + resolution: {integrity: sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==} + engines: {node: '>=10.0.0'} + peerDependencies: + enquirer: '>= 2.3.0 < 3' + peerDependenciesMeta: + enquirer: + optional: true + + loader-runner@4.3.0: + resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} + engines: {node: '>=6.11.5'} + + loader-utils@1.4.2: + resolution: {integrity: sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==} + engines: {node: '>=4.0.0'} + + loader-utils@2.0.4: + resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==} + engines: {node: '>=8.9.0'} + + loader-utils@3.3.1: + resolution: {integrity: sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==} + engines: {node: '>= 12.13.0'} + + localforage@1.10.0: + resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==} + + locate-path@3.0.0: + resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} + engines: {node: '>=6'} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + + lodash._reinterpolate@3.0.0: + resolution: {integrity: sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==} + + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + lodash.curry@4.1.1: + resolution: {integrity: sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA==} + + lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + + lodash.flow@3.5.0: + resolution: {integrity: sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw==} + + lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. + + lodash.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.sortby@4.7.0: + resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + + lodash.template@4.5.0: + resolution: {integrity: sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==} + deprecated: This package is deprecated. Use https://socket.dev/npm/package/eta instead. + + lodash.templatesettings@4.2.0: + resolution: {integrity: sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==} + + lodash.throttle@4.1.1: + resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} + + lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + + lodash.upperfirst@4.3.1: + resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + + log-update@4.0.0: + resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} + engines: {node: '>=10'} + + longest@1.0.1: + resolution: {integrity: sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==} + engines: {node: '>=0.10.0'} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + lottie-web@5.12.2: + resolution: {integrity: sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==} + + lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@4.1.5: + resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + lru-queue@0.1.0: + resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==} + + magic-string@0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + + make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + + mana-common@0.3.2: + resolution: {integrity: sha512-1oylLR9CcyshQcTiBdM96HxIoaA413eudpo1INiOCwyZE554TDJNUD0zrIjmeBvw8CBAjukzaAHn2gn0hZphIg==} + + mana-syringe@0.2.2: + resolution: {integrity: sha512-Sv5r0/PrQRq4pW+9lDicGsEPzPLkd1PwjTs5zHUV1I293S3alkBNyuSjktVeBploofH8MAMLd4DS2crwct48wg==} + + map-cache@0.2.2: + resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} + engines: {node: '>=0.10.0'} + + map-visit@1.0.0: + resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} + engines: {node: '>=0.10.0'} + + mapbox-gl@1.13.3: + resolution: {integrity: sha512-p8lJFEiqmEQlyv+DQxFAOG/XPWN0Wp7j/Psq93Zywz7qt9CcUKFYDBOoOEKzqe6gudHVJY8/Bhqw6VDpX2lSBg==} + engines: {node: '>=6.4.0'} + + maplibre-gl@3.6.2: + resolution: {integrity: sha512-krg2KFIdOpLPngONDhP6ixCoWl5kbdMINP0moMSJFVX7wX1Clm2M9hlNKXS8vBGlVWwR5R3ZfI6IPrYz7c+aCQ==} + engines: {node: '>=16.14.0', npm: '>=8.1.0'} + + material-colors@1.2.6: + resolution: {integrity: sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + math-random@1.0.4: + resolution: {integrity: sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==} + + md5.js@1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + + mdn-data@2.0.14: + resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + + mdn-data@2.0.4: + resolution: {integrity: sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + memfs@3.5.3: + resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} + engines: {node: '>= 4.0.0'} + + memoize-one@5.2.1: + resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==} + + memoizee@0.4.17: + resolution: {integrity: sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==} + engines: {node: '>=0.12'} + + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + micromatch@2.3.11: + resolution: {integrity: sha512-LnU2XFEk9xxSJ6rfgAry/ty5qwUTyHYOBU0g4R6tIw5ljwgGIBmiKhRWLw5NpMOnrgUNcDJ4WMp8rl3sYVHLNA==} + engines: {node: '>=0.10.0'} + + micromatch@3.1.10: + resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} + engines: {node: '>=0.10.0'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + miller-rabin@4.0.1: + resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} + hasBin: true + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@1.4.1: + resolution: {integrity: sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==} + hasBin: true + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + min-document@2.19.0: + resolution: {integrity: sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==} + + mini-create-react-context@0.4.1: + resolution: {integrity: sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + peerDependencies: + prop-types: ^15.0.0 + react: ^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + mini-css-extract-plugin@1.6.2: + resolution: {integrity: sha512-WhDvO3SjGm40oV5y26GjMJYjd2UMqrLAGKy5YS2/3QKJy2F7jgynuHTir/tgUUOiNQu5saXHdc8reo7YuhhT4Q==} + engines: {node: '>= 10.13.0'} + peerDependencies: + webpack: ^4.4.0 || ^5.0.0 + + mini-css-extract-plugin@2.9.2: + resolution: {integrity: sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + + minimalistic-crypto-utils@1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + mixin-deep@1.3.2: + resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} + engines: {node: '>=0.10.0'} + + mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + + ml-array-max@1.2.4: + resolution: {integrity: sha512-BlEeg80jI0tW6WaPyGxf5Sa4sqvcyY6lbSn5Vcv44lp1I2GR6AWojfUvLnGTNsIXrZ8uqWmo8VcG1WpkI2ONMQ==} + + ml-array-min@1.2.3: + resolution: {integrity: sha512-VcZ5f3VZ1iihtrGvgfh/q0XlMobG6GQ8FsNyQXD3T+IlstDv85g8kfV0xUG1QPRO/t21aukaJowDzMTc7j5V6Q==} + + ml-array-rescale@1.3.7: + resolution: {integrity: sha512-48NGChTouvEo9KBctDfHC3udWnQKNKEWN0ziELvY3KG25GR5cA8K8wNVzracsqSW1QEkAXjTNx+ycgAv06/1mQ==} + + ml-matrix@6.12.1: + resolution: {integrity: sha512-TJ+8eOFdp+INvzR4zAuwBQJznDUfktMtOB6g/hUcGh3rcyjxbz4Te57Pgri8Q9bhSQ7Zys4IYOGhFdnlgeB6Lw==} + + ml-matrix@6.5.0: + resolution: {integrity: sha512-sms732Dge+rs5dU4mnjE0oqLWm1WujvR2fr38LgUHRG2cjXjWlO3WJupLYaSz3++2iYr0UrGDK72OAivr3J8dg==} + + mock-property@1.0.3: + resolution: {integrity: sha512-2emPTb1reeLLYwHxyVx993iYyCHEiRRO+y8NFXFPL5kl5q14sgTK76cXyEKkeKCHeRw35SfdkUJ10Q1KfHuiIQ==} + engines: {node: '>= 0.4'} + + mock.js@0.2.0: + resolution: {integrity: sha512-DKI8Rh/h7Mma+fg+6aD0uUvwn0QXAjKG6q3s+lTaCboCQ/kvQMBN9IXRBzgEaz4aPiYoRnKU9jVsfZp0mHpWrQ==} + + mockjs@1.1.0: + resolution: {integrity: sha512-eQsKcWzIaZzEZ07NuEyO4Nw65g0hdWAyurVol1IPl1gahRwY+svqzfgfey8U8dahLwG44d6/RwEzuK52rSa/JQ==} + hasBin: true + + moment@2.30.1: + resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} + + mousetrap@1.6.5: + resolution: {integrity: sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + multicast-dns@7.2.5: + resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} + hasBin: true + + murmurhash-js@1.0.0: + resolution: {integrity: sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==} + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + nan@2.22.2: + resolution: {integrity: sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==} + + nano-css@5.6.2: + resolution: {integrity: sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw==} + peerDependencies: + react: '*' + react-dom: '*' + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanomatch@1.2.13: + resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} + engines: {node: '>=0.10.0'} + + natural-compare-lite@1.4.0: + resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + + nested-error-stacks@2.1.1: + resolution: {integrity: sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==} + + next-tick@1.1.0: + resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} + + nice-try@1.0.5: + resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} + + no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + + node-fetch-h2@2.3.0: + resolution: {integrity: sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==} + engines: {node: 4.x || >=6.0.0} + + node-fetch@1.7.3: + resolution: {integrity: sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-forge@1.3.1: + resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} + engines: {node: '>= 6.13.0'} + + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + + node-libs-browser@2.2.1: + resolution: {integrity: sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==} + + node-notifier@8.0.2: + resolution: {integrity: sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg==} + + node-readfiles@0.2.0: + resolution: {integrity: sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA==} + + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + + normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + + normalize-path@1.0.0: + resolution: {integrity: sha512-7WyT0w8jhpDStXRq5836AMmihQwq2nrUVQrgjvUo/p/NZf9uy/MeJ246lBJVmWuYXMlJuG9BNZHF0hWjfTbQUA==} + engines: {node: '>=0.10.0'} + + normalize-path@2.1.1: + resolution: {integrity: sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==} + engines: {node: '>=0.10.0'} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + + normalize-url@1.9.1: + resolution: {integrity: sha512-A48My/mtCklowHBlI8Fq2jFWK4tX4lJ5E6ytFsSOq1fzpvT0SQSgKhSg7lN5c2uYFOrUAOQp6zhhJnpp1eMloQ==} + engines: {node: '>=4'} + + normalize-url@6.1.0: + resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} + engines: {node: '>=10'} + + normalize.css@7.0.0: + resolution: {integrity: sha512-LYaFZxj2Q1Q9e1VJ0f6laG46Rt5s9URhKyckNaA2vZnL/0gwQHWhM7ALQkp3WBQKM5sXRLQ5Ehrfkp+E/ZiCRg==} + + npm-run-path@2.0.2: + resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} + engines: {node: '>=4'} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + nth-check@1.0.2: + resolution: {integrity: sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + num2fraction@1.2.2: + resolution: {integrity: sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==} + + numericjs@1.2.6: + resolution: {integrity: sha512-AbumaZGCaoXy0Fn231zqrFbQ1b6yUX5WD2Ve5jvD1hJbIYaCKFsG7XPFz5M8+O5rqdxI6Ms5+TQL8ZeSdN5FdA==} + + nunjucks@3.2.4: + resolution: {integrity: sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==} + engines: {node: '>= 6.9.0'} + hasBin: true + peerDependencies: + chokidar: ^3.3.0 + peerDependenciesMeta: + chokidar: + optional: true + + nwsapi@2.2.20: + resolution: {integrity: sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==} + + oas-kit-common@1.0.8: + resolution: {integrity: sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==} + + oas-linter@3.2.2: + resolution: {integrity: sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==} + + oas-resolver@2.5.6: + resolution: {integrity: sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==} + hasBin: true + + oas-schema-walker@1.1.5: + resolution: {integrity: sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==} + + oas-validator@5.0.8: + resolution: {integrity: sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-copy@0.1.0: + resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==} + engines: {node: '>=0.10.0'} + + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + + object-inspect@1.12.3: + resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object-visit@1.0.1: + resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==} + engines: {node: '>=0.10.0'} + + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + object.entries@1.1.9: + resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} + engines: {node: '>= 0.4'} + + object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + + object.getownpropertydescriptors@2.1.8: + resolution: {integrity: sha512-qkHIGe4q0lSYMv0XI4SsBTJz3WaURhLvd0lKSgtVuOsJ2krg4SgMw3PIRQFMp07yi++UR3se2mkcLqsBNpBb/A==} + engines: {node: '>= 0.8'} + + object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + + object.omit@2.0.1: + resolution: {integrity: sha512-UiAM5mhmIuKLsOvrL+B0U2d1hXHF3bFYWIuH1LMpuV2EJEHG1Ntz06PgLEHjm6VFd87NpH8rastvPoyv6UW2fA==} + engines: {node: '>=0.10.0'} + + object.pick@1.3.0: + resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} + engines: {node: '>=0.10.0'} + + object.values@1.2.1: + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} + engines: {node: '>= 0.4'} + + obuf@1.1.2: + resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} + + omit.js@1.0.2: + resolution: {integrity: sha512-/QPc6G2NS+8d4L/cQhbk6Yit1WTB6Us2g84A7A/1+w9d/eRGHyEqC5kkQtHVoHZ5NFWGG7tUGgrhVZwgZanKrQ==} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + on-headers@1.0.2: + resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + + openapi3-ts@2.0.2: + resolution: {integrity: sha512-TxhYBMoqx9frXyOgnRHufjQfPXomTIHYKhSKJ6jHfj13kS8OEIhvmE8CTuQyKtjjWttAjX5DPxM1vmalEpo8Qw==} + + optionator@0.8.3: + resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} + engines: {node: '>= 0.8.0'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + os-browserify@0.3.0: + resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} + + os-homedir@1.0.2: + resolution: {integrity: sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==} + engines: {node: '>=0.10.0'} + + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + + output-file-sync@1.1.2: + resolution: {integrity: sha512-uQLlclru4xpCi+tfs80l3QF24KL81X57ELNMy7W/dox+JTtxUf1bLyQ8968fFCmSqqbokjW0kn+WBIlO+rSkNg==} + + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + + p-all@2.1.0: + resolution: {integrity: sha512-HbZxz5FONzz/z2gJfk6bFca0BCiSRF8jU3yCsWOen/vR6lZjfPOu/e7L3uFzTW1i0H8TlC3vqQstEJPQL4/uLA==} + engines: {node: '>=6'} + + p-each-series@2.2.0: + resolution: {integrity: sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==} + engines: {node: '>=8'} + + p-event@4.2.0: + resolution: {integrity: sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==} + engines: {node: '>=8'} + + p-filter@2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} + engines: {node: '>=8'} + + p-finally@1.0.0: + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} + engines: {node: '>=4'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@3.0.0: + resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} + engines: {node: '>=6'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + + p-map@3.0.0: + resolution: {integrity: sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==} + engines: {node: '>=8'} + + p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + + p-retry@4.6.2: + resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} + engines: {node: '>=8'} + + p-timeout@3.2.0: + resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} + engines: {node: '>=8'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + + param-case@3.0.4: + resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-asn1@5.1.7: + resolution: {integrity: sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==} + engines: {node: '>= 0.10'} + + parse-glob@3.0.4: + resolution: {integrity: sha512-FC5TeK0AwXzq3tUBFtH74naWkPQCEWs4K+xMxWZBlKDWu0bVHXGZa+KKqxKidd7xwhdZ19ZNuF2uO1M/r196HA==} + engines: {node: '>=0.10.0'} + + parse-json@4.0.0: + resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} + engines: {node: '>=4'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + parse5@6.0.1: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + pascal-case@3.1.2: + resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + + pascalcase@0.1.1: + resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} + engines: {node: '>=0.10.0'} + + path-browserify@0.0.1: + resolution: {integrity: sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==} + + path-dirname@1.0.2: + resolution: {integrity: sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==} + + path-exists@3.0.0: + resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} + engines: {node: '>=4'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@2.0.1: + resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} + engines: {node: '>=4'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-to-regexp@0.1.12: + resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + + path-to-regexp@1.9.0: + resolution: {integrity: sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==} + + path-to-regexp@7.2.0: + resolution: {integrity: sha512-0W4AcUxPpFlcS8ql8ZEmFwaI0X5WshUVAFdXe3PBurrt18DK8bvSS+UKHvJUAfGILco/nTtc/E4LcPNfVysfwQ==} + engines: {node: '>=16'} + + path-to-regexp@8.2.0: + resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} + engines: {node: '>=16'} + + path-type@3.0.0: + resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==} + engines: {node: '>=4'} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pbf@3.3.0: + resolution: {integrity: sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==} + hasBin: true + + pbkdf2@3.1.2: + resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} + engines: {node: '>=0.12'} + + pdfast@0.2.0: + resolution: {integrity: sha512-cq6TTu6qKSFUHwEahi68k/kqN2mfepjkGrG9Un70cgdRRKLKY6Rf8P8uvP2NvZktaQZNF3YE7agEkLj0vGK9bA==} + + performance-now@2.1.0: + resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} + + picocolors@0.2.1: + resolution: {integrity: sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + + pify@3.0.0: + resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} + engines: {node: '>=4'} + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + + pkg-up@3.1.0: + resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==} + engines: {node: '>=8'} + + please-upgrade-node@3.2.0: + resolution: {integrity: sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==} + + pmtiles@2.11.0: + resolution: {integrity: sha512-dU9SzzaqmCGpdEuTnIba6bDHT6j09ZJFIXxwGpvkiEnce3ZnBB1VKt6+EOmJGueriweaZLAMTUmKVElU2CBe0g==} + + polygon-clipping@0.15.7: + resolution: {integrity: sha512-nhfdr83ECBg6xtqOAJab1tbksbBAOMUltN60bU+llHVOL0e5Onm1WpAXXWXVB39L8AJFssoIhEVuy/S90MmotA==} + + polyline-miter-util@1.0.1: + resolution: {integrity: sha512-/3u91zz6mBerBZo6qnOJOTjv7EfPhKtsV028jMyj86YpzLRNmCCFfrX7IO9tCEQ2W4x45yc+vKOezjf7u2Nd6Q==} + + polyline-normals@2.0.2: + resolution: {integrity: sha512-dpHrAi61ymhsB4N0XlNb3YpkKJeTFnXBXDWpeH8Ucstq0TUZrCN3YK4Jlgk8ofMWN25lhGC4wnxLMv+TUK8rig==} + + posix-character-classes@0.1.1: + resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==} + engines: {node: '>=0.10.0'} + + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + postcss-attribute-case-insensitive@4.0.2: + resolution: {integrity: sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA==} + + postcss-attribute-case-insensitive@5.0.2: + resolution: {integrity: sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-browser-comments@4.0.0: + resolution: {integrity: sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==} + engines: {node: '>=8'} + peerDependencies: + browserslist: '>=4' + postcss: '>=8' + + postcss-calc@8.2.4: + resolution: {integrity: sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==} + peerDependencies: + postcss: ^8.2.2 + + postcss-clamp@4.1.0: + resolution: {integrity: sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==} + engines: {node: '>=7.6.0'} + peerDependencies: + postcss: ^8.4.6 + + postcss-color-functional-notation@2.0.1: + resolution: {integrity: sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g==} + engines: {node: '>=6.0.0'} + + postcss-color-functional-notation@4.2.4: + resolution: {integrity: sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-color-gray@5.0.0: + resolution: {integrity: sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw==} + engines: {node: '>=6.0.0'} + + postcss-color-hex-alpha@5.0.3: + resolution: {integrity: sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw==} + engines: {node: '>=6.0.0'} + + postcss-color-hex-alpha@8.0.4: + resolution: {integrity: sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.4 + + postcss-color-mod-function@3.0.3: + resolution: {integrity: sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ==} + engines: {node: '>=6.0.0'} + + postcss-color-rebeccapurple@4.0.1: + resolution: {integrity: sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g==} + engines: {node: '>=6.0.0'} + + postcss-color-rebeccapurple@7.1.1: + resolution: {integrity: sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-colormin@5.3.1: + resolution: {integrity: sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-convert-values@5.1.3: + resolution: {integrity: sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-custom-media@7.0.8: + resolution: {integrity: sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg==} + engines: {node: '>=6.0.0'} + + postcss-custom-media@8.0.2: + resolution: {integrity: sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.3 + + postcss-custom-properties@12.1.11: + resolution: {integrity: sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-custom-properties@8.0.11: + resolution: {integrity: sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==} + engines: {node: '>=6.0.0'} + + postcss-custom-selectors@5.1.2: + resolution: {integrity: sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w==} + engines: {node: '>=6.0.0'} + + postcss-custom-selectors@6.0.3: + resolution: {integrity: sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.3 + + postcss-dir-pseudo-class@5.0.0: + resolution: {integrity: sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw==} + engines: {node: '>=4.0.0'} + + postcss-dir-pseudo-class@6.0.5: + resolution: {integrity: sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-discard-comments@5.1.2: + resolution: {integrity: sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-discard-duplicates@5.1.0: + resolution: {integrity: sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-discard-empty@5.1.1: + resolution: {integrity: sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-discard-overridden@5.1.0: + resolution: {integrity: sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-double-position-gradients@1.0.0: + resolution: {integrity: sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA==} + engines: {node: '>=6.0.0'} + + postcss-double-position-gradients@3.1.2: + resolution: {integrity: sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-env-function@2.0.2: + resolution: {integrity: sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw==} + engines: {node: '>=6.0.0'} + + postcss-env-function@4.0.6: + resolution: {integrity: sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.4 + + postcss-flexbugs-fixes@4.2.1: + resolution: {integrity: sha512-9SiofaZ9CWpQWxOwRh1b/r85KD5y7GgvsNt1056k6OYLvWUun0czCvogfJgylC22uJTwW1KzY3Gz65NZRlvoiQ==} + + postcss-flexbugs-fixes@5.0.2: + resolution: {integrity: sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==} + peerDependencies: + postcss: ^8.1.4 + + postcss-focus-visible@4.0.0: + resolution: {integrity: sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g==} + engines: {node: '>=6.0.0'} + + postcss-focus-visible@6.0.4: + resolution: {integrity: sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.4 + + postcss-focus-within@3.0.0: + resolution: {integrity: sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w==} + engines: {node: '>=6.0.0'} + + postcss-focus-within@5.0.4: + resolution: {integrity: sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.4 + + postcss-font-variant@4.0.1: + resolution: {integrity: sha512-I3ADQSTNtLTTd8uxZhtSOrTCQ9G4qUVKPjHiDk0bV75QSxXjVWiJVJ2VLdspGUi9fbW9BcjKJoRvxAH1pckqmA==} + + postcss-font-variant@5.0.0: + resolution: {integrity: sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==} + peerDependencies: + postcss: ^8.1.0 + + postcss-gap-properties@2.0.0: + resolution: {integrity: sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg==} + engines: {node: '>=6.0.0'} + + postcss-gap-properties@3.0.5: + resolution: {integrity: sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-image-set-function@3.0.1: + resolution: {integrity: sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw==} + engines: {node: '>=6.0.0'} + + postcss-image-set-function@4.0.7: + resolution: {integrity: sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-initial@3.0.4: + resolution: {integrity: sha512-3RLn6DIpMsK1l5UUy9jxQvoDeUN4gP939tDcKUHD/kM8SGSKbFAnvkpFpj3Bhtz3HGk1jWY5ZNWX6mPta5M9fg==} + + postcss-initial@4.0.1: + resolution: {integrity: sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.0.1: + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + + postcss-lab-function@2.0.1: + resolution: {integrity: sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg==} + engines: {node: '>=6.0.0'} + + postcss-lab-function@4.2.1: + resolution: {integrity: sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-less@6.0.0: + resolution: {integrity: sha512-FPX16mQLyEjLzEuuJtxA8X3ejDLNGGEG503d2YGZR5Ask1SpDN8KmZUMpzCvyalWRywAn1n1VOA5dcqfCLo5rg==} + engines: {node: '>=12'} + peerDependencies: + postcss: ^8.3.5 + + postcss-load-config@2.1.2: + resolution: {integrity: sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw==} + engines: {node: '>= 4'} + + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-loader@3.0.0: + resolution: {integrity: sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==} + engines: {node: '>= 6'} + + postcss-loader@6.2.1: + resolution: {integrity: sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==} + engines: {node: '>= 12.13.0'} + peerDependencies: + postcss: ^7.0.0 || ^8.0.1 + webpack: ^5.0.0 + + postcss-logical@3.0.0: + resolution: {integrity: sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==} + engines: {node: '>=6.0.0'} + + postcss-logical@5.0.4: + resolution: {integrity: sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.4 + + postcss-media-minmax@4.0.0: + resolution: {integrity: sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw==} + engines: {node: '>=6.0.0'} + + postcss-media-minmax@5.0.0: + resolution: {integrity: sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + postcss: ^8.1.0 + + postcss-merge-longhand@5.1.7: + resolution: {integrity: sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-merge-rules@5.1.4: + resolution: {integrity: sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-minify-font-values@5.1.0: + resolution: {integrity: sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-minify-gradients@5.1.1: + resolution: {integrity: sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-minify-params@5.1.4: + resolution: {integrity: sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-minify-selectors@5.2.1: + resolution: {integrity: sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-modules-extract-imports@3.1.0: + resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-local-by-default@4.2.0: + resolution: {integrity: sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-scope@3.2.1: + resolution: {integrity: sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-values@4.0.0: + resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-nesting@10.2.0: + resolution: {integrity: sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-nesting@7.0.1: + resolution: {integrity: sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==} + engines: {node: '>=6.0.0'} + + postcss-normalize-charset@5.1.0: + resolution: {integrity: sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-display-values@5.1.0: + resolution: {integrity: sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-positions@5.1.1: + resolution: {integrity: sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-repeat-style@5.1.1: + resolution: {integrity: sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-string@5.1.0: + resolution: {integrity: sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-timing-functions@5.1.0: + resolution: {integrity: sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-unicode@5.1.1: + resolution: {integrity: sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-url@5.1.0: + resolution: {integrity: sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-whitespace@5.1.1: + resolution: {integrity: sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize@10.0.1: + resolution: {integrity: sha512-+5w18/rDev5mqERcG3W5GZNMJa1eoYYNGo8gB7tEwaos0ajk3ZXAI4mHGcNT47NE+ZnZD1pEpUOFLvltIwmeJA==} + engines: {node: '>= 12'} + peerDependencies: + browserslist: '>= 4' + postcss: '>= 8' + + postcss-opacity-percentage@1.1.3: + resolution: {integrity: sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-ordered-values@5.1.3: + resolution: {integrity: sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-overflow-shorthand@2.0.0: + resolution: {integrity: sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g==} + engines: {node: '>=6.0.0'} + + postcss-overflow-shorthand@3.0.4: + resolution: {integrity: sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-page-break@2.0.0: + resolution: {integrity: sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ==} + + postcss-page-break@3.0.4: + resolution: {integrity: sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==} + peerDependencies: + postcss: ^8 + + postcss-place@4.0.1: + resolution: {integrity: sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg==} + engines: {node: '>=6.0.0'} + + postcss-place@7.0.5: + resolution: {integrity: sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-preset-env@6.7.0: + resolution: {integrity: sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg==} + engines: {node: '>=6.0.0'} + + postcss-preset-env@7.8.3: + resolution: {integrity: sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-pseudo-class-any-link@6.0.0: + resolution: {integrity: sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew==} + engines: {node: '>=6.0.0'} + + postcss-pseudo-class-any-link@7.1.6: + resolution: {integrity: sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-reduce-initial@5.1.2: + resolution: {integrity: sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-reduce-transforms@5.1.0: + resolution: {integrity: sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-replace-overflow-wrap@3.0.0: + resolution: {integrity: sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw==} + + postcss-replace-overflow-wrap@4.0.0: + resolution: {integrity: sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==} + peerDependencies: + postcss: ^8.0.3 + + postcss-safe-parser@4.0.2: + resolution: {integrity: sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g==} + engines: {node: '>=6.0.0'} + + postcss-selector-matches@4.0.0: + resolution: {integrity: sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww==} + + postcss-selector-not@4.0.1: + resolution: {integrity: sha512-YolvBgInEK5/79C+bdFMyzqTg6pkYqDbzZIST/PDMqa/o3qtXenD05apBG2jLgT0/BQ77d4U2UK12jWpilqMAQ==} + + postcss-selector-not@6.0.1: + resolution: {integrity: sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-selector-parser@5.0.0: + resolution: {integrity: sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==} + engines: {node: '>=4'} + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss-selector-parser@7.1.0: + resolution: {integrity: sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==} + engines: {node: '>=4'} + + postcss-strip-inline-comments@0.1.5: + resolution: {integrity: sha512-4EW5hYyv2syFyIBahkXGhZppp9zb5wD5NJ2R65WjXnB5q8T0g4VyLBTevU6ZpxtaN4HkoYZhV03DGUf5Ptd4FA==} + + postcss-svgo@5.1.0: + resolution: {integrity: sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-unique-selectors@5.1.1: + resolution: {integrity: sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss-values-parser@2.0.1: + resolution: {integrity: sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==} + engines: {node: '>=6.14.4'} + + postcss@5.2.18: + resolution: {integrity: sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==} + engines: {node: '>=0.12'} + + postcss@7.0.32: + resolution: {integrity: sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==} + engines: {node: '>=6.0.0'} + + postcss@7.0.39: + resolution: {integrity: sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==} + engines: {node: '>=6.0.0'} + + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + engines: {node: ^10 || ^12 || >=14} + + potpack@1.0.2: + resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==} + + potpack@2.0.0: + resolution: {integrity: sha512-Q+/tYsFU9r7xoOJ+y/ZTtdVQwTWfzjbiXBDMM/JKUux3+QPP02iUuIoeBQ+Ot6oEDlC+/PGjB/5A3K7KKb7hcw==} + + prelude-ls@1.1.2: + resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} + engines: {node: '>= 0.8.0'} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prepend-http@1.0.4: + resolution: {integrity: sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==} + engines: {node: '>=0.10.0'} + + preserve@0.2.0: + resolution: {integrity: sha512-s/46sYeylUfHNjI+sA/78FAHlmIuKqI9wNnzEOGehAlUUYeObv5C2mOinXBjyUyWmJ2SfcS2/ydApH4hTF4WXQ==} + engines: {node: '>=0.10.0'} + + prettier@2.2.1: + resolution: {integrity: sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + pretty-bytes@5.6.0: + resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} + engines: {node: '>=6'} + + pretty-error@2.1.2: + resolution: {integrity: sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==} + + pretty-error@4.0.0: + resolution: {integrity: sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==} + + pretty-format@26.6.2: + resolution: {integrity: sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==} + engines: {node: '>= 10'} + + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + pretty-format@28.1.3: + resolution: {integrity: sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + printj@1.1.2: + resolution: {integrity: sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==} + engines: {node: '>=0.8'} + hasBin: true + + prism-react-renderer@1.3.5: + resolution: {integrity: sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg==} + peerDependencies: + react: '>=0.14.9' + + prism-react@1.0.2: + resolution: {integrity: sha512-OoBo0kX55Fi+M4oGuYQ+AkU4/xSvB357mLXbYGP3j4oi4RtsdY5Rn3ViJ6gGU8IkZKs5cnmF7IteWWwUFyVd7Q==} + peerDependencies: + react: ^15.0.2 || ^0.14.8 + + prism-redux@1.0.2: + resolution: {integrity: sha512-e1DGRK+V/dxL6n6M25Py1QrAQLHkeueXyNxDTURT1y+KAMwSJdnlNvGU3ZLY2RIaA+ZdFTc9oTvTSR+mS88VyQ==} + + prism@4.1.2: + resolution: {integrity: sha512-SsqrfKkYKYEYz/7RRET2KVZd9O22Rnj3331Al06ClLMycKWoM+MpfrjQrKuHGoIJ9IOy+k27kPEFnqPoAeFZpA==} + + private@0.1.8: + resolution: {integrity: sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==} + engines: {node: '>= 0.6'} + + probe.gl@3.6.0: + resolution: {integrity: sha512-19JydJWI7+DtR4feV+pu4Mn1I5TAc0xojuxVgZdXIyfmTLfUaFnk4OloWK1bKbPtkgGKLr2lnbnCXmpZEcEp9g==} + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + + promise@7.3.1: + resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==} + + promise@8.3.0: + resolution: {integrity: sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + + protocol-buffers-schema@3.6.0: + resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + pseudomap@1.0.2: + resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + + psl@1.15.0: + resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} + + public-encrypt@4.0.3: + resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} + + pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + + punycode@1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + pure-color@1.3.0: + resolution: {integrity: sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA==} + + q@1.5.1: + resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==} + engines: {node: '>=0.6.0', teleport: '>=0.2.0'} + deprecated: |- + You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other. + + (For a CapTP with native promises, see @endo/eventual-send and @endo/captp) + + qs@6.13.0: + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} + engines: {node: '>=0.6'} + + qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + engines: {node: '>=0.6'} + + query-string@4.3.4: + resolution: {integrity: sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==} + engines: {node: '>=0.10.0'} + + query-string@6.14.1: + resolution: {integrity: sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==} + engines: {node: '>=6'} + + query-string@8.2.0: + resolution: {integrity: sha512-tUZIw8J0CawM5wyGBiDOAp7ObdRQh4uBor/fUR9ZjmbZVvw95OD9If4w3MQxr99rg0DJZ/9CIORcpEqU5hQG7g==} + engines: {node: '>=14.16'} + + query-string@9.1.1: + resolution: {integrity: sha512-MWkCOVIcJP9QSKU52Ngow6bsAWAPlPK2MludXvcrS2bGZSl+T1qX9MZvRIkqUIkGLJquMJHWfsT6eRqUpp4aWg==} + engines: {node: '>=18'} + + querystring-es3@0.2.1: + resolution: {integrity: sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==} + engines: {node: '>=0.4.x'} + + querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + quickselect@2.0.0: + resolution: {integrity: sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==} + + raf-schd@4.0.3: + resolution: {integrity: sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==} + + raf@3.4.1: + resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==} + + ramda@0.27.2: + resolution: {integrity: sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==} + + randexp@0.5.3: + resolution: {integrity: sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w==} + engines: {node: '>=4'} + + randomatic@3.1.1: + resolution: {integrity: sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==} + engines: {node: '>= 0.10.0'} + + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + + randomfill@1.0.4: + resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + + rc-align@2.4.5: + resolution: {integrity: sha512-nv9wYUYdfyfK+qskThf4BQUSIadeI/dCsfaMZfNEoxm9HwOIioQ+LyqmMK6jWHAZQgOzMLaqawhuBXlF63vgjw==} + + rc-align@4.0.15: + resolution: {integrity: sha512-wqJtVH60pka/nOX7/IspElA8gjPNQKIx/ZqJ6heATCkXpe1Zg4cPVrMD2vC96wjsFFL8WsmhPbx9tdMo1qqlIA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-animate@2.11.1: + resolution: {integrity: sha512-1NyuCGFJG/0Y+9RKh5y/i/AalUCA51opyyS/jO2seELpgymZm2u9QV3xwODwEuzkmeQ1BDPxMLmYLcTJedPlkQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-cascader@3.33.1: + resolution: {integrity: sha512-Kyl4EJ7ZfCBuidmZVieegcbFw0RcU5bHHSbtEdmuLYd0fYHCAiYKZ6zon7fWAVyC6rWWOOib0XKdTSf7ElC9rg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-cascader@3.7.3: + resolution: {integrity: sha512-KBpT+kzhxDW+hxPiNk4zaKa99+Lie2/8nnI11XF+FIOPl4Bj9VlFZi61GrnWzhLGA7VEN+dTxAkNOjkySDa0dA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-checkbox@2.0.3: + resolution: {integrity: sha512-sSDV5AcxK5CxBTyUNj9pb0zfhdgLLsWKHwJG18ikeGoIwklcxXvIF6cI/KGVbPLFDa8mPS5WLOlLRqbq/1/ouw==} + + rc-checkbox@3.0.1: + resolution: {integrity: sha512-k7nxDWxYF+jDI0ZcCvuvj71xONmWRVe5+1MKcERRR9MRyP3tZ69b+yUCSXXh+sik4/Hc9P5wHr2nnUoGS2zBjA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-checkbox@3.5.0: + resolution: {integrity: sha512-aOAQc3E98HteIIsSqm6Xk2FPKIER6+5vyEFMZfo73TqM+VVAIqOkHoPjgKLqSNtVLWScoaM7vY2ZrGEheI79yg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-collapse@1.9.3: + resolution: {integrity: sha512-8cG+FzudmgFCC9zRGKXJZA36zoI9Dmyjp6UDi8N80sXUch0JOpsZDxgcFzw4HPpPpK/dARtTilEe9zyuspnW0w==} + + rc-collapse@3.4.2: + resolution: {integrity: sha512-jpTwLgJzkhAgp2Wpi3xmbTbbYExg6fkptL67Uu5LCRVEj6wqmy0DHTjjeynsjOLsppHGHu41t1ELntZ0lEvS/Q==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-collapse@3.9.0: + resolution: {integrity: sha512-swDdz4QZ4dFTo4RAUMLL50qP0EY62N2kvmk2We5xYdRwcRn8WcYtuetCJpwpaCbUfUt5+huLpVxhvmnK+PHrkA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-dialog@9.0.4: + resolution: {integrity: sha512-pmnPRZKd9CGzGgf4a1ysBvMhxm8Afx5fF6M7AzLtJ0qh8X1bshurDlqnK4MBNAB4hAeAMMbz6Ytb1rkGMvKFbQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-dialog@9.6.0: + resolution: {integrity: sha512-ApoVi9Z8PaCQg6FsUzS8yvBEQy0ZL2PkuvAgrmohPkN3okps5WZ5WQWPc1RNuiOKaAYv8B97ACdsFU5LizzCqg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-drawer@6.3.0: + resolution: {integrity: sha512-uBZVb3xTAR+dBV53d/bUhTctCw3pwcwJoM7g5aX+7vgwt2zzVzoJ6aqFjYJpBlZ9zp0dVYN8fV+hykFE7c4lig==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-drawer@7.2.0: + resolution: {integrity: sha512-9lOQ7kBekEJRdEpScHvtmEtXnAsy+NGDXiRWc2ZVC7QXAazNVbeT4EraQKYwCME8BJLa8Bxqxvs5swwyOepRwg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-dropdown@3.6.2: + resolution: {integrity: sha512-Wsw7GkVbUXADEs8FPL0v8gd+3mWQiydPFXBlr2imMScQaf8hh79pG9KrBc1DwK+nqHmYOpQfK2gn6jG2AQw9Pw==} + peerDependencies: + react: '>=16.11.0' + react-dom: '>=16.11.0' + + rc-dropdown@4.0.1: + resolution: {integrity: sha512-OdpXuOcme1rm45cR0Jzgfl1otzmU4vuBVb+etXM8vcaULGokAKVpKlw8p6xzspG7jGd/XxShvq+N3VNEfk/l5g==} + peerDependencies: + react: '>=16.11.0' + react-dom: '>=16.11.0' + + rc-dropdown@4.2.1: + resolution: {integrity: sha512-YDAlXsPv3I1n42dv1JpdM7wJ+gSUBfeyPK59ZpBD9jQhK9jVuxpjj3NmWQHOBceA1zEPVX84T2wbdb2SD0UjmA==} + peerDependencies: + react: '>=16.11.0' + react-dom: '>=16.11.0' + + rc-editor-core@0.8.10: + resolution: {integrity: sha512-T3aHpeMCIYA1sdAI7ynHHjXy5fqp83uPlD68ovZ0oClTSc3tbHmyCxXlA+Ti4YgmcpCYv7avF6a+TIbAka53kw==} + peerDependencies: + react: '>=15.0.0' + react-dom: '>=15.0.0' + + rc-editor-mention@1.1.13: + resolution: {integrity: sha512-3AOmGir91Fi2ogfRRaXLtqlNuIwQpvla7oUnGHS1+3eo7b+fUp5IlKcagqtwUBB5oDNofoySXkLBxzWvSYNp/Q==} + peerDependencies: + react: '>=15.x' + react-dom: '>=15.x' + + rc-field-form@1.38.2: + resolution: {integrity: sha512-O83Oi1qPyEv31Sg+Jwvsj6pXc8uQI2BtIAkURr5lvEYHVggXJhdU/nynK8wY1gbw0qR48k731sN5ON4egRCROA==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-field-form@1.44.0: + resolution: {integrity: sha512-el7w87fyDUsca63Y/s8qJcq9kNkf/J5h+iTdqG5WsSHLH0e6Usl7QuYSmSVzJMgtp40mOVZIY/W/QP9zwrp1FA==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-field-form@2.7.0: + resolution: {integrity: sha512-hgKsCay2taxzVnBPZl+1n4ZondsV78G++XVsMIJCAoioMjlMQR9YwAp7JZDIECzIu2Z66R+f4SFIRrO2DjDNAA==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-form@2.4.12: + resolution: {integrity: sha512-sHfyWRrnjCHkeCYfYAGop2GQBUC6CKMPcJF9h/gL/vTmZB/RN6fNOGKjXrXjFbwFwKXUWBoPtIDDDmXQW9xNdw==} + peerDependencies: + prop-types: ^15.0 + + rc-gesture@0.0.22: + resolution: {integrity: sha512-6G6qrCE0MUTXyjh/powj91XkjRjoFL4HiJLPU5lALXHvGX+/efcUjGYUrHrrw0mwQdmrmg4POqnY/bibns+G3g==} + + rc-image@5.13.0: + resolution: {integrity: sha512-iZTOmw5eWo2+gcrJMMcnd7SsxVHl3w5xlyCgsULUdJhJbnuI8i/AL0tVOsE7aLn9VfOh1qgDT3mC2G75/c7mqg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-image@7.11.1: + resolution: {integrity: sha512-XuoWx4KUXg7hNy5mRTy1i8c8p3K8boWg6UajbHpDXS5AlRVucNfTi5YxTtPBTBzegxAZpvuLfh3emXFt6ybUdA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-input-number@7.3.11: + resolution: {integrity: sha512-aMWPEjFeles6PQnMqP5eWpxzsvHm9rh1jQOWXExUEIxhX62Fyl/ptifLHOn17+waDG1T/YUb6flfJbvwRhHrbA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-input-number@9.5.0: + resolution: {integrity: sha512-bKaEvB5tHebUURAEXw35LDcnRZLq3x1k7GxfAqBMzmpHkDGzjAtnUL8y4y5N15rIFIg5IJgwr211jInl3cipag==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-input@0.1.4: + resolution: {integrity: sha512-FqDdNz+fV2dKNgfXzcSLKvC+jEs1709t7nD+WdfjrdSaOcefpgc7BUJYadc3usaING+b7ediMTfKxuJBsEFbXA==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + + rc-input@1.8.0: + resolution: {integrity: sha512-KXvaTbX+7ha8a/k+eg6SYRVERK0NddX8QX7a7AnRvUa/rEH0CNMlpcBzBkhI0wp2C8C4HlMoYl8TImSN+fuHKA==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + + rc-mentions@1.13.1: + resolution: {integrity: sha512-FCkaWw6JQygtOz0+Vxz/M/NWqrWHB9LwqlY2RtcuFqWJNFK9njijOOzTSsBGANliGufVUzx/xuPHmZPBV0+Hgw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-mentions@2.20.0: + resolution: {integrity: sha512-w8HCMZEh3f0nR8ZEd466ATqmXFCMGMN5UFCzEUL0bM/nGw/wOS2GgRzKBcm19K++jDyuWCOJOdgcKGXU3fXfbQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-menu@9.16.1: + resolution: {integrity: sha512-ghHx6/6Dvp+fw8CJhDUHFHDJ84hJE3BXNCzSgLdmNiFErWSOaZNsihDAsKq9ByTALo/xkNIwtDFGIl6r+RPXBg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-menu@9.8.4: + resolution: {integrity: sha512-lmw2j8I2fhdIzHmC9ajfImfckt0WDb2KVJJBBRIsxPEw2kGkEfjLMUoB1NgiNT/Q5cC8PdjGOGQjHJIJMwyNMw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-motion@2.9.5: + resolution: {integrity: sha512-w+XTUrfh7ArbYEd2582uDrEhmBHwK1ZENJiSJVb7uRxdE7qJSYjbO2eksRXmndqyKqKoYPc9ClpPh5242mV1vA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-notification@4.6.1: + resolution: {integrity: sha512-NSmFYwrrdY3+un1GvDAJQw62Xi9LNMSsoQyo95tuaYrcad5Bn9gJUL8AREufRxSQAQnr64u3LtP3EUyLYT6bhw==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-notification@5.6.4: + resolution: {integrity: sha512-KcS4O6B4qzM3KH7lkwOB7ooLPZ4b6J+VMmQgT51VZCeEcmghdeR4IrMcFq0LG+RPdnbe/ArT086tGM8Snimgiw==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-overflow@1.4.1: + resolution: {integrity: sha512-3MoPQQPV1uKyOMVNd6SZfONi+f3st0r8PksexIdBTeIYbMX0Jr+k7pHEDvsXtR4BpCv90/Pv2MovVNhktKrwvw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-pagination@3.2.0: + resolution: {integrity: sha512-5tIXjB670WwwcAJzAqp2J+cOBS9W3cH/WU1EiYwXljuZ4vtZXKlY2Idq8FZrnYBz8KhN3vwPo9CoV/SJS6SL1w==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-pagination@5.1.0: + resolution: {integrity: sha512-8416Yip/+eclTFdHXLKTxZvn70duYVGTvUUWbckCCZoIl3jagqke3GLsFrMs0bsQBikiYpZLD9206Ej4SOdOXQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-picker@2.7.6: + resolution: {integrity: sha512-H9if/BUJUZBOhPfWcPeT15JUI3/ntrG9muzERrXDkSoWmDj4yzmBvumozpxYrHwjcKnjyDGAke68d+whWwvhHA==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-picker@4.11.3: + resolution: {integrity: sha512-MJ5teb7FlNE0NFHTncxXQ62Y5lytq6sh5nUw0iH8OkHL/TjARSEvSHpr940pWgjGANpjCwyMdvsEV55l5tYNSg==} + engines: {node: '>=8.x'} + peerDependencies: + date-fns: '>= 2.x' + dayjs: '>= 1.x' + luxon: '>= 3.x' + moment: '>= 2.x' + react: '>=16.9.0' + react-dom: '>=16.9.0' + peerDependenciesMeta: + date-fns: + optional: true + dayjs: + optional: true + luxon: + optional: true + moment: + optional: true + + rc-progress@3.4.2: + resolution: {integrity: sha512-iAGhwWU+tsayP+Jkl9T4+6rHeQTG9kDz8JAHZk4XtQOcYN5fj9H34NXNEdRdZx94VUDHMqCb1yOIvi8eJRh67w==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-progress@4.0.0: + resolution: {integrity: sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-rate@2.13.1: + resolution: {integrity: sha512-QUhQ9ivQ8Gy7mtMZPAjLbxBt5y9GRp65VcUyGUMF3N3fhiftivPHdpuDIaWIMOTEprAjZPC08bls1dQB+I1F2Q==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-rate@2.9.3: + resolution: {integrity: sha512-2THssUSnRhtqIouQIIXqsZGzRczvp4WsH4WvGuhiwm+LG2fVpDUJliP9O1zeDOZvYfBE/Bup4SgHun/eCkbjgQ==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-resize-observer@0.2.6: + resolution: {integrity: sha512-YX6nYnd6fk7zbuvT6oSDMKiZjyngjHoy+fz+vL3Tez38d/G5iGdaDJa2yE7345G6sc4Mm1IGRUIwclvltddhmA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-resize-observer@1.4.3: + resolution: {integrity: sha512-YZLjUbyIWox8E9i9C3Tm7ia+W7euPItNWSPX5sCcQTYbnwDb5uNpnLHQCG1f22oZWUhLw4Mv2tFmeWe68CDQRQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-segmented@2.3.0: + resolution: {integrity: sha512-I3FtM5Smua/ESXutFfb8gJ8ZPcvFR+qUgeeGFQHBOvRiRKyAk4aBE5nfqrxXx+h8/vn60DQjOt6i4RNtrbOobg==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + + rc-segmented@2.7.0: + resolution: {integrity: sha512-liijAjXz+KnTRVnxxXG2sYDGd6iLL7VpGGdR8gwoxAXy2KglviKCxLWZdjKYJzYzGSUwKDSTdYk8brj54Bn5BA==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + + rc-select@14.1.18: + resolution: {integrity: sha512-4JgY3oG2Yz68ECMUSCON7mtxuJvCSj+LJpHEg/AONaaVBxIIrmI/ZTuMJkyojall/X50YdBe5oMKqHHPNiPzEg==} + engines: {node: '>=8.x'} + peerDependencies: + react: '*' + react-dom: '*' + + rc-select@14.16.6: + resolution: {integrity: sha512-YPMtRPqfZWOm2XGTbx5/YVr1HT0vn//8QS77At0Gjb3Lv+Lbut0IORJPKLWu1hQ3u4GsA0SrDzs7nI8JG7Zmyg==} + engines: {node: '>=8.x'} + peerDependencies: + react: '*' + react-dom: '*' + + rc-slider@10.0.1: + resolution: {integrity: sha512-igTKF3zBet7oS/3yNiIlmU8KnZ45npmrmHlUUio8PNbIhzMcsh+oE/r2UD42Y6YD2D/s+kzCQkzQrPD6RY435Q==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-slider@11.1.8: + resolution: {integrity: sha512-2gg/72YFSpKP+Ja5AjC5DPL1YnV8DEITDQrcc1eASrUYjl0esptaBVJBh5nLTXCCp15eD8EuGjwezVGSHhs9tQ==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-slider@8.2.0: + resolution: {integrity: sha512-rnO36M3VhMoPWh1kRuCeJoluT4duAW7+5aLaAn9oLu2pKEKsuOFUh5DmA2kEo88UmvPV6nr7HHDeZuC8SNM/lA==} + + rc-steps@5.0.0: + resolution: {integrity: sha512-9TgRvnVYirdhbV0C3syJFj9EhCRqoJAsxt4i1rED5o8/ZcSv5TLIYyo4H8MCjLPvbe2R+oBAm/IYBEtC+OS1Rw==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-steps@6.0.1: + resolution: {integrity: sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-swipeout@2.0.11: + resolution: {integrity: sha512-d37Lgn4RX4OOQyuA2BFo0rGlUwrmZk5q83srH3ixJ1Y1jidr2GKjgJDbNeGUVZPNfYBL91Elu6+xfVGftWf4Lg==} + + rc-switch@3.2.2: + resolution: {integrity: sha512-+gUJClsZZzvAHGy1vZfnwySxj+MjLlGRyXKXScrtCTcmiYNPzxDFOxdQ/3pK1Kt/0POvwJ/6ALOR8gwdXGhs+A==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-switch@4.1.0: + resolution: {integrity: sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-table@7.26.0: + resolution: {integrity: sha512-0cD8e6S+DTGAt5nBZQIPFYEaIukn17sfa5uFL98faHlH/whZzD8ii3dbFL4wmUDEL4BLybhYop+QUfZJ4CPvNQ==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-table@7.50.4: + resolution: {integrity: sha512-Y+YuncnQqoS5e7yHvfvlv8BmCvwDYDX/2VixTBEhkMDk9itS9aBINp4nhzXFKiBP/frG4w0pS9d9Rgisl0T1Bw==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-tabs@12.5.10: + resolution: {integrity: sha512-Ay0l0jtd4eXepFH9vWBvinBjqOpqzcsJTerBGwJy435P2S90Uu38q8U/mvc1sxUEVOXX5ZCFbxcWPnfG3dH+tQ==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-tabs@15.6.0: + resolution: {integrity: sha512-SQ99Yjc9ewrJCUwoWPKq0FeGL2znWsqPhfcZgsHz1R7bkA2rMNe7CPgOiJkwppdJ98wkLhzs9vPrv21QOE1RyQ==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-textarea@0.4.7: + resolution: {integrity: sha512-IQPd1CDI3mnMlkFyzt2O4gQ2lxUsnBAeJEoZGJnkkXgORNqyM9qovdrCj9NzcRfpHgLdzaEbU3AmobNFGUznwQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-textarea@1.10.0: + resolution: {integrity: sha512-ai9IkanNuyBS4x6sOL8qu/Ld40e6cEs6pgk93R+XLYg0mDSjNBGey6/ZpDs5+gNLD7urQ14po3V6Ck2dJLt9SA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-tooltip@3.7.3: + resolution: {integrity: sha512-dE2ibukxxkrde7wH9W8ozHKUO4aQnPZ6qBHtrTH9LoO836PjDdiaWO73fgPB05VfJs9FbZdmGPVEbXCeOP99Ww==} + + rc-tooltip@5.2.2: + resolution: {integrity: sha512-jtQzU/18S6EI3lhSGoDYhPqNpWajMtS5VV/ld1LwyfrDByQpYmw/LW6U7oFXXLukjfDHQ7Ju705A82PRNFWYhg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-tooltip@6.4.0: + resolution: {integrity: sha512-kqyivim5cp8I5RkHmpsp1Nn/Wk+1oeloMv9c7LXNgDxUpGm+RbXJGL+OPvDlcRnx9DBeOe4wyOIl4OKUERyH1g==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-tree-select@5.27.0: + resolution: {integrity: sha512-2qTBTzwIT7LRI1o7zLyrCzmo5tQanmyGbSaGTIf7sYimCklAToVVfpMC6OAldSKolcnjorBYPNSKQqJmN3TCww==} + peerDependencies: + react: '*' + react-dom: '*' + + rc-tree-select@5.5.5: + resolution: {integrity: sha512-k2av7jF6tW9bIO4mQhaVdV4kJ1c54oxV3/hHVU+oD251Gb5JN+m1RbJFTMf1o0rAFqkvto33rxMdpafaGKQRJw==} + peerDependencies: + react: '*' + react-dom: '*' + + rc-tree@5.13.1: + resolution: {integrity: sha512-FNhIefhftobCdUJshO7M8uZTA9F4OPGVXqGfZkkD/5soDeOhwO06T/aKTrg0WD8gRg/pyfq+ql3aMymLHCTC4A==} + engines: {node: '>=10.x'} + peerDependencies: + react: '*' + react-dom: '*' + + rc-tree@5.7.12: + resolution: {integrity: sha512-LXA5nY2hG5koIAlHW5sgXgLpOMz+bFRbnZZ+cCg0tQs4Wv1AmY7EDi1SK7iFXhslYockbqUerQan82jljoaItg==} + engines: {node: '>=10.x'} + peerDependencies: + react: '*' + react-dom: '*' + + rc-trigger@2.6.5: + resolution: {integrity: sha512-m6Cts9hLeZWsTvWnuMm7oElhf+03GOjOLfTuU0QmdB9ZrW7jR2IpI5rpNM7i9MvAAlMAmTx5Zr7g3uu/aMvZAw==} + + rc-trigger@5.3.4: + resolution: {integrity: sha512-mQv+vas0TwKcjAO2izNPkqR4j86OemLRmvL2nOzdP9OWNWA1ivoTt5hzFqYNW9zACwmTezRiN8bttrC7cZzYSw==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-upload@4.3.6: + resolution: {integrity: sha512-Bt7ESeG5tT3IY82fZcP+s0tQU2xmo1W6P3S8NboUUliquJLQYLkUcsaExi3IlBVr43GQMCjo30RA2o0i70+NjA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-upload@4.8.1: + resolution: {integrity: sha512-toEAhwl4hjLAI1u8/CgKWt30BR06ulPa4iGQSMvSXoHzO88gPCslxqV/mnn4gJU7PDoltGIC9Eh+wkeudqgHyw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-util@4.21.1: + resolution: {integrity: sha512-Z+vlkSQVc1l8O2UjR3WQ+XdWlhj5q9BMQNLk2iOBch75CqPfrJyGtcWMcnhRlNuDu0Ndtt4kLVO8JI8BrABobg==} + + rc-util@5.44.4: + resolution: {integrity: sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-virtual-list@3.18.5: + resolution: {integrity: sha512-1FuxVSxhzTj3y8k5xMPbhXCB0t2TOiI3Tq+qE2Bu+GGV7f+ECVuQl4OUg6lZ2qT5fordTW7CBpr9czdzXCI7Pg==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + react-app-polyfill@3.0.0: + resolution: {integrity: sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w==} + engines: {node: '>=14'} + + react-base16-styling@0.6.0: + resolution: {integrity: sha512-yvh/7CArceR/jNATXOKDlvTnPKPmGZz7zsenQ3jUwLzHkNUR0CvY3yGYJbWJ/nnxsL8Sgmt5cO3/SILVuPO6TQ==} + + react-beautiful-dnd@12.2.0: + resolution: {integrity: sha512-s5UrOXNDgeEC+sx65IgbeFlqKKgK3c0UfbrJLWufP34WBheyu5kJ741DtJbsSgPKyNLkqfswpMYr0P8lRj42cA==} + deprecated: 'react-beautiful-dnd is now deprecated. Context and options: https://github.com/atlassian/react-beautiful-dnd/issues/2672' + peerDependencies: + react: ^16.8.5 + react-dom: ^16.8.5 + + react-color@2.17.1: + resolution: {integrity: sha512-S+I6TkUKJaqfALLkAIfiCZ/MANQyy7dKkf7g9ZU5GTUy2rf8c2Rx62otyvADAviWR+6HRkzdf2vL1Qvz9goCLQ==} + peerDependencies: + react: '*' + + react-color@2.17.3: + resolution: {integrity: sha512-1dtO8LqAVotPIChlmo6kLtFS1FP89ll8/OiA8EcFRDR+ntcK+0ukJgByuIQHRtzvigf26dV5HklnxDIvhON9VQ==} + peerDependencies: + react: '*' + + react-content-loader@5.1.4: + resolution: {integrity: sha512-hTq7pZi2GKCK6a9d3u6XStozm0QGCEjw8cSqQReiWnh2up6IwCha5R5TF0o6SY5qUDpByloEZEZtnFxpJyENFw==} + engines: {node: '>=10'} + peerDependencies: + react: '>=16.0.0' + + react-copy-to-clipboard@5.1.0: + resolution: {integrity: sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==} + peerDependencies: + react: ^15.3.0 || 16 || 17 || 18 + + react-dev-utils@12.0.1: + resolution: {integrity: sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=2.7' + webpack: '>=4' + peerDependenciesMeta: + typescript: + optional: true + + react-dom@16.14.0: + resolution: {integrity: sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==} + peerDependencies: + react: ^16.14.0 + + react-error-overlay@6.1.0: + resolution: {integrity: sha512-SN/U6Ytxf1QGkw/9ve5Y+NxBbZM6Ht95tuXNMKs8EJyFa/Vy/+Co3stop3KBHARfn/giv+Lj1uUnTfOJ3moFEQ==} + + react-fast-compare@3.2.2: + resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} + + react-helmet@6.1.0: + resolution: {integrity: sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==} + peerDependencies: + react: '>=16.3.0' + + react-intl@3.12.1: + resolution: {integrity: sha512-cgumW29mwROIqyp8NXStYsoIm27+8FqnxykiLSawWjOxGIBeLuN/+p2srei5SRIumcJefOkOIHP+NDck05RgHg==} + peerDependencies: + react: ^16.3.0 + + react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + react-json-view@1.21.3: + resolution: {integrity: sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw==} + peerDependencies: + react: ^17.0.0 || ^16.3.0 || ^15.5.4 + react-dom: ^17.0.0 || ^16.3.0 || ^15.5.4 + + react-lifecycles-compat@3.0.4: + resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==} + + react-native-swipeout@2.3.6: + resolution: {integrity: sha512-t9suUCspzck4vp2pWggWe0frS/QOtX6yYCawHnEes75A7dZCEE74bxX2A1bQzGH9cUMjq6xsdfC94RbiDKIkJg==} + deprecated: Package no longer supported. Use at your own risk or consider using https://github.com/software-mansion/react-native-gesture-handler + + react-redux@7.2.9: + resolution: {integrity: sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==} + peerDependencies: + react: ^16.8.3 || ^17 || ^18 + react-dom: '*' + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + + react-refresh@0.10.0: + resolution: {integrity: sha512-PgidR3wST3dDYKr6b4pJoqQFpPGNKDSCDx4cZoshjXipw3LzO7mG1My2pwEzz2JVkF+inx3xRpDeQLFQGH/hsQ==} + engines: {node: '>=0.10.0'} + + react-refresh@0.11.0: + resolution: {integrity: sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==} + engines: {node: '>=0.10.0'} + + react-resize-detector@7.1.2: + resolution: {integrity: sha512-zXnPJ2m8+6oq9Nn8zsep/orts9vQv3elrpA+R8XTcW7DVVUJ9vwDwMXaBtykAYjMnkCIaOoK9vObyR7ZgFNlOw==} + peerDependencies: + react: ^16.0.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 + + react-router-config@5.1.1: + resolution: {integrity: sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==} + peerDependencies: + react: '>=15' + react-router: '>=5' + + react-router-dom@5.2.0: + resolution: {integrity: sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==} + peerDependencies: + react: '>=15' + + react-router-dom@5.3.4: + resolution: {integrity: sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==} + peerDependencies: + react: '>=15' + + react-router@5.2.0: + resolution: {integrity: sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==} + peerDependencies: + react: '>=15' + + react-router@5.3.4: + resolution: {integrity: sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==} + peerDependencies: + react: '>=15' + + react-scripts@5.0.1: + resolution: {integrity: sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==} + engines: {node: '>=14.0.0'} + hasBin: true + peerDependencies: + eslint: '*' + react: '>= 16' + typescript: ^3.2.1 || ^4 + peerDependenciesMeta: + typescript: + optional: true + + react-side-effect@2.1.2: + resolution: {integrity: sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==} + peerDependencies: + react: ^16.3.0 || ^17.0.0 || ^18.0.0 + + react-split-pane@0.1.92: + resolution: {integrity: sha512-GfXP1xSzLMcLJI5BM36Vh7GgZBpy+U/X0no+VM3fxayv+p1Jly5HpMofZJraeaMl73b3hvlr+N9zJKvLB/uz9w==} + peerDependencies: + react: ^16.0.0-0 + react-dom: ^16.0.0-0 + + react-sticky-mouse-tooltip@0.0.1: + resolution: {integrity: sha512-nuKyvolX3Zsu48uoGXkEvEE8oAwl7jaUvJrA/SxCSmBmbzmECNBQp03Z60L6/1ImLUzLFUHh2Wul3GpkEffrPw==} + peerDependencies: + react: ^16.1.0 + react-dom: ^16.1.0 + + react-style-proptype@3.2.2: + resolution: {integrity: sha512-ywYLSjNkxKHiZOqNlso9PZByNEY+FTyh3C+7uuziK0xFXu9xzdyfHwg4S9iyiRRoPCR4k2LqaBBsWVmSBwCWYQ==} + + react-textarea-autosize@8.5.9: + resolution: {integrity: sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==} + engines: {node: '>=10'} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + react-tween-state@0.1.5: + resolution: {integrity: sha512-sJQpjsdn0wjlDIUpfpb7jQGnOG8hAEW2e8k0KPA+xmf5KFa6Xat2JldbmxBhaqP0S/uIXhVE5ymKyH/b9X8nYA==} + + react-universal-interface@0.6.2: + resolution: {integrity: sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==} + peerDependencies: + react: '*' + tslib: '*' + + react-use@17.3.1: + resolution: {integrity: sha512-hs7+tS4rRm1QLHPfanLCqXIi632tP4V7Sai1ENUP2WTufU6am++tU9uSw9YrNCFqbABiEv0ndKU1XCUcfu2tXA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 + react-dom: ^16.8.0 || ^17.0.0 + + react@16.14.0: + resolution: {integrity: sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==} + engines: {node: '>=0.10.0'} + + reactcss@1.2.3: + resolution: {integrity: sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==} + peerDependencies: + react: '*' + + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + + read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + + read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdirp@2.2.1: + resolution: {integrity: sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==} + engines: {node: '>=0.10'} + + readdirp@3.5.0: + resolution: {integrity: sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==} + engines: {node: '>=8.10.0'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + recompose@0.22.0: + resolution: {integrity: sha512-QjNK/CgNg6wa7sqaQelgkRdl7ktIYbOV4xp0m2n8TexmHI5h3gjOc5a6nNQhtH3Js63hGZ1HfvJ3DUErrvZ2yg==} + peerDependencies: + react: ^0.14.0 || ^15.0.0 + + recursive-readdir@2.2.3: + resolution: {integrity: sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==} + engines: {node: '>=6.0.0'} + + redbox-react@1.6.0: + resolution: {integrity: sha512-mLjM5eYR41yOp5YKHpd3syFeGq6B4Wj5vZr64nbLvTZW5ZLff4LYk7VE4ITpVxkZpCY6OZuqh0HiP3A3uEaCpg==} + peerDependencies: + react: ^0.14.0 || ^15.0.0 || ^16.0.0-beta || ^16.0.0 + react-dom: ^0.14.0 || ^15.0.0 || ^16.0.0-beta || ^16.0.0 + + redux-saga@0.16.2: + resolution: {integrity: sha512-iIjKnRThI5sKPEASpUvySemjzwqwI13e3qP7oLub+FycCRDysLSAOwt958niZW6LhxfmS6Qm1BzbU70w/Koc4w==} + + redux@4.2.1: + resolution: {integrity: sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==} + + reflect-metadata@0.1.14: + resolution: {integrity: sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==} + + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} + + reftools@1.1.9: + resolution: {integrity: sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==} + + regenerate-unicode-properties@10.0.1: + resolution: {integrity: sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==} + engines: {node: '>=4'} + + regenerate-unicode-properties@10.2.0: + resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==} + engines: {node: '>=4'} + + regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + + regenerator-runtime@0.10.5: + resolution: {integrity: sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==} + + regenerator-runtime@0.11.1: + resolution: {integrity: sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==} + + regenerator-runtime@0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + + regenerator-runtime@0.13.5: + resolution: {integrity: sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==} + + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + + regenerator-transform@0.10.1: + resolution: {integrity: sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==} + + regenerator-transform@0.15.2: + resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} + + regex-cache@0.4.4: + resolution: {integrity: sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==} + engines: {node: '>=0.10.0'} + + regex-not@1.0.2: + resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} + engines: {node: '>=0.10.0'} + + regex-parser@2.3.1: + resolution: {integrity: sha512-yXLRqatcCuKtVHsWrNg0JL3l1zGfdXeEvDa0bdu4tCDQw0RpMDZsqbkyRTUnKMR0tXF627V2oEWjBEaEdqTwtQ==} + + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + + regexpu-core@2.0.0: + resolution: {integrity: sha512-tJ9+S4oKjxY8IZ9jmjnp/mtytu1u3iyIQAfmI51IKWH6bFf7XR1ybtaO6j7INhZKXOTYADk7V5qxaqLkmNxiZQ==} + + regexpu-core@6.2.0: + resolution: {integrity: sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==} + engines: {node: '>=4'} + + regjsgen@0.2.0: + resolution: {integrity: sha512-x+Y3yA24uF68m5GA+tBjbGYo64xXVJpbToBaWCoSNSc1hdk6dfctaRWrNFTVJZIIhL5GxW8zwjoixbnifnK59g==} + + regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} + + regjsparser@0.1.5: + resolution: {integrity: sha512-jlQ9gYLfk2p3V5Ag5fYhA7fv7OHzd1KUH0PRP46xc3TgwjwgROIW572AfYg/X9kaNq/LJnu6oJcFRXlIrGoTRw==} + hasBin: true + + regjsparser@0.12.0: + resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} + hasBin: true + + regl@1.6.1: + resolution: {integrity: sha512-7Z9rmpEqmLNwC9kCYCyfyu47eWZaQWeNpwZfwz99QueXN8B/Ow40DB0N+OeUeM/yu9pZAB01+JgJ+XghGveVoA==} + + regl@1.7.0: + resolution: {integrity: sha512-bEAtp/qrtKucxXSJkD4ebopFZYP0q1+3Vb2WECWv/T8yQEgKxDxJ7ztO285tAMaYZVR6mM1GgI6CCn8FROtL1w==} + + relateurl@0.2.7: + resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} + engines: {node: '>= 0.10'} + + remove-trailing-separator@1.1.0: + resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==} + + renderkid@2.0.7: + resolution: {integrity: sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==} + + renderkid@3.0.0: + resolution: {integrity: sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==} + + repeat-element@1.1.4: + resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==} + engines: {node: '>=0.10.0'} + + repeat-string@1.6.1: + resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} + engines: {node: '>=0.10'} + + repeating@2.0.1: + resolution: {integrity: sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==} + engines: {node: '>=0.10.0'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + + reserved-words@0.1.2: + resolution: {integrity: sha512-0S5SrIUJ9LfpbVl4Yzij6VipUdafHrOTzvmfazSw/jeZrZtQK303OPZW+obtkaw7jQlTQppy0UvZWm9872PbRw==} + + resize-observer-polyfill@1.5.1: + resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} + + resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + + resolve-from@3.0.0: + resolution: {integrity: sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==} + engines: {node: '>=4'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-pathname@3.0.0: + resolution: {integrity: sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==} + + resolve-protobuf-schema@2.1.0: + resolution: {integrity: sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==} + + resolve-url-loader@4.0.0: + resolution: {integrity: sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==} + engines: {node: '>=8.9'} + peerDependencies: + rework: 1.0.1 + rework-visit: 1.0.0 + peerDependenciesMeta: + rework: + optional: true + rework-visit: + optional: true + + resolve-url@0.2.1: + resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} + deprecated: https://github.com/lydell/resolve-url#deprecated + + resolve.exports@1.1.1: + resolution: {integrity: sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==} + engines: {node: '>=10'} + + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} + hasBin: true + + resolve@2.0.0-next.5: + resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} + hasBin: true + + restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + + ret@0.1.15: + resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} + engines: {node: '>=0.12'} + + ret@0.2.2: + resolution: {integrity: sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==} + engines: {node: '>=4'} + + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + + right-align@0.1.3: + resolution: {integrity: sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==} + engines: {node: '>=0.10.0'} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + ripemd160@2.0.2: + resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} + + rmc-align@1.0.0: + resolution: {integrity: sha512-3gEa5/+hqqoEVoeQ25KoRc8DOsXIdSaVpaBq1zQFaV941LR3xvZIRTlxTDT/IagYwoGM1KZea/jd7cNMYP34Rg==} + + rmc-calendar@1.1.4: + resolution: {integrity: sha512-xxQZaPFDnpHt4IFO8mukYrXSgC1W8LcNVp+EoX4iyeOJFimungOKB/iP5/cy+st8yXq8lUgk9TXsHNtM6Xo6ZA==} + + rmc-cascader@5.0.3: + resolution: {integrity: sha512-PxDhMjWViDdG4SMZqoXtAthGwgDyYnyxxZEE17IDDYsiCHpWtOhoIL8nsI+/hZ212UT/XF2LpqCsOlMoJiYk+w==} + + rmc-date-picker@6.0.10: + resolution: {integrity: sha512-/9+I6lm3EDEl6M7862V6++zFuxwsM0UEq8wSHbotYIPPmyB/65gx1cviblghOv2QfB0O9+U2w3qEJlRP/WsMrA==} + + rmc-dialog@1.1.1: + resolution: {integrity: sha512-28aJqtPTX6v13Z/aU1WBy1AFIXkE74PxZXde7JvtEIy9hQDTjH8fqOi822BpzAbXCyNE7jF9iFomy3H2ClsDJA==} + + rmc-drawer@0.4.11: + resolution: {integrity: sha512-YfB9XEJ8iM0MMuLWAK4313uOxSM8NAljC8Cqun1KamXutglYTuRviUuTLNSOzV8HHPp5kNpsVduvPCGLWXvThw==} + engines: {node: '>=4.0.0'} + + rmc-feedback@2.0.0: + resolution: {integrity: sha512-5PWOGOW7VXks/l3JzlOU9NIxRpuaSS8d9zA3UULUCuTKnpwBHNvv1jSJzxgbbCQeYzROWUpgKI4za3X4C/mKmQ==} + + rmc-input-number@1.0.5: + resolution: {integrity: sha512-prPkEtoOVde77GnEnEaBeWjBobMOPgGqU5bd0gxfp1kt1pUN740mMpVAcH7uxpJjVfmw+kuGWtiz4S7CueagSg==} + + rmc-list-view@0.11.5: + resolution: {integrity: sha512-eMOC5394tLNawcdEEhF7boMpQgpjJGDdL5lS+LblAWdBec7Q4EYkUdnrKNbt+O9k5RGM6nSLAGZK5oB4FN85Lg==} + + rmc-notification@1.0.0: + resolution: {integrity: sha512-9sPxjltFvtRLt2v312Hu7OXwk53pHkBYgINRDmnJ3A5NF1qtJeCCcdN0Xr0fzJ6sbQvtGju822tWHdzYA9u7Vw==} + + rmc-nuka-carousel@3.0.1: + resolution: {integrity: sha512-w2EPTERMUUZqcUSKFuejjin7xsMlhrLrtS0A/igTXpFJGq3kemDKcRi7q3pSYDuZBHYBl5iV4UqsLLkjdFtrYA==} + + rmc-picker@5.0.10: + resolution: {integrity: sha512-KZ70+WjcaZHnG5GyCxWCPFWAZ12s6NqyrbW73LeqH0WEqaTMMs0sOrk2f4mQAZ/CGT0XcFN6VZLw7Ozoxfn7LA==} + + rmc-pull-to-refresh@1.0.13: + resolution: {integrity: sha512-iYLsURiR7G/sKmRA6p2kq6ZXicn7Hyeo6VQFljssV1eMW+fzDgihhaz0kv5mza0f88vphGJvjOihT9E6+xGb6Q==} + + rmc-steps@1.0.1: + resolution: {integrity: sha512-8ijtwp4D1CYTtI2yerXJYqCv+GQbiBc9T12nrFngd/vM0y+58CnznGphTAueF6IWf7qbxBwcjTrcFgg7bP2YGA==} + + rmc-tabs@1.2.29: + resolution: {integrity: sha512-wiJS9WSJi9JH9GQO+FqncX+zaHP31qHa/S8nDW9UXUx0qbCX294QcJEnvfB+WmsfUws7rXjs6sOQp5EDiObnHg==} + + rmc-tooltip@1.0.1: + resolution: {integrity: sha512-fSDArf2BlMVrHExmBiqb2TkCRJHshvXFJQ/7tMraLellwaJLNiwrxtWpW329k3S+zTtoVG8UxFS1TjBGEsMzRg==} + + rmc-trigger@1.0.12: + resolution: {integrity: sha512-AccQniX7PX7Pm8hBhHEsnf3JU6CA61Xc7fAt2WbO+oXrGaI/jqN8C3COhhOXG54S5iTOjLS26j858zshwAxR9A==} + + robust-predicates@3.0.2: + resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} + + rollup-plugin-terser@7.0.2: + resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==} + deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser + peerDependencies: + rollup: ^2.0.0 + + rollup@0.25.8: + resolution: {integrity: sha512-a2S4Bh3bgrdO4BhKr2E4nZkjTvrJ2m2bWjMTzVYtoqSCn0HnuxosXnaJUHrMEziOWr3CzL9GjilQQKcyCQpJoA==} + hasBin: true + + rollup@2.79.2: + resolution: {integrity: sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==} + engines: {node: '>=10.0.0'} + hasBin: true + + rsvp@4.8.5: + resolution: {integrity: sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==} + engines: {node: 6.* || >= 7.*} + + rtl-css-js@1.16.1: + resolution: {integrity: sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + runscript@1.6.0: + resolution: {integrity: sha512-lI0ybcwtdC5Wz3aiVtMAK6U5jcTDeLseEBSXcz6ABtQeMmQGpj35dmzpmpy2C9Bn0k2wTjTRLZoya0NFt8Mxsg==} + engines: {node: '>=4.2.3'} + + rw@1.3.3: + resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} + + rxjs@6.6.7: + resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} + engines: {npm: '>=2.0.0'} + + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + + safe-array-concat@1.1.3: + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} + engines: {node: '>=0.4'} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + safe-regex@1.1.0: + resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sane@4.1.0: + resolution: {integrity: sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==} + engines: {node: 6.* || 8.* || >= 10.*} + deprecated: some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added + hasBin: true + + sanitize.css@13.0.0: + resolution: {integrity: sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==} + + sass-loader@12.6.0: + resolution: {integrity: sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==} + engines: {node: '>= 12.13.0'} + peerDependencies: + fibers: '>= 3.1.0' + node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + sass: ^1.3.0 + sass-embedded: '*' + webpack: ^5.0.0 + peerDependenciesMeta: + fibers: + optional: true + node-sass: + optional: true + sass: + optional: true + sass-embedded: + optional: true + + sax@1.2.4: + resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} + + saxes@5.0.1: + resolution: {integrity: sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==} + engines: {node: '>=10'} + + scheduler@0.19.1: + resolution: {integrity: sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==} + + schema-utils@1.0.0: + resolution: {integrity: sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==} + engines: {node: '>= 4'} + + schema-utils@2.7.0: + resolution: {integrity: sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==} + engines: {node: '>= 8.9.0'} + + schema-utils@2.7.1: + resolution: {integrity: sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==} + engines: {node: '>= 8.9.0'} + + schema-utils@3.3.0: + resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} + engines: {node: '>= 10.13.0'} + + schema-utils@4.3.2: + resolution: {integrity: sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==} + engines: {node: '>= 10.13.0'} + + screenfull@5.2.0: + resolution: {integrity: sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==} + engines: {node: '>=0.10.0'} + + screenfull@6.0.2: + resolution: {integrity: sha512-AQdy8s4WhNvUZ6P8F6PB21tSPIYKniic+Ogx0AacBMjKP1GUHN2E9URxQHtCusiwxudnCKkdy4GrHXPPJSkCCw==} + engines: {node: ^14.13.1 || >=16.0.0} + + script-ext-html-webpack-plugin@2.1.5: + resolution: {integrity: sha512-nMjd5dtsnoB8dS+pVM9ZL4mC9O1uVtTxrDS99OGZsZxFbkZE6pw0HCMued/cncDrKivIShO9vwoyOTvsGqQHEQ==} + engines: {node: '>=6.11.5'} + peerDependencies: + html-webpack-plugin: ^3.0.0 || ^4.0.0 + webpack: ^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 + + scroll-into-view-if-needed@2.2.31: + resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==} + + scroll-into-view-if-needed@3.1.0: + resolution: {integrity: sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==} + + scroll-into-view@1.16.2: + resolution: {integrity: sha512-vyTE0i27o6eldt9xinjHec41Dw05y+faoI+s2zNKJAVOdbA5M2XZrYq/obJ8E+QDQulJ2gDjgui9w9m9RZSRng==} + + seamless-immutable@7.1.4: + resolution: {integrity: sha512-XiUO1QP4ki4E2PHegiGAlu6r82o5A+6tRh7IkGGTVg/h+UoeX4nFBeCGPOhb4CYjvkqsfm/TUtvOMYC1xmV30A==} + + select-hose@2.0.0: + resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} + + selfsigned@2.4.1: + resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} + engines: {node: '>=10'} + + semver-compare@1.0.0: + resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + engines: {node: '>=10'} + hasBin: true + + send@0.19.0: + resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} + engines: {node: '>= 0.8.0'} + + serialize-javascript@4.0.0: + resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==} + + serialize-javascript@6.0.2: + resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + + serve-index@1.9.1: + resolution: {integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==} + engines: {node: '>= 0.8.0'} + + serve-static@1.16.2: + resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} + engines: {node: '>= 0.8.0'} + + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + set-harmonic-interval@1.0.1: + resolution: {integrity: sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==} + engines: {node: '>=6.9'} + + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + + set-value@2.0.1: + resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} + engines: {node: '>=0.10.0'} + + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + + setprototypeof@1.1.0: + resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + sha.js@2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + + shallow-equal@1.2.1: + resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==} + + shallowequal@1.1.0: + resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} + + shebang-command@1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@1.0.0: + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} + engines: {node: '>=0.10.0'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shell-quote@1.8.2: + resolution: {integrity: sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==} + engines: {node: '>= 0.4'} + + shellwords@0.1.1: + resolution: {integrity: sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==} + + should-equal@2.0.0: + resolution: {integrity: sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==} + + should-format@3.0.3: + resolution: {integrity: sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==} + + should-type-adaptors@1.1.0: + resolution: {integrity: sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==} + + should-type@1.4.0: + resolution: {integrity: sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==} + + should-util@1.0.1: + resolution: {integrity: sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==} + + should@13.2.3: + resolution: {integrity: sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + size-sensor@1.0.2: + resolution: {integrity: sha512-2NCmWxY7A9pYKGXNBfteo4hy14gWu47rg5692peVMst6lQLPKrVjhY+UTEsPI5ceFRJSl3gVgMYaUi/hKuaiKw==} + + slash@1.0.0: + resolution: {integrity: sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==} + engines: {node: '>=0.10.0'} + + slash@2.0.0: + resolution: {integrity: sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==} + engines: {node: '>=6'} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slash@4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} + + slice-ansi@3.0.0: + resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} + engines: {node: '>=8'} + + slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + + snapdragon-node@2.1.1: + resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} + engines: {node: '>=0.10.0'} + + snapdragon-util@3.0.1: + resolution: {integrity: sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==} + engines: {node: '>=0.10.0'} + + snapdragon@0.8.2: + resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} + engines: {node: '>=0.10.0'} + + sockjs@0.3.24: + resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} + + sort-asc@0.2.0: + resolution: {integrity: sha512-umMGhjPeHAI6YjABoSTrFp2zaBtXBej1a0yKkuMUyjjqu6FJsTF+JYwCswWDg+zJfk/5npWUUbd33HH/WLzpaA==} + engines: {node: '>=0.10.0'} + + sort-desc@0.2.0: + resolution: {integrity: sha512-NqZqyvL4VPW+RAxxXnB8gvE1kyikh8+pR+T+CXLksVRN9eiQqkQlPwqWYU0mF9Jm7UnctShlxLyAt1CaBOTL1w==} + engines: {node: '>=0.10.0'} + + sort-keys@1.1.2: + resolution: {integrity: sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==} + engines: {node: '>=0.10.0'} + + sort-object@3.0.3: + resolution: {integrity: sha512-nK7WOY8jik6zaG9CRwZTaD5O7ETWDLZYMM12pqY8htll+7dYeqGfEUPcUBHOpSJg2vJOrvFIY2Dl5cX2ih1hAQ==} + engines: {node: '>=0.10.0'} + + source-list-map@2.0.1: + resolution: {integrity: sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map-loader@3.0.2: + resolution: {integrity: sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + + source-map-resolve@0.5.3: + resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} + deprecated: See https://github.com/lydell/source-map-resolve#deprecated + + source-map-support@0.3.3: + resolution: {integrity: sha512-9O4+y9n64RewmFoKUZ/5Tx9IHIcXM6Q+RTSw6ehnqybUz4a7iwR3Eaw80uLtqqQ5D0C+5H03D4KKGo9PdP33Gg==} + + source-map-support@0.4.18: + resolution: {integrity: sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map-url@0.4.1: + resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} + deprecated: See https://github.com/lydell/source-map-url#deprecated + + source-map@0.1.32: + resolution: {integrity: sha512-htQyLrrRLkQ87Zfrir4/yN+vAUd6DNjVayEjTSHXu29AYQJw57I4/xEL/M6p6E/woPNJwvZt6rVlzc7gFEJccQ==} + engines: {node: '>=0.8.0'} + + source-map@0.5.6: + resolution: {integrity: sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==} + engines: {node: '>=0.10.0'} + + source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + + source-map@0.8.0-beta.0: + resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} + engines: {node: '>= 8'} + + sourcemap-codec@1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead + + sourcemapped-stacktrace@1.1.11: + resolution: {integrity: sha512-O0pcWjJqzQFVsisPlPXuNawJHHg9N9UgpJ/aDmvi9+vnS3x1C0NhwkVFzzZ1VN0Xo+bekyweoqYvBw5ZBKiNnQ==} + + spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.21: + resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==} + + spdy-transport@3.0.0: + resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} + + spdy@4.0.2: + resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} + engines: {node: '>=6.0.0'} + + splaytree@3.1.2: + resolution: {integrity: sha512-4OM2BJgC5UzrhVnnJA4BkHKGtjXNzzUfpQjCO8I05xYPsfS/VuQDwjCGGMi8rYQilHEV4j8NBqTFbls/PZEE7A==} + + split-on-first@1.1.0: + resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==} + engines: {node: '>=6'} + + split-on-first@3.0.0: + resolution: {integrity: sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==} + engines: {node: '>=12'} + + split-string@3.1.0: + resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} + engines: {node: '>=0.10.0'} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + sql-formatter@2.3.4: + resolution: {integrity: sha512-CajWtvzYoBJbD5PQeVe3E7AOHAIYvRQEPOKgF9kfKNeY8jtjBiiA6pDzkMuAID8jJMluoPvyKveLigSaA5tKQQ==} + + ssf@0.11.2: + resolution: {integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==} + engines: {node: '>=0.8'} + + stable@0.1.8: + resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==} + deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' + + stack-generator@2.0.10: + resolution: {integrity: sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==} + + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + + stackframe@0.3.1: + resolution: {integrity: sha512-XmoiF4T5nuWEp2x2w92WdGjdHGY/cZa6LIbRsDRQR/Xlk4uW0PAUlH1zJYVffocwKpCdwyuypIp25xsSXEtZHw==} + + stackframe@1.3.4: + resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} + + stacktrace-gps@3.1.2: + resolution: {integrity: sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==} + + stacktrace-js@2.0.2: + resolution: {integrity: sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==} + + static-eval@2.0.2: + resolution: {integrity: sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==} + + static-extend@0.1.2: + resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} + engines: {node: '>=0.10.0'} + + statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + stream-browserify@2.0.2: + resolution: {integrity: sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==} + + stream-http@2.8.3: + resolution: {integrity: sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==} + + strict-uri-encode@1.1.0: + resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==} + engines: {node: '>=0.10.0'} + + strict-uri-encode@2.0.0: + resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} + engines: {node: '>=4'} + + string-argv@0.3.1: + resolution: {integrity: sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==} + engines: {node: '>=0.6.19'} + + string-convert@0.2.1: + resolution: {integrity: sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==} + + string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + + string-length@5.0.1: + resolution: {integrity: sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==} + engines: {node: '>=12.20'} + + string-natural-compare@3.0.1: + resolution: {integrity: sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string.prototype.includes@2.0.1: + resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} + engines: {node: '>= 0.4'} + + string.prototype.matchall@4.0.12: + resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} + engines: {node: '>= 0.4'} + + string.prototype.repeat@1.0.0: + resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} + + string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.9: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + stringify-object@3.3.0: + resolution: {integrity: sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==} + engines: {node: '>=4'} + + strip-ansi@3.0.1: + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} + engines: {node: '>=0.10.0'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + + strip-comments@2.0.1: + resolution: {integrity: sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==} + engines: {node: '>=10'} + + strip-eof@1.0.0: + resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} + engines: {node: '>=0.10.0'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-indent@2.0.0: + resolution: {integrity: sha512-RsSNPLpq6YUL7QYy44RnPVTn/lcVZtb48Uof3X5JLbF4zD/Gs7ZFDv2HWol+leoQN2mT86LAzSshGfkTlSOpsA==} + engines: {node: '>=4'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + style-ext-html-webpack-plugin@4.1.3: + resolution: {integrity: sha512-J3zn7abHfyhlQ7ghOJd2sH0aYiKoKYuIsa5gk5bGqCmq/JAHlDkMd5gz3xKQ4elcSAS0TsPKpwm/7YAxpVJ+ZQ==} + + style-loader@3.3.4: + resolution: {integrity: sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + + stylehacks@5.1.1: + resolution: {integrity: sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + stylis@4.2.0: + resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} + + stylis@4.3.6: + resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} + + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + supercluster@7.1.5: + resolution: {integrity: sha512-EulshI3pGUM66o6ZdH3ReiFcvHpM3vAigyK+vcxdjpJyEbIIrtbmBdY23mGgnI24uXiGFvrGq9Gkum/8U7vJWg==} + + supercluster@8.0.1: + resolution: {integrity: sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==} + + supports-color@2.0.0: + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} + engines: {node: '>=0.8.0'} + + supports-color@3.2.3: + resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==} + engines: {node: '>=0.8.0'} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@6.1.0: + resolution: {integrity: sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==} + engines: {node: '>=6'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-hyperlinks@2.3.0: + resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + svg-parser@2.0.4: + resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} + + svgo@1.3.2: + resolution: {integrity: sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==} + engines: {node: '>=4.0.0'} + deprecated: This SVGO version is no longer supported. Upgrade to v2.x.x. + hasBin: true + + svgo@2.8.0: + resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==} + engines: {node: '>=10.13.0'} + hasBin: true + + swagger-ui-dist@4.19.1: + resolution: {integrity: sha512-n/gFn+R7G/BXWwl5UZLw6F1YgWOlf3zkwGlsPhTMhNtAAolBGKg0JS5b2RKt5NI6/hSopVaSrki2wTIMUDDy2w==} + + swagger2openapi@7.0.8: + resolution: {integrity: sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==} + hasBin: true + + swr@2.3.3: + resolution: {integrity: sha512-dshNvs3ExOqtZ6kJBaAsabhPdHyeY4P2cKwRCniDVifBMoG/SVI7tfLWqPXriVspf2Rg4tPzXJTnwaihIeFw2A==} + peerDependencies: + react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + symbol-observable@1.2.0: + resolution: {integrity: sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==} + engines: {node: '>=0.10.0'} + + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + + tailwindcss@3.4.17: + resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==} + engines: {node: '>=14.0.0'} + hasBin: true + + tapable@1.1.3: + resolution: {integrity: sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==} + engines: {node: '>=6'} + + tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + + tape@4.17.0: + resolution: {integrity: sha512-KCuXjYxCZ3ru40dmND+oCLsXyuA8hoseu2SS404Px5ouyS0A99v8X/mdiLqsR5MTAyamMBN7PRwt2Dv3+xGIxw==} + hasBin: true + + temp-dir@2.0.0: + resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} + engines: {node: '>=8'} + + tempy@0.6.0: + resolution: {integrity: sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==} + engines: {node: '>=10'} + + terminal-link@2.1.1: + resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} + engines: {node: '>=8'} + + terser-webpack-plugin@5.3.14: + resolution: {integrity: sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true + + terser@4.8.1: + resolution: {integrity: sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==} + engines: {node: '>=6.0.0'} + hasBin: true + + terser@5.14.2: + resolution: {integrity: sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==} + engines: {node: '>=10'} + hasBin: true + + terser@5.39.0: + resolution: {integrity: sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==} + engines: {node: '>=10'} + hasBin: true + + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + throat@5.0.0: + resolution: {integrity: sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==} + + throat@6.0.2: + resolution: {integrity: sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==} + + throttle-debounce@3.0.1: + resolution: {integrity: sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==} + engines: {node: '>=10'} + + throttle-debounce@5.0.2: + resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==} + engines: {node: '>=12.22'} + + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + + thunky@1.1.0: + resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} + + timers-browserify@2.0.12: + resolution: {integrity: sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==} + engines: {node: '>=0.6.0'} + + timers-ext@0.1.8: + resolution: {integrity: sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==} + engines: {node: '>=0.12'} + + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + + tiny-pinyin@1.3.2: + resolution: {integrity: sha512-uHNGu4evFt/8eNLldazeAM1M8JrMc1jshhJJfVRARTN3yT8HEEibofeQ7QETWQ5ISBjd6fKtTVBCC/+mGS6FpA==} + + tiny-warning@1.0.3: + resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + + tinycolor2@1.6.0: + resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} + + tinyqueue@2.0.3: + resolution: {integrity: sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==} + + tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + + to-arraybuffer@1.0.1: + resolution: {integrity: sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==} + + to-fast-properties@1.0.3: + resolution: {integrity: sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==} + engines: {node: '>=0.10.0'} + + to-object-path@0.3.0: + resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} + engines: {node: '>=0.10.0'} + + to-regex-range@2.1.1: + resolution: {integrity: sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==} + engines: {node: '>=0.10.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + to-regex@3.0.2: + resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} + engines: {node: '>=0.10.0'} + + toggle-selection@1.0.6: + resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + topojson-client@3.1.0: + resolution: {integrity: sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==} + hasBin: true + + toposort@2.0.2: + resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==} + + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + engines: {node: '>=6'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + tr46@1.0.1: + resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + + tr46@2.1.0: + resolution: {integrity: sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==} + engines: {node: '>=8'} + + trim-right@1.0.1: + resolution: {integrity: sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw==} + engines: {node: '>=0.10.0'} + + tryer@1.0.1: + resolution: {integrity: sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==} + + ts-easing@0.2.0: + resolution: {integrity: sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==} + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + + tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsutils@3.21.0: + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + + tty-browserify@0.0.0: + resolution: {integrity: sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==} + + tween-functions@1.2.0: + resolution: {integrity: sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==} + + type-check@0.3.2: + resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} + engines: {node: '>= 0.8.0'} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + type-fest@0.16.0: + resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==} + engines: {node: '>=10'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + + type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + type@2.7.3: + resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==} + + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + engines: {node: '>= 0.4'} + + typedarray-to-buffer@3.1.5: + resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} + + typescript@4.9.5: + resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} + engines: {node: '>=4.2.0'} + hasBin: true + + typewise-core@1.2.0: + resolution: {integrity: sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg==} + + typewise@1.0.3: + resolution: {integrity: sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ==} + + ua-parser-js@0.7.40: + resolution: {integrity: sha512-us1E3K+3jJppDBa3Tl0L3MOJiGhe1C6P0+nIvQAFYbxlMAx0h81eOwLmU57xgqToduDDPx3y5QsdjPfDu+FgOQ==} + hasBin: true + + ua-parser-js@1.0.40: + resolution: {integrity: sha512-z6PJ8Lml+v3ichVojCiB8toQJBuwR42ySM4ezjXIqXK3M0HczmKQ3LF4rhU55PfD99KEEXQG6yb7iOMyvYuHew==} + hasBin: true + + uglify-js@2.8.29: + resolution: {integrity: sha512-qLq/4y2pjcU3vhlhseXGGJ7VbFO4pBANu0kwl8VCa9KEI0V8VfZIx2Fy3w01iSTA/pGwKZSmu/+I4etLNDdt5w==} + engines: {node: '>=0.8.0'} + hasBin: true + + uglify-to-browserify@1.0.2: + resolution: {integrity: sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==} + + umi-request@1.4.0: + resolution: {integrity: sha512-OknwtQZddZHi0Ggi+Vr/olJ7HNMx4AzlywyK0W3NZBT7B0stjeZ9lcztA85dBgdAj3KVk8uPJPZSnGaDjELhrA==} + + umi@3.5.43: + resolution: {integrity: sha512-WWusH/o3MTGIJ+S6MiUquz5OwOAQKVdgGHD0CwYBBXcUmwodeZ1mpQSfj8u7VO/OLgVfCmBw8ENsdaWEK6OMtw==} + hasBin: true + + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} + + underscore@1.12.1: + resolution: {integrity: sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==} + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} + engines: {node: '>=4'} + + unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + + unicode-match-property-value-ecmascript@2.2.0: + resolution: {integrity: sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==} + engines: {node: '>=4'} + + unicode-property-aliases-ecmascript@2.1.0: + resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} + engines: {node: '>=4'} + + union-value@1.0.1: + resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} + engines: {node: '>=0.10.0'} + + uniq@1.0.1: + resolution: {integrity: sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==} + + unique-string@2.0.0: + resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} + engines: {node: '>=8'} + + universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + unquote@1.1.1: + resolution: {integrity: sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==} + + unset-value@1.0.0: + resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==} + engines: {node: '>=0.10.0'} + + upath@1.2.0: + resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} + engines: {node: '>=4'} + + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + urix@0.1.0: + resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==} + deprecated: Please see https://github.com/lydell/urix#deprecated + + url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + + url@0.11.4: + resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==} + engines: {node: '>= 0.4'} + + use-composed-ref@1.4.0: + resolution: {integrity: sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + use-deep-compare-effect@1.8.1: + resolution: {integrity: sha512-kbeNVZ9Zkc0RFGpfMN3MNfaKNvcLNyxOAAd9O4CBZ+kCBXXscn9s/4I+8ytUER4RDpEYs5+O6Rs4PqiZ+rHr5Q==} + engines: {node: '>=10', npm: '>=6'} + peerDependencies: + react: '>=16.13' + + use-isomorphic-layout-effect@1.2.0: + resolution: {integrity: sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w==} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + use-latest@1.3.0: + resolution: {integrity: sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + use-memo-one@1.1.3: + resolution: {integrity: sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + + use-merge-value@1.2.0: + resolution: {integrity: sha512-DXgG0kkgJN45TcyoXL49vJnn55LehnrmoHc7MbKi+QDBvr8dsesqws8UlyIWGHMR+JXgxc1nvY+jDGMlycsUcw==} + peerDependencies: + react: '>= 16.x' + + use-resize-observer@9.1.0: + resolution: {integrity: sha512-R25VqO9Wb3asSD4eqtcxk8sJalvIOYBqS8MNZlpDSQ4l4xMQxC/J7Id9HoTqPq8FwULIn0PVW+OAqF2dyYbjow==} + peerDependencies: + react: 16.8.0 - 18 + react-dom: 16.8.0 - 18 + + use-subscription@1.5.1: + resolution: {integrity: sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 + + use-sync-external-store@1.5.0: + resolution: {integrity: sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + use@3.1.1: + resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} + engines: {node: '>=0.10.0'} + + user-home@1.1.1: + resolution: {integrity: sha512-aggiKfEEubv3UwRNqTzLInZpAOmKzwdHqEBmW/hBA/mt99eg+b4VrX6i+IRLxU8+WJYfa33rGwRseg4eElUgsQ==} + engines: {node: '>=0.10.0'} + hasBin: true + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + util.promisify@1.0.0: + resolution: {integrity: sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==} + + util.promisify@1.0.1: + resolution: {integrity: sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==} + + util@0.10.4: + resolution: {integrity: sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==} + + util@0.11.1: + resolution: {integrity: sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==} + + utila@0.4.0: + resolution: {integrity: sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==} + + utility-types@3.11.0: + resolution: {integrity: sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==} + engines: {node: '>= 4'} + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + v8-compile-cache@2.3.0: + resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} + + v8-to-istanbul@7.1.2: + resolution: {integrity: sha512-TxNb7YEUwkLXCQYeudi6lgQ/SZrzNO4kMdlqVxaZPUIUjCv6iSSypUQX70kNBSERpQ8fk48+d61FXk+tgqcWow==} + engines: {node: '>=10.10.0'} + + v8-to-istanbul@8.1.1: + resolution: {integrity: sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==} + engines: {node: '>=10.12.0'} + + v8flags@2.1.1: + resolution: {integrity: sha512-SKfhk/LlaXzvtowJabLZwD4K6SGRYeoxA7KJeISlUMAB/NT4CBkZjMq3WceX2Ckm4llwqYVo8TICgsDYCBU2tA==} + engines: {node: '>= 0.10.0'} + + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + + validator@13.15.0: + resolution: {integrity: sha512-36B2ryl4+oL5QxZ3AzD0t5SsMNGvTtQHpjgFO5tbNxfXbMFkY822ktCDe1MnlqV3301QQI9SLHDNJokDI+Z9pA==} + engines: {node: '>= 0.10'} + + value-equal@1.0.1: + resolution: {integrity: sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + viewport-mercator-project@6.2.3: + resolution: {integrity: sha512-QQb0/qCLlP4DdfbHHSWVYXpghB2wkLIiiZQnoelOB59mXKQSyZVxjreq1S+gaBJFpcGkWEcyVtre0+2y2DTl/Q==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + + vm-browserify@1.1.2: + resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} + + vt-pbf@3.1.3: + resolution: {integrity: sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==} + + w3c-hr-time@1.0.2: + resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} + deprecated: Use your platform's native performance.now() and performance.timeOrigin. + + w3c-xmlserializer@2.0.0: + resolution: {integrity: sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==} + engines: {node: '>=10'} + + walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + + warning@3.0.0: + resolution: {integrity: sha512-jMBt6pUrKn5I+OGgtQ4YZLdhIeJmObddh6CsibPxyQ5yPZm1XExSyzC1LCNX7BzhxWgiHmizBWJTHJIjMjTQYQ==} + + warning@4.0.3: + resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} + + watchpack@2.4.2: + resolution: {integrity: sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==} + engines: {node: '>=10.13.0'} + + wbuf@1.7.3: + resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==} + + web-worker-helper@0.0.3: + resolution: {integrity: sha512-/TllNPjGenDwjE67M16TD9ALwuY847/zIoH7r+e5rSeG4kEa3HiMTAsUDj80yzIzhtshkv215KfsnQ/RXR3nVA==} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + webidl-conversions@4.0.2: + resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + + webidl-conversions@5.0.0: + resolution: {integrity: sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==} + engines: {node: '>=8'} + + webidl-conversions@6.1.0: + resolution: {integrity: sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==} + engines: {node: '>=10.4'} + + webpack-chain@6.5.1: + resolution: {integrity: sha512-7doO/SRtLu8q5WM0s7vPKPWX580qhi0/yBHkOxNkv50f6qB76Zy9o2wRTrrPULqYTvQlVHuvbA8v+G5ayuUDsA==} + engines: {node: '>=8'} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + + webpack-dev-middleware@5.3.4: + resolution: {integrity: sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + + webpack-dev-server@4.15.2: + resolution: {integrity: sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==} + engines: {node: '>= 12.13.0'} + hasBin: true + peerDependencies: + webpack: ^4.37.0 || ^5.0.0 + webpack-cli: '*' + peerDependenciesMeta: + webpack: + optional: true + webpack-cli: + optional: true + + webpack-manifest-plugin@4.1.1: + resolution: {integrity: sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==} + engines: {node: '>=12.22.0'} + peerDependencies: + webpack: ^4.44.2 || ^5.47.0 + + webpack-sources@1.4.3: + resolution: {integrity: sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==} + + webpack-sources@2.3.1: + resolution: {integrity: sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==} + engines: {node: '>=10.13.0'} + + webpack-sources@3.2.3: + resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} + engines: {node: '>=10.13.0'} + + webpack@5.99.7: + resolution: {integrity: sha512-CNqKBRMQjwcmKR0idID5va1qlhrqVUKpovi+Ec79ksW8ux7iS1+A6VqzfZXgVYCFRKl7XL5ap3ZoMpwBJxcg0w==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + + websocket-driver@0.7.4: + resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} + engines: {node: '>=0.8.0'} + + websocket-extensions@0.1.4: + resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} + engines: {node: '>=0.8.0'} + + whatwg-encoding@1.0.5: + resolution: {integrity: sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==} + + whatwg-fetch@3.6.20: + resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} + + whatwg-mimetype@2.3.0: + resolution: {integrity: sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + whatwg-url@7.1.0: + resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} + + whatwg-url@8.7.0: + resolution: {integrity: sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==} + engines: {node: '>=10'} + + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + + which-typed-array@1.1.19: + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} + engines: {node: '>= 0.4'} + + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + window-size@0.1.0: + resolution: {integrity: sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg==} + engines: {node: '>= 0.8.0'} + + wmf@1.0.2: + resolution: {integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==} + engines: {node: '>=0.8'} + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + word@0.3.0: + resolution: {integrity: sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==} + engines: {node: '>=0.8'} + + wordwrap@0.0.2: + resolution: {integrity: sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q==} + engines: {node: '>=0.4.0'} + + workbox-background-sync@6.6.0: + resolution: {integrity: sha512-jkf4ZdgOJxC9u2vztxLuPT/UjlH7m/nWRQ/MgGL0v8BJHoZdVGJd18Kck+a0e55wGXdqyHO+4IQTk0685g4MUw==} + + workbox-broadcast-update@6.6.0: + resolution: {integrity: sha512-nm+v6QmrIFaB/yokJmQ/93qIJ7n72NICxIwQwe5xsZiV2aI93MGGyEyzOzDPVz5THEr5rC3FJSsO3346cId64Q==} + + workbox-build@6.6.0: + resolution: {integrity: sha512-Tjf+gBwOTuGyZwMz2Nk/B13Fuyeo0Q84W++bebbVsfr9iLkDSo6j6PST8tET9HYA58mlRXwlMGpyWO8ETJiXdQ==} + engines: {node: '>=10.0.0'} + + workbox-cacheable-response@6.6.0: + resolution: {integrity: sha512-JfhJUSQDwsF1Xv3EV1vWzSsCOZn4mQ38bWEBR3LdvOxSPgB65gAM6cS2CX8rkkKHRgiLrN7Wxoyu+TuH67kHrw==} + deprecated: workbox-background-sync@6.6.0 + + workbox-core@6.6.0: + resolution: {integrity: sha512-GDtFRF7Yg3DD859PMbPAYPeJyg5gJYXuBQAC+wyrWuuXgpfoOrIQIvFRZnQ7+czTIQjIr1DhLEGFzZanAT/3bQ==} + + workbox-expiration@6.6.0: + resolution: {integrity: sha512-baplYXcDHbe8vAo7GYvyAmlS4f6998Jff513L4XvlzAOxcl8F620O91guoJ5EOf5qeXG4cGdNZHkkVAPouFCpw==} + + workbox-google-analytics@6.6.0: + resolution: {integrity: sha512-p4DJa6OldXWd6M9zRl0H6vB9lkrmqYFkRQ2xEiNdBFp9U0LhsGO7hsBscVEyH9H2/3eZZt8c97NB2FD9U2NJ+Q==} + deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained + + workbox-navigation-preload@6.6.0: + resolution: {integrity: sha512-utNEWG+uOfXdaZmvhshrh7KzhDu/1iMHyQOV6Aqup8Mm78D286ugu5k9MFD9SzBT5TcwgwSORVvInaXWbvKz9Q==} + + workbox-precaching@6.6.0: + resolution: {integrity: sha512-eYu/7MqtRZN1IDttl/UQcSZFkHP7dnvr/X3Vn6Iw6OsPMruQHiVjjomDFCNtd8k2RdjLs0xiz9nq+t3YVBcWPw==} + + workbox-range-requests@6.6.0: + resolution: {integrity: sha512-V3aICz5fLGq5DpSYEU8LxeXvsT//mRWzKrfBOIxzIdQnV/Wj7R+LyJVTczi4CQ4NwKhAaBVaSujI1cEjXW+hTw==} + + workbox-recipes@6.6.0: + resolution: {integrity: sha512-TFi3kTgYw73t5tg73yPVqQC8QQjxJSeqjXRO4ouE/CeypmP2O/xqmB/ZFBBQazLTPxILUQ0b8aeh0IuxVn9a6A==} + + workbox-routing@6.6.0: + resolution: {integrity: sha512-x8gdN7VDBiLC03izAZRfU+WKUXJnbqt6PG9Uh0XuPRzJPpZGLKce/FkOX95dWHRpOHWLEq8RXzjW0O+POSkKvw==} + + workbox-strategies@6.6.0: + resolution: {integrity: sha512-eC07XGuINAKUWDnZeIPdRdVja4JQtTuc35TZ8SwMb1ztjp7Ddq2CJ4yqLvWzFWGlYI7CG/YGqaETntTxBGdKgQ==} + + workbox-streams@6.6.0: + resolution: {integrity: sha512-rfMJLVvwuED09CnH1RnIep7L9+mj4ufkTyDPVaXPKlhi9+0czCu+SJggWCIFbPpJaAZmp2iyVGLqS3RUmY3fxg==} + + workbox-sw@6.6.0: + resolution: {integrity: sha512-R2IkwDokbtHUE4Kus8pKO5+VkPHD2oqTgl+XJwh4zbF1HyjAbgNmK/FneZHVU7p03XUt9ICfuGDYISWG9qV/CQ==} + + workbox-webpack-plugin@6.6.0: + resolution: {integrity: sha512-xNZIZHalboZU66Wa7x1YkjIqEy1gTR+zPM+kjrYJzqN7iurYZBctBLISyScjhkJKYuRrZUP0iqViZTh8rS0+3A==} + engines: {node: '>=10.0.0'} + peerDependencies: + webpack: ^4.4.0 || ^5.9.0 + + workbox-window@6.6.0: + resolution: {integrity: sha512-L4N9+vka17d16geaJXXRjENLFldvkWy7JyGxElRD0JvBxvFEd8LOhr+uXCcar/NzAmIBRv9EZ+M+Qr4mOoBITw==} + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + write-file-atomic@3.0.3: + resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} + + ws@7.5.10: + resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.18.1: + resolution: {integrity: sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xlsx@0.17.5: + resolution: {integrity: sha512-lXNU0TuYsvElzvtI6O7WIVb9Zar1XYw7Xb3VAx2wn8N/n0whBYrCnHMxtFyIiUU1Wjf09WzmLALDfBO5PqTb1g==} + engines: {node: '>=0.8'} + hasBin: true + + xml-name-validator@3.0.0: + resolution: {integrity: sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + + y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@2.1.2: + resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + + yaml@2.7.1: + resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} + engines: {node: '>= 14'} + hasBin: true + + yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + + yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yargs@3.10.0: + resolution: {integrity: sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A==} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yorkie@2.0.0: + resolution: {integrity: sha512-jcKpkthap6x63MB4TxwCyuIGkV0oYP/YRyuQU5UO0Yz/E/ZAu+653/uov+phdmO54n6BcvFRyyt0RRrWdN2mpw==} + engines: {node: '>=4'} + + zscroller@0.4.8: + resolution: {integrity: sha512-G5NiNLKx2+QhhvZi2yV1jjVXY50otktxkseX2hG2N/eixohOUk0AY8ZpbAxNqS9oJS/NxItCsowupy2tsXxAMw==} + +snapshots: + + '@ahooksjs/use-request@2.8.15(react@16.14.0)': + dependencies: + lodash.debounce: 4.0.8 + lodash.throttle: 4.1.1 + react: 16.14.0 + + '@ahooksjs/use-url-state@3.5.1(react-router@5.2.0(react@16.14.0))(react@16.14.0)': + dependencies: + ahooks: 3.8.4(react@16.14.0) + query-string: 6.14.1 + react: 16.14.0 + react-router: 5.2.0(react@16.14.0) + tslib: 2.8.1 + + '@alloc/quick-lru@5.2.0': {} + + '@amap/amap-jsapi-loader@1.0.1': {} + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + + '@ant-design/charts@1.4.3(@ant-design/icons@5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(classnames@2.5.1)(lodash@4.17.21)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(reflect-metadata@0.1.14)': + dependencies: + '@ant-design/flowchart': 1.2.2(@ant-design/icons@5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(classnames@2.5.1)(lodash@4.17.21)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(reflect-metadata@0.1.14) + '@ant-design/graphs': 1.4.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/icons': 5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/maps': 1.0.8(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/plots': 1.2.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + lodash: 4.17.21 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + transitivePeerDependencies: + - classnames + - reflect-metadata + + '@ant-design/colors@4.0.5': + dependencies: + tinycolor2: 1.6.0 + + '@ant-design/colors@6.0.0': + dependencies: + '@ctrl/tinycolor': 3.6.1 + + '@ant-design/colors@7.2.0': + dependencies: + '@ant-design/fast-color': 2.0.6 + + '@ant-design/compatible@1.1.2(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(prop-types@15.8.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/icons': 4.8.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + lodash.camelcase: 4.3.0 + lodash.upperfirst: 4.3.1 + omit.js: 1.0.2 + rc-animate: 2.11.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-editor-mention: 1.1.13(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-form: 2.4.12(prop-types@15.8.1) + rc-util: 4.21.1 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + transitivePeerDependencies: + - prop-types + + '@ant-design/cssinjs-utils@1.1.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/cssinjs': 1.23.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@babel/runtime': 7.27.0 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + '@ant-design/cssinjs@1.23.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@babel/runtime': 7.27.0 + '@emotion/hash': 0.8.0 + '@emotion/unitless': 0.7.5 + classnames: 2.5.1 + csstype: 3.1.3 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + stylis: 4.3.6 + + '@ant-design/fast-color@2.0.6': + dependencies: + '@babel/runtime': 7.27.0 + + '@ant-design/flowchart@1.2.2(@ant-design/icons@5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(classnames@2.5.1)(lodash@4.17.21)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(reflect-metadata@0.1.14)': + dependencies: + '@ant-design/icons': 5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@antv/layout': 0.1.31 + '@antv/x6': 1.35.1 + '@antv/x6-react-components': 1.1.20(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@antv/x6-react-shape': 1.6.6(@antv/x6@1.35.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@antv/xflow': 1.1.52(@ant-design/icons@5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(classnames@2.5.1)(lodash@4.17.21)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(reflect-metadata@0.1.14) + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + lodash: 4.17.21 + react: 16.14.0 + react-color: 2.17.3(react@16.14.0) + react-dom: 16.14.0(react@16.14.0) + react-use: 17.3.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + transitivePeerDependencies: + - classnames + - reflect-metadata + + '@ant-design/graphs@1.4.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@antv/dom-util': 2.0.4 + '@antv/g6': 4.8.25 + '@antv/layout': 0.1.31 + '@antv/util': 2.0.17 + insert-css: 2.0.0 + react: 16.14.0 + react-content-loader: 5.1.4(react@16.14.0) + react-dom: 16.14.0(react@16.14.0) + + '@ant-design/icons-svg@4.4.2': {} + + '@ant-design/icons@4.8.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/colors': 6.0.0 + '@ant-design/icons-svg': 4.4.2 + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + lodash: 4.17.21 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + '@ant-design/icons@5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/colors': 7.2.0 + '@ant-design/icons-svg': 4.4.2 + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + '@ant-design/maps@1.0.8(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@antv/l7': 2.22.5 + '@antv/l7plot': 0.5.11(@antv/l7@2.22.5) + '@antv/util': 2.0.17 + react: 16.14.0 + react-content-loader: 5.1.4(react@16.14.0) + react-dom: 16.14.0(react@16.14.0) + + '@ant-design/moment-webpack-plugin@0.0.3': {} + + '@ant-design/plots@1.2.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@antv/g2plot': 2.4.33 + '@antv/util': 2.0.17 + react: 16.14.0 + react-content-loader: 5.1.4(react@16.14.0) + react-dom: 16.14.0(react@16.14.0) + + '@ant-design/pro-card@2.9.7(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/cssinjs': 1.23.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/icons': 5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-provider': 2.15.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-utils': 2.17.0(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@babel/runtime': 7.27.0 + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + rc-resize-observer: 1.4.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + transitivePeerDependencies: + - react-dom + + '@ant-design/pro-components@2.8.7(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(rc-field-form@2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/pro-card': 2.9.7(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-descriptions': 2.6.7(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(rc-field-form@2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-field': 3.0.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-form': 2.31.7(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(rc-field-form@2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-layout': 7.22.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-list': 2.6.7(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(rc-field-form@2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-provider': 2.15.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-skeleton': 2.2.1(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-table': 3.19.0(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(rc-field-form@2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-utils': 2.17.0(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@babel/runtime': 7.27.0 + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + transitivePeerDependencies: + - rc-field-form + + '@ant-design/pro-descriptions@2.6.7(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(rc-field-form@2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/pro-field': 3.0.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-form': 2.31.7(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(rc-field-form@2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-provider': 2.15.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-skeleton': 2.2.1(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-utils': 2.17.0(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@babel/runtime': 7.27.0 + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-resize-observer: 0.2.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + transitivePeerDependencies: + - rc-field-form + - react-dom + + '@ant-design/pro-field@3.0.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/icons': 5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-provider': 2.15.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-utils': 2.17.0(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@babel/runtime': 7.27.0 + '@chenshuai2144/sketch-color': 1.0.9(react@16.14.0) + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + dayjs: 1.11.13 + lodash: 4.17.21 + lodash-es: 4.17.21 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + swr: 2.3.3(react@16.14.0) + transitivePeerDependencies: + - react-dom + + '@ant-design/pro-form@2.31.7(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(rc-field-form@2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/icons': 5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-field': 3.0.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-provider': 2.15.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-utils': 2.17.0(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@babel/runtime': 7.27.0 + '@chenshuai2144/sketch-color': 1.0.9(react@16.14.0) + '@umijs/use-params': 1.0.9(react@16.14.0) + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + dayjs: 1.11.13 + lodash: 4.17.21 + lodash-es: 4.17.21 + rc-field-form: 2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-resize-observer: 1.4.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + '@ant-design/pro-layout@7.22.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/cssinjs': 1.23.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/icons': 5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-provider': 2.15.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-utils': 2.17.0(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@babel/runtime': 7.27.0 + '@umijs/route-utils': 4.0.1 + '@umijs/use-params': 1.0.9(react@16.14.0) + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + lodash: 4.17.21 + lodash-es: 4.17.21 + path-to-regexp: 8.2.0 + rc-resize-observer: 1.4.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + swr: 2.3.3(react@16.14.0) + warning: 4.0.3 + + '@ant-design/pro-list@2.6.7(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(rc-field-form@2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/cssinjs': 1.23.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/icons': 5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-card': 2.9.7(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-field': 3.0.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-table': 3.19.0(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(rc-field-form@2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-utils': 2.17.0(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@babel/runtime': 7.27.0 + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + dayjs: 1.11.13 + rc-resize-observer: 1.4.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 4.21.1 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + transitivePeerDependencies: + - rc-field-form + + '@ant-design/pro-provider@2.15.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/cssinjs': 1.23.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@babel/runtime': 7.27.0 + '@ctrl/tinycolor': 3.6.1 + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + dayjs: 1.11.13 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + swr: 2.3.3(react@16.14.0) + + '@ant-design/pro-skeleton@2.2.1(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@babel/runtime': 7.27.0 + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + '@ant-design/pro-table@3.19.0(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(rc-field-form@2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/cssinjs': 1.23.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/icons': 5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-card': 2.9.7(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-field': 3.0.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-form': 2.31.7(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(rc-field-form@2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-provider': 2.15.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-utils': 2.17.0(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@babel/runtime': 7.27.0 + '@dnd-kit/core': 6.3.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@dnd-kit/modifiers': 6.0.1(@dnd-kit/core@6.3.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react@16.14.0) + '@dnd-kit/sortable': 7.0.2(@dnd-kit/core@6.3.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react@16.14.0) + '@dnd-kit/utilities': 3.2.2(react@16.14.0) + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + dayjs: 1.11.13 + lodash: 4.17.21 + lodash-es: 4.17.21 + rc-field-form: 2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-resize-observer: 1.4.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + '@ant-design/pro-utils@2.17.0(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/icons': 5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-provider': 2.15.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@babel/runtime': 7.27.0 + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + dayjs: 1.11.13 + lodash: 4.17.21 + lodash-es: 4.17.21 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + safe-stable-stringify: 2.5.0 + swr: 2.3.3(react@16.14.0) + + '@ant-design/react-slick@1.0.2(react@16.14.0)': + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + json2mq: 0.2.0 + react: 16.14.0 + resize-observer-polyfill: 1.5.1 + throttle-debounce: 5.0.2 + + '@ant-design/react-slick@1.1.2(react@16.14.0)': + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + json2mq: 0.2.0 + react: 16.14.0 + resize-observer-polyfill: 1.5.1 + throttle-debounce: 5.0.2 + + '@antv/adjust@0.2.5': + dependencies: + '@antv/util': 2.0.17 + tslib: 1.14.1 + + '@antv/algorithm@0.1.26': + dependencies: + '@antv/util': 2.0.17 + tslib: 2.8.1 + + '@antv/async-hook@2.2.9': + dependencies: + async: 3.2.6 + + '@antv/attr@0.3.5': + dependencies: + '@antv/color-util': 2.0.6 + '@antv/scale': 0.3.18 + '@antv/util': 2.0.17 + tslib: 2.8.1 + + '@antv/color-util@2.0.6': + dependencies: + '@antv/util': 2.0.17 + tslib: 2.8.1 + + '@antv/component@0.8.35': + dependencies: + '@antv/color-util': 2.0.6 + '@antv/dom-util': 2.0.4 + '@antv/g-base': 0.5.16 + '@antv/matrix-util': 3.1.0-beta.3 + '@antv/path-util': 2.0.15 + '@antv/scale': 0.3.18 + '@antv/util': 2.0.17 + fecha: 4.2.3 + tslib: 2.8.1 + + '@antv/coord@0.3.1': + dependencies: + '@antv/matrix-util': 3.1.0-beta.3 + '@antv/util': 2.0.17 + tslib: 2.8.1 + + '@antv/dom-util@2.0.4': + dependencies: + tslib: 2.8.1 + + '@antv/event-emitter@0.1.3': {} + + '@antv/g-base@0.4.7': + dependencies: + '@antv/event-emitter': 0.1.3 + '@antv/g-math': 0.1.9 + '@antv/matrix-util': 3.1.0-beta.3 + '@antv/path-util': 2.0.15 + '@antv/util': 2.0.17 + '@types/d3-timer': 1.0.12 + d3-ease: 1.0.7 + d3-interpolate: 1.4.0 + d3-timer: 1.0.10 + detect-browser: 5.3.0 + + '@antv/g-base@0.5.16': + dependencies: + '@antv/event-emitter': 0.1.3 + '@antv/g-math': 0.1.9 + '@antv/matrix-util': 3.1.0-beta.3 + '@antv/path-util': 2.0.15 + '@antv/util': 2.0.17 + '@types/d3-timer': 2.0.3 + d3-ease: 1.0.7 + d3-interpolate: 3.0.1 + d3-timer: 1.0.10 + detect-browser: 5.3.0 + tslib: 2.8.1 + + '@antv/g-canvas@0.4.15': + dependencies: + '@antv/g-base': 0.4.7 + '@antv/g-math': 0.1.9 + '@antv/path-util': 2.0.15 + '@antv/util': 2.0.17 + gl-matrix: 3.4.3 + + '@antv/g-canvas@0.5.17': + dependencies: + '@antv/g-base': 0.5.16 + '@antv/g-math': 0.1.9 + '@antv/matrix-util': 3.1.0-beta.3 + '@antv/path-util': 2.0.15 + '@antv/util': 2.0.17 + gl-matrix: 3.4.3 + tslib: 2.8.1 + + '@antv/g-device-api@1.6.13': + dependencies: + '@antv/util': 3.3.10 + '@webgpu/types': 0.1.60 + eventemitter3: 5.0.1 + gl-matrix: 3.4.3 + tslib: 2.8.1 + + '@antv/g-math@0.1.9': + dependencies: + '@antv/util': 2.0.17 + gl-matrix: 3.4.3 + + '@antv/g-svg@0.4.7': + dependencies: + '@antv/g-base': 0.4.7 + '@antv/g-math': 0.1.9 + '@antv/util': 2.0.17 + detect-browser: 4.8.0 + + '@antv/g-svg@0.5.7': + dependencies: + '@antv/g-base': 0.5.16 + '@antv/g-math': 0.1.9 + '@antv/util': 2.0.17 + detect-browser: 5.3.0 + tslib: 2.8.1 + + '@antv/g-webgpu-core@0.5.6': + dependencies: + eventemitter3: 4.0.7 + gl-matrix: 3.4.3 + inversify: 5.1.1 + inversify-inject-decorators: 3.1.0 + probe.gl: 3.6.0 + reflect-metadata: 0.1.14 + + '@antv/g-webgpu-core@0.7.2': + dependencies: + eventemitter3: 4.0.7 + gl-matrix: 3.4.3 + lodash: 4.17.21 + probe.gl: 3.6.0 + + '@antv/g-webgpu-engine@0.5.6': + dependencies: + '@antv/g-webgpu-core': 0.5.6 + '@webgpu/glslang': 0.0.15 + '@webgpu/types': 0.0.31 + gl-matrix: 3.4.3 + hammerjs: 2.0.8 + inversify: 5.1.1 + inversify-inject-decorators: 3.1.0 + probe.gl: 3.6.0 + reflect-metadata: 0.1.14 + regl: 1.7.0 + + '@antv/g-webgpu-engine@0.7.2': + dependencies: + '@antv/g-webgpu-core': 0.7.2 + gl-matrix: 3.4.3 + lodash: 4.17.21 + regl: 1.7.0 + + '@antv/g-webgpu@0.5.5': + dependencies: + '@antv/g-webgpu-core': 0.5.6 + '@antv/g-webgpu-engine': 0.5.6 + '@webgpu/types': 0.0.31 + gl-matrix: 3.4.3 + gl-vec2: 1.3.0 + hammerjs: 2.0.8 + inversify: 5.1.1 + inversify-inject-decorators: 3.1.0 + polyline-miter-util: 1.0.1 + polyline-normals: 2.0.2 + probe.gl: 3.6.0 + reflect-metadata: 0.1.14 + + '@antv/g-webgpu@0.7.2': + dependencies: + '@antv/g-webgpu-core': 0.7.2 + '@antv/g-webgpu-engine': 0.7.2 + gl-matrix: 3.4.3 + gl-vec2: 1.3.0 + lodash: 4.17.21 + + '@antv/g2@4.2.11': + dependencies: + '@antv/adjust': 0.2.5 + '@antv/attr': 0.3.5 + '@antv/color-util': 2.0.6 + '@antv/component': 0.8.35 + '@antv/coord': 0.3.1 + '@antv/dom-util': 2.0.4 + '@antv/event-emitter': 0.1.3 + '@antv/g-base': 0.5.16 + '@antv/g-canvas': 0.5.17 + '@antv/g-svg': 0.5.7 + '@antv/matrix-util': 3.1.0-beta.3 + '@antv/path-util': 2.0.15 + '@antv/scale': 0.3.18 + '@antv/util': 2.0.17 + tslib: 2.8.1 + + '@antv/g2plot@2.4.33': + dependencies: + '@antv/color-util': 2.0.6 + '@antv/event-emitter': 0.1.3 + '@antv/g-base': 0.5.16 + '@antv/g2': 4.2.11 + '@antv/matrix-util': 3.1.0-beta.3 + '@antv/path-util': 3.0.1 + '@antv/scale': 0.3.18 + '@antv/util': 2.0.17 + d3-hierarchy: 2.0.0 + d3-regression: 1.3.10 + fmin: 0.0.2 + pdfast: 0.2.0 + size-sensor: 1.0.2 + tslib: 2.8.1 + + '@antv/g6-core@0.8.24': + dependencies: + '@antv/algorithm': 0.1.26 + '@antv/dom-util': 2.0.4 + '@antv/event-emitter': 0.1.3 + '@antv/g-base': 0.5.16 + '@antv/g-math': 0.1.9 + '@antv/matrix-util': 3.1.0-beta.3 + '@antv/path-util': 2.0.15 + '@antv/util': 2.0.17 + ml-matrix: 6.12.1 + tslib: 2.8.1 + + '@antv/g6-element@0.8.25(@antv/g6@4.8.25)': + dependencies: + '@antv/g-base': 0.5.16 + '@antv/g6': 4.8.25 + '@antv/g6-core': 0.8.24 + '@antv/util': 2.0.17 + tslib: 2.8.1 + + '@antv/g6-pc@0.8.25(@antv/g6@4.8.25)': + dependencies: + '@ant-design/colors': 4.0.5 + '@antv/algorithm': 0.1.26 + '@antv/dom-util': 2.0.4 + '@antv/event-emitter': 0.1.3 + '@antv/g-base': 0.5.16 + '@antv/g-canvas': 0.5.17 + '@antv/g-math': 0.1.9 + '@antv/g-svg': 0.5.7 + '@antv/g6-core': 0.8.24 + '@antv/g6-element': 0.8.25(@antv/g6@4.8.25) + '@antv/g6-plugin': 0.8.25(@antv/g6@4.8.25) + '@antv/hierarchy': 0.6.14 + '@antv/layout': 0.3.25(dagre@0.8.5) + '@antv/matrix-util': 3.1.0-beta.3 + '@antv/path-util': 2.0.15 + '@antv/util': 2.0.17 + color: 3.2.1 + d3-force: 2.1.1 + dagre: 0.8.5 + insert-css: 2.0.0 + ml-matrix: 6.12.1 + tslib: 2.8.1 + transitivePeerDependencies: + - '@antv/g6' + + '@antv/g6-plugin@0.8.25(@antv/g6@4.8.25)': + dependencies: + '@antv/dom-util': 2.0.4 + '@antv/g-base': 0.5.16 + '@antv/g-canvas': 0.5.17 + '@antv/g-svg': 0.5.7 + '@antv/g6': 4.8.25 + '@antv/g6-core': 0.8.24 + '@antv/g6-element': 0.8.25(@antv/g6@4.8.25) + '@antv/matrix-util': 3.1.0-beta.3 + '@antv/path-util': 2.0.15 + '@antv/scale': 0.3.18 + '@antv/util': 2.0.17 + insert-css: 2.0.0 + + '@antv/g6@3.4.10': + dependencies: + '@antv/dom-util': 2.0.4 + '@antv/event-emitter': 0.1.3 + '@antv/g-base': 0.4.7 + '@antv/g-canvas': 0.4.15 + '@antv/g-math': 0.1.9 + '@antv/g-svg': 0.4.7 + '@antv/hierarchy': 0.6.14 + '@antv/matrix-util': 2.0.7 + '@antv/path-util': 2.0.15 + '@antv/scale': 0.3.18 + '@antv/util': 2.0.17 + d3-force: 2.1.1 + dagre: 0.8.5 + lodash: 4.17.21 + numericjs: 1.2.6 + + '@antv/g6@4.8.25': + dependencies: + '@antv/g6-pc': 0.8.25(@antv/g6@4.8.25) + + '@antv/gl-matrix@2.7.1': {} + + '@antv/graphlib@1.2.0': {} + + '@antv/hierarchy@0.6.14': {} + + '@antv/l7-component@2.22.5': + dependencies: + '@antv/l7-core': 2.22.5 + '@antv/l7-layers': 2.22.5 + '@antv/l7-utils': 2.22.5 + '@babel/runtime': 7.27.0 + eventemitter3: 4.0.7 + supercluster: 7.1.5 + + '@antv/l7-core@2.22.5': + dependencies: + '@antv/async-hook': 2.2.9 + '@antv/l7-utils': 2.22.5 + '@babel/runtime': 7.27.0 + '@mapbox/tiny-sdf': 1.2.5 + '@turf/helpers': 6.5.0 + ajv: 6.12.6 + element-resize-detector: 1.2.4 + eventemitter3: 4.0.7 + gl-matrix: 3.4.3 + hammerjs: 2.0.8 + viewport-mercator-project: 6.2.3 + + '@antv/l7-layers@2.22.5': + dependencies: + '@antv/async-hook': 2.2.9 + '@antv/l7-core': 2.22.5 + '@antv/l7-maps': 2.22.5 + '@antv/l7-source': 2.22.5 + '@antv/l7-utils': 2.22.5 + '@babel/runtime': 7.27.0 + '@mapbox/martini': 0.2.0 + '@turf/clone': 6.5.0 + '@turf/helpers': 6.5.0 + '@turf/meta': 6.5.0 + '@turf/polygon-to-line': 6.5.0 + '@turf/union': 6.5.0 + d3-array: 2.12.1 + d3-color: 1.4.1 + d3-interpolate: 1.4.0 + d3-scale: 2.2.2 + earcut: 2.2.4 + eventemitter3: 4.0.7 + extrude-polyline: 1.0.6 + gl-matrix: 3.4.3 + gl-vec2: 1.3.0 + polyline-miter-util: 1.0.1 + + '@antv/l7-map@2.22.5': + dependencies: + '@antv/l7-utils': 2.22.5 + '@babel/runtime': 7.27.0 + '@mapbox/point-geometry': 0.1.0 + '@mapbox/unitbezier': 0.0.1 + eventemitter3: 4.0.7 + gl-matrix: 3.4.3 + + '@antv/l7-maps@2.22.5': + dependencies: + '@amap/amap-jsapi-loader': 1.0.1 + '@antv/l7-core': 2.22.5 + '@antv/l7-map': 2.22.5 + '@antv/l7-utils': 2.22.5 + '@babel/runtime': 7.27.0 + eventemitter3: 4.0.7 + gl-matrix: 3.4.3 + mapbox-gl: 1.13.3 + maplibre-gl: 3.6.2 + pmtiles: 2.11.0 + viewport-mercator-project: 6.2.3 + + '@antv/l7-renderer@2.22.5': + dependencies: + '@antv/g-device-api': 1.6.13 + '@antv/l7-core': 2.22.5 + '@antv/l7-utils': 2.22.5 + '@babel/runtime': 7.27.0 + regl: 1.6.1 + + '@antv/l7-scene@2.22.5': + dependencies: + '@antv/l7-component': 2.22.5 + '@antv/l7-core': 2.22.5 + '@antv/l7-layers': 2.22.5 + '@antv/l7-maps': 2.22.5 + '@antv/l7-renderer': 2.22.5 + '@antv/l7-utils': 2.22.5 + '@babel/runtime': 7.27.0 + eventemitter3: 4.0.7 + + '@antv/l7-source@2.22.5': + dependencies: + '@antv/async-hook': 2.2.9 + '@antv/l7-core': 2.22.5 + '@antv/l7-utils': 2.22.5 + '@babel/runtime': 7.27.0 + '@mapbox/geojson-rewind': 0.5.2 + '@mapbox/vector-tile': 1.3.1 + '@turf/helpers': 6.5.0 + '@turf/invariant': 6.5.0 + '@turf/meta': 6.5.0 + d3-dsv: 1.2.0 + d3-hexbin: 0.2.2 + eventemitter3: 4.0.7 + geojson-vt: 3.2.1 + pbf: 3.3.0 + supercluster: 7.1.5 + + '@antv/l7-utils@2.22.5': + dependencies: + '@babel/runtime': 7.27.0 + '@turf/bbox': 6.5.0 + '@turf/bbox-polygon': 6.5.0 + '@turf/helpers': 6.5.0 + d3-color: 1.4.1 + earcut: 2.2.4 + eventemitter3: 4.0.7 + gl-matrix: 3.4.3 + lodash: 4.17.21 + web-worker-helper: 0.0.3 + + '@antv/l7@2.22.5': + dependencies: + '@antv/l7-component': 2.22.5 + '@antv/l7-core': 2.22.5 + '@antv/l7-layers': 2.22.5 + '@antv/l7-maps': 2.22.5 + '@antv/l7-scene': 2.22.5 + '@antv/l7-source': 2.22.5 + '@antv/l7-utils': 2.22.5 + '@babel/runtime': 7.27.0 + + '@antv/l7plot-component@0.0.11': + dependencies: + '@antv/dom-util': 2.0.4 + '@antv/util': 2.0.17 + + '@antv/l7plot@0.5.11(@antv/l7@2.22.5)': + dependencies: + '@antv/event-emitter': 0.1.3 + '@antv/l7': 2.22.5 + '@antv/l7plot-component': 0.0.11 + '@antv/util': 2.0.17 + lodash-es: 4.17.21 + topojson-client: 3.1.0 + + '@antv/layout@0.1.31': + dependencies: + '@antv/g-webgpu': 0.5.5 + '@dagrejs/graphlib': 2.1.4 + d3-force: 2.1.1 + ml-matrix: 6.12.1 + + '@antv/layout@0.3.25(dagre@0.8.5)': + dependencies: + '@antv/g-webgpu': 0.7.2 + '@antv/graphlib': 1.2.0 + '@antv/util': 3.3.10 + d3-force: 2.1.1 + d3-quadtree: 2.0.0 + dagre-compound: 0.0.11(dagre@0.8.5) + ml-matrix: 6.5.0 + transitivePeerDependencies: + - dagre + + '@antv/matrix-util@2.0.7': + dependencies: + '@antv/gl-matrix': 2.7.1 + '@antv/util': 2.0.17 + tslib: 1.14.1 + + '@antv/matrix-util@3.0.4': + dependencies: + '@antv/util': 2.0.17 + gl-matrix: 3.4.3 + tslib: 2.8.1 + + '@antv/matrix-util@3.1.0-beta.3': + dependencies: + '@antv/util': 2.0.17 + gl-matrix: 3.4.3 + tslib: 2.8.1 + + '@antv/path-util@2.0.15': + dependencies: + '@antv/matrix-util': 3.0.4 + '@antv/util': 2.0.17 + tslib: 2.8.1 + + '@antv/path-util@3.0.1': + dependencies: + gl-matrix: 3.4.3 + lodash-es: 4.17.21 + tslib: 2.8.1 + + '@antv/scale@0.3.18': + dependencies: + '@antv/util': 2.0.17 + fecha: 4.2.3 + tslib: 2.8.1 + + '@antv/util@2.0.17': + dependencies: + csstype: 3.1.3 + tslib: 2.8.1 + + '@antv/util@3.3.10': + dependencies: + fast-deep-equal: 3.1.3 + gl-matrix: 3.4.3 + tslib: 2.8.1 + + '@antv/x6-react-components@1.1.20(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + clamp: 1.0.1 + classnames: 2.5.1 + rc-dropdown: 3.6.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 4.21.1 + react: 16.14.0 + react-color: 2.17.1(react@16.14.0) + react-dom: 16.14.0(react@16.14.0) + react-resize-detector: 7.1.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + ua-parser-js: 0.7.40 + + '@antv/x6-react-shape@1.6.6(@antv/x6@1.35.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@antv/x6': 1.35.1 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + '@antv/x6@1.35.1': + dependencies: + csstype: 3.1.3 + jquery: 3.7.1 + jquery-mousewheel: 3.2.2 + lodash-es: 4.17.21 + mousetrap: 1.6.5 + utility-types: 3.11.0 + + '@antv/xflow-core@1.1.52(@ant-design/icons@5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@antv/x6-react-components@1.1.20(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@antv/x6-react-shape@1.6.6(@antv/x6@1.35.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@antv/x6@1.35.1)(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(lodash@4.17.21)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/icons': 5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@antv/x6': 1.35.1 + '@antv/x6-react-components': 1.1.20(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@antv/x6-react-shape': 1.6.6(@antv/x6@1.35.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@antv/xflow-hook': 1.0.52 + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + immer: 9.0.21 + lodash: 4.17.21 + mana-common: 0.3.2 + mana-syringe: 0.2.2 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + reflect-metadata: 0.1.14 + rxjs: 6.6.7 + + '@antv/xflow-extension@1.1.52(@ant-design/icons@5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@antv/x6-react-components@1.1.20(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@antv/x6-react-shape@1.6.6(@antv/x6@1.35.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@antv/x6@1.35.1)(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(classnames@2.5.1)(lodash@4.17.21)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(reflect-metadata@0.1.14)': + dependencies: + '@ant-design/icons': 5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@antv/x6': 1.35.1 + '@antv/x6-react-components': 1.1.20(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@antv/x6-react-shape': 1.6.6(@antv/x6@1.35.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@antv/xflow-core': 1.1.52(@ant-design/icons@5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@antv/x6-react-components@1.1.20(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@antv/x6-react-shape@1.6.6(@antv/x6@1.35.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@antv/x6@1.35.1)(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(lodash@4.17.21)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@antv/xflow-hook': 1.0.52 + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + mana-syringe: 0.2.2 + moment: 2.30.1 + rc-field-form: 1.44.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-color: 2.17.1(react@16.14.0) + react-dom: 16.14.0(react@16.14.0) + reflect-metadata: 0.1.14 + transitivePeerDependencies: + - lodash + + '@antv/xflow-hook@1.0.52': + dependencies: + toposort: 2.0.2 + + '@antv/xflow-hook@1.1.52': + dependencies: + toposort: 2.0.2 + + '@antv/xflow@1.1.52(@ant-design/icons@5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(classnames@2.5.1)(lodash@4.17.21)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(reflect-metadata@0.1.14)': + dependencies: + '@ant-design/icons': 5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@antv/layout': 0.1.31 + '@antv/x6': 1.35.1 + '@antv/x6-react-components': 1.1.20(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@antv/x6-react-shape': 1.6.6(@antv/x6@1.35.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@antv/xflow-core': 1.1.52(@ant-design/icons@5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@antv/x6-react-components@1.1.20(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@antv/x6-react-shape@1.6.6(@antv/x6@1.35.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@antv/x6@1.35.1)(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(lodash@4.17.21)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@antv/xflow-extension': 1.1.52(@ant-design/icons@5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@antv/x6-react-components@1.1.20(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@antv/x6-react-shape@1.6.6(@antv/x6@1.35.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@antv/x6@1.35.1)(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(classnames@2.5.1)(lodash@4.17.21)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(reflect-metadata@0.1.14) + '@antv/xflow-hook': 1.1.52 + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + lodash: 4.17.21 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + transitivePeerDependencies: + - classnames + - reflect-metadata + + '@apideck/better-ajv-errors@0.3.6(ajv@8.17.1)': + dependencies: + ajv: 8.17.1 + json-schema: 0.4.0 + jsonpointer: 5.0.1 + leven: 3.1.0 + + '@babel/code-frame@7.26.2': + dependencies: + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.26.8': {} + + '@babel/core@7.18.6': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.27.0 + '@babel/helper-compilation-targets': 7.27.0 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.18.6) + '@babel/helpers': 7.27.0 + '@babel/parser': 7.27.0 + '@babel/template': 7.27.0 + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 + convert-source-map: 1.9.0 + debug: 4.4.0 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/core@7.26.10': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.27.0 + '@babel/helper-compilation-targets': 7.27.0 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) + '@babel/helpers': 7.27.0 + '@babel/parser': 7.27.0 + '@babel/template': 7.27.0 + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 + convert-source-map: 2.0.0 + debug: 4.4.0 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/eslint-parser@7.27.0(@babel/core@7.26.10)(eslint@9.25.1(jiti@1.21.7))': + dependencies: + '@babel/core': 7.26.10 + '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 + eslint: 9.25.1(jiti@1.21.7) + eslint-visitor-keys: 2.1.0 + semver: 6.3.1 + + '@babel/generator@7.27.0': + dependencies: + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.25.9': + dependencies: + '@babel/types': 7.27.0 + + '@babel/helper-compilation-targets@7.27.0': + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.4 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.27.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-member-expression-to-functions': 7.25.9 + '@babel/helper-optimise-call-expression': 7.25.9 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.10) + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/traverse': 7.27.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-create-regexp-features-plugin@7.27.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-annotate-as-pure': 7.25.9 + regexpu-core: 6.2.0 + semver: 6.3.1 + + '@babel/helper-define-polyfill-provider@0.6.4(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-compilation-targets': 7.27.0 + '@babel/helper-plugin-utils': 7.26.5 + debug: 4.4.0 + lodash.debounce: 4.0.8 + resolve: 1.22.10 + transitivePeerDependencies: + - supports-color + + '@babel/helper-member-expression-to-functions@7.25.9': + dependencies: + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.25.9': + dependencies: + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.26.0(@babel/core@7.18.6)': + dependencies: + '@babel/core': 7.18.6 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.27.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.27.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.25.9': + dependencies: + '@babel/types': 7.27.0 + + '@babel/helper-plugin-utils@7.26.5': {} + + '@babel/helper-remap-async-to-generator@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-wrap-function': 7.25.9 + '@babel/traverse': 7.27.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-replace-supers@7.26.5(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-member-expression-to-functions': 7.25.9 + '@babel/helper-optimise-call-expression': 7.25.9 + '@babel/traverse': 7.27.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.25.9': + dependencies: + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.25.9': {} + + '@babel/helper-validator-identifier@7.25.9': {} + + '@babel/helper-validator-option@7.25.9': {} + + '@babel/helper-wrap-function@7.25.9': + dependencies: + '@babel/template': 7.27.0 + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 + transitivePeerDependencies: + - supports-color + + '@babel/helpers@7.27.0': + dependencies: + '@babel/template': 7.27.0 + '@babel/types': 7.27.0 + + '@babel/parser@7.27.0': + dependencies: + '@babel/types': 7.27.0 + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.27.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.10) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.27.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-decorators@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-syntax-decorators': 7.25.9(@babel/core@7.26.10) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.10) + + '@babel/plugin-proposal-numeric-separator@7.18.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.10) + + '@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.10) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + + '@babel/plugin-proposal-private-property-in-object@7.21.11(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.10) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.18.6)': + dependencies: + '@babel/core': 7.18.6 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.18.6)': + dependencies: + '@babel/core': 7.18.6 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.18.6)': + dependencies: + '@babel/core': 7.18.6 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.18.6)': + dependencies: + '@babel/core': 7.18.6 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-decorators@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-flow@7.26.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-assertions@7.26.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.18.6)': + dependencies: + '@babel/core': 7.18.6 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.18.6)': + dependencies: + '@babel/core': 7.18.6 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.18.6)': + dependencies: + '@babel/core': 7.18.6 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.18.6)': + dependencies: + '@babel/core': 7.18.6 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.18.6)': + dependencies: + '@babel/core': 7.18.6 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.18.6)': + dependencies: + '@babel/core': 7.18.6 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.18.6)': + dependencies: + '@babel/core': 7.18.6 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.18.6)': + dependencies: + '@babel/core': 7.18.6 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.18.6)': + dependencies: + '@babel/core': 7.18.6 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.18.6)': + dependencies: + '@babel/core': 7.18.6 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.18.6)': + dependencies: + '@babel/core': 7.18.6 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-arrow-functions@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-async-generator-functions@7.26.8(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.10) + '@babel/traverse': 7.27.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-async-to-generator@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.10) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-block-scoped-functions@7.26.5(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-block-scoping@7.27.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-class-properties@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-class-static-block@7.26.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-classes@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-compilation-targets': 7.27.0 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.10) + '@babel/traverse': 7.27.0 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-computed-properties@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/template': 7.27.0 + + '@babel/plugin-transform-destructuring@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-dotall-regex@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-duplicate-keys@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-dynamic-import@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-exponentiation-operator@7.26.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-export-namespace-from@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-flow-strip-types@7.26.5(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-syntax-flow': 7.26.0(@babel/core@7.26.10) + + '@babel/plugin-transform-for-of@7.26.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-function-name@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-compilation-targets': 7.27.0 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.27.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-json-strings@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-literals@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-logical-assignment-operators@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-member-expression-literals@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-modules-amd@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-commonjs@7.26.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-systemjs@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.27.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-umd@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-named-capturing-groups-regex@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-new-target@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-nullish-coalescing-operator@7.26.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-numeric-separator@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-object-rest-spread@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-compilation-targets': 7.27.0 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.10) + + '@babel/plugin-transform-object-super@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.10) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-optional-catch-binding@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-optional-chaining@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-parameters@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-private-methods@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-private-property-in-object@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-property-literals@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-react-constant-elements@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-react-display-name@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-react-jsx-development@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.10) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.10) + '@babel/types': 7.27.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-react-pure-annotations@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-regenerator@7.27.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + regenerator-transform: 0.15.2 + + '@babel/plugin-transform-regexp-modifiers@7.26.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-reserved-words@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-runtime@7.26.10(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 + babel-plugin-polyfill-corejs2: 0.4.13(@babel/core@7.26.10) + babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.26.10) + babel-plugin-polyfill-regenerator: 0.6.4(@babel/core@7.26.10) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-shorthand-properties@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-spread@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-sticky-regex@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-template-literals@7.26.8(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-typeof-symbol@7.27.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-typescript@7.27.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.10) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-unicode-escapes@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-unicode-property-regex@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-unicode-regex@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-unicode-sets-regex@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/preset-env@7.26.9(@babel/core@7.26.10)': + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/core': 7.26.10 + '@babel/helper-compilation-targets': 7.27.0 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-validator-option': 7.25.9 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.10) + '@babel/plugin-syntax-import-assertions': 7.26.0(@babel/core@7.26.10) + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.10) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.26.10) + '@babel/plugin-transform-arrow-functions': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-async-generator-functions': 7.26.8(@babel/core@7.26.10) + '@babel/plugin-transform-async-to-generator': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-block-scoped-functions': 7.26.5(@babel/core@7.26.10) + '@babel/plugin-transform-block-scoping': 7.27.0(@babel/core@7.26.10) + '@babel/plugin-transform-class-properties': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-class-static-block': 7.26.0(@babel/core@7.26.10) + '@babel/plugin-transform-classes': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-computed-properties': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-destructuring': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-dotall-regex': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-duplicate-keys': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-dynamic-import': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-exponentiation-operator': 7.26.3(@babel/core@7.26.10) + '@babel/plugin-transform-export-namespace-from': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-for-of': 7.26.9(@babel/core@7.26.10) + '@babel/plugin-transform-function-name': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-json-strings': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-literals': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-logical-assignment-operators': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-member-expression-literals': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-modules-amd': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-modules-commonjs': 7.26.3(@babel/core@7.26.10) + '@babel/plugin-transform-modules-systemjs': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-modules-umd': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-new-target': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-nullish-coalescing-operator': 7.26.6(@babel/core@7.26.10) + '@babel/plugin-transform-numeric-separator': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-object-rest-spread': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-object-super': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-optional-catch-binding': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-private-methods': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-private-property-in-object': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-property-literals': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-regenerator': 7.27.0(@babel/core@7.26.10) + '@babel/plugin-transform-regexp-modifiers': 7.26.0(@babel/core@7.26.10) + '@babel/plugin-transform-reserved-words': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-shorthand-properties': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-spread': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-sticky-regex': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-template-literals': 7.26.8(@babel/core@7.26.10) + '@babel/plugin-transform-typeof-symbol': 7.27.0(@babel/core@7.26.10) + '@babel/plugin-transform-unicode-escapes': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-unicode-property-regex': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-unicode-regex': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-unicode-sets-regex': 7.25.9(@babel/core@7.26.10) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.26.10) + babel-plugin-polyfill-corejs2: 0.4.13(@babel/core@7.26.10) + babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.26.10) + babel-plugin-polyfill-regenerator: 0.6.4(@babel/core@7.26.10) + core-js-compat: 3.41.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/types': 7.27.0 + esutils: 2.0.3 + + '@babel/preset-react@7.26.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-validator-option': 7.25.9 + '@babel/plugin-transform-react-display-name': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-react-jsx-development': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-react-pure-annotations': 7.25.9(@babel/core@7.26.10) + transitivePeerDependencies: + - supports-color + + '@babel/preset-typescript@7.27.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-validator-option': 7.25.9 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-modules-commonjs': 7.26.3(@babel/core@7.26.10) + '@babel/plugin-transform-typescript': 7.27.0(@babel/core@7.26.10) + transitivePeerDependencies: + - supports-color + + '@babel/runtime-corejs2@7.27.0': + dependencies: + core-js: 2.6.12 + regenerator-runtime: 0.14.1 + + '@babel/runtime@7.18.6': + dependencies: + regenerator-runtime: 0.13.11 + + '@babel/runtime@7.27.0': + dependencies: + regenerator-runtime: 0.14.1 + + '@babel/template@7.27.0': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 + + '@babel/traverse@7.27.0': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.27.0 + '@babel/parser': 7.27.0 + '@babel/template': 7.27.0 + '@babel/types': 7.27.0 + debug: 4.4.0 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.27.0': + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + + '@bcoe/v8-coverage@0.2.3': {} + + '@bloomberg/record-tuple-polyfill@0.0.3': {} + + '@chenshuai2144/less2cssinjs@1.0.7(typescript@4.9.5)': + dependencies: + '@babel/generator': 7.27.0 + '@babel/parser': 7.27.0 + '@babel/runtime': 7.27.0 + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 + '@types/node': 18.19.87 + commander: 10.0.1 + postcss: 8.5.3 + postcss-less: 6.0.0(postcss@8.5.3) + postcss-strip-inline-comments: 0.1.5 + prettier: 2.8.8 + ts-node: 10.9.2(@types/node@18.19.87)(typescript@4.9.5) + transitivePeerDependencies: + - '@swc/core' + - '@swc/wasm' + - supports-color + - typescript + + '@chenshuai2144/sketch-color@1.0.9(react@16.14.0)': + dependencies: + react: 16.14.0 + reactcss: 1.2.3(react@16.14.0) + tinycolor2: 1.6.0 + + '@cnakazawa/watch@1.0.4': + dependencies: + exec-sh: 0.3.6 + minimist: 1.2.8 + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@csstools/convert-colors@1.4.0': {} + + '@csstools/normalize.css@12.1.1': {} + + '@csstools/postcss-cascade-layers@1.1.1(postcss@8.5.3)': + dependencies: + '@csstools/selector-specificity': 2.2.0(postcss-selector-parser@6.1.2) + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + '@csstools/postcss-color-function@1.1.1(postcss@8.5.3)': + dependencies: + '@csstools/postcss-progressive-custom-properties': 1.3.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-font-format-keywords@1.0.1(postcss@8.5.3)': + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-hwb-function@1.0.2(postcss@8.5.3)': + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-ic-unit@1.0.1(postcss@8.5.3)': + dependencies: + '@csstools/postcss-progressive-custom-properties': 1.3.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-is-pseudo-class@2.0.7(postcss@8.5.3)': + dependencies: + '@csstools/selector-specificity': 2.2.0(postcss-selector-parser@6.1.2) + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + '@csstools/postcss-nested-calc@1.0.0(postcss@8.5.3)': + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-normalize-display-values@1.0.1(postcss@8.5.3)': + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-oklab-function@1.1.1(postcss@8.5.3)': + dependencies: + '@csstools/postcss-progressive-custom-properties': 1.3.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-progressive-custom-properties@1.3.0(postcss@8.5.3)': + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-stepped-value-functions@1.0.1(postcss@8.5.3)': + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-text-decoration-shorthand@1.0.0(postcss@8.5.3)': + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-trigonometric-functions@1.0.2(postcss@8.5.3)': + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-unset-value@1.0.2(postcss@8.5.3)': + dependencies: + postcss: 8.5.3 + + '@csstools/selector-specificity@2.2.0(postcss-selector-parser@6.1.2)': + dependencies: + postcss-selector-parser: 6.1.2 + + '@ctrl/tinycolor@3.6.1': {} + + '@ctrl/tinycolor@4.1.0': {} + + '@dagrejs/graphlib@2.1.4': + dependencies: + lodash: 4.17.21 + + '@dnd-kit/accessibility@3.1.1(react@16.14.0)': + dependencies: + react: 16.14.0 + tslib: 2.8.1 + + '@dnd-kit/core@6.3.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@dnd-kit/accessibility': 3.1.1(react@16.14.0) + '@dnd-kit/utilities': 3.2.2(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + tslib: 2.8.1 + + '@dnd-kit/modifiers@6.0.1(@dnd-kit/core@6.3.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react@16.14.0)': + dependencies: + '@dnd-kit/core': 6.3.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@dnd-kit/utilities': 3.2.2(react@16.14.0) + react: 16.14.0 + tslib: 2.8.1 + + '@dnd-kit/sortable@7.0.2(@dnd-kit/core@6.3.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react@16.14.0)': + dependencies: + '@dnd-kit/core': 6.3.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@dnd-kit/utilities': 3.2.2(react@16.14.0) + react: 16.14.0 + tslib: 2.8.1 + + '@dnd-kit/utilities@3.2.2(react@16.14.0)': + dependencies: + react: 16.14.0 + tslib: 2.8.1 + + '@emotion/babel-plugin@11.13.5': + dependencies: + '@babel/helper-module-imports': 7.25.9 + '@babel/runtime': 7.27.0 + '@emotion/hash': 0.9.2 + '@emotion/memoize': 0.9.0 + '@emotion/serialize': 1.3.3 + babel-plugin-macros: 3.1.0 + convert-source-map: 1.9.0 + escape-string-regexp: 4.0.0 + find-root: 1.1.0 + source-map: 0.5.7 + stylis: 4.2.0 + transitivePeerDependencies: + - supports-color + + '@emotion/cache@11.14.0': + dependencies: + '@emotion/memoize': 0.9.0 + '@emotion/sheet': 1.4.0 + '@emotion/utils': 1.4.2 + '@emotion/weak-memoize': 0.4.0 + stylis: 4.2.0 + + '@emotion/css@11.13.5': + dependencies: + '@emotion/babel-plugin': 11.13.5 + '@emotion/cache': 11.14.0 + '@emotion/serialize': 1.3.3 + '@emotion/sheet': 1.4.0 + '@emotion/utils': 1.4.2 + transitivePeerDependencies: + - supports-color + + '@emotion/hash@0.8.0': {} + + '@emotion/hash@0.9.2': {} + + '@emotion/memoize@0.9.0': {} + + '@emotion/react@11.14.0(@types/react@17.0.52)(react@16.14.0)': + dependencies: + '@babel/runtime': 7.27.0 + '@emotion/babel-plugin': 11.13.5 + '@emotion/cache': 11.14.0 + '@emotion/serialize': 1.3.3 + '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@16.14.0) + '@emotion/utils': 1.4.2 + '@emotion/weak-memoize': 0.4.0 + hoist-non-react-statics: 3.3.2 + react: 16.14.0 + optionalDependencies: + '@types/react': 17.0.52 + transitivePeerDependencies: + - supports-color + + '@emotion/serialize@1.3.3': + dependencies: + '@emotion/hash': 0.9.2 + '@emotion/memoize': 0.9.0 + '@emotion/unitless': 0.10.0 + '@emotion/utils': 1.4.2 + csstype: 3.1.3 + + '@emotion/sheet@1.4.0': {} + + '@emotion/unitless@0.10.0': {} + + '@emotion/unitless@0.7.5': {} + + '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@16.14.0)': + dependencies: + react: 16.14.0 + + '@emotion/utils@1.4.2': {} + + '@emotion/weak-memoize@0.4.0': {} + + '@eslint-community/eslint-utils@4.6.1(eslint@9.25.1(jiti@1.21.7))': + dependencies: + eslint: 9.25.1(jiti@1.21.7) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/config-array@0.20.0': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.0 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.2.1': {} + + '@eslint/core@0.13.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.1': + dependencies: + ajv: 6.12.6 + debug: 4.4.0 + espree: 10.3.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.25.1': {} + + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.2.8': + dependencies: + '@eslint/core': 0.13.0 + levn: 0.4.1 + + '@exodus/schemasafe@1.3.0': {} + + '@formatjs/intl-displaynames@1.2.10': + dependencies: + '@formatjs/intl-utils': 2.3.0 + + '@formatjs/intl-listformat@1.4.8': + dependencies: + '@formatjs/intl-utils': 2.3.0 + + '@formatjs/intl-pluralrules@1.5.9': + dependencies: + '@formatjs/intl-utils': 2.3.0 + + '@formatjs/intl-relativetimeformat@4.5.16': + dependencies: + '@formatjs/intl-utils': 2.3.0 + + '@formatjs/intl-unified-numberformat@3.3.7': + dependencies: + '@formatjs/intl-utils': 2.3.0 + + '@formatjs/intl-utils@2.3.0': {} + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.2': {} + + '@icons/material@0.2.4(react@16.14.0)': + dependencies: + react: 16.14.0 + + '@inline-svg-unique-id/react@1.2.3(react@16.14.0)': + dependencies: + react: 16.14.0 + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@istanbuljs/load-nyc-config@1.1.0': + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + + '@istanbuljs/schema@0.1.3': {} + + '@jest/console@26.6.2': + dependencies: + '@jest/types': 26.6.2 + '@types/node': 22.15.3 + chalk: 4.1.2 + jest-message-util: 26.6.2 + jest-util: 26.6.2 + slash: 3.0.0 + + '@jest/console@27.5.1': + dependencies: + '@jest/types': 27.5.1 + '@types/node': 22.15.3 + chalk: 4.1.2 + jest-message-util: 27.5.1 + jest-util: 27.5.1 + slash: 3.0.0 + + '@jest/console@28.1.3': + dependencies: + '@jest/types': 28.1.3 + '@types/node': 22.15.3 + chalk: 4.1.2 + jest-message-util: 28.1.3 + jest-util: 28.1.3 + slash: 3.0.0 + + '@jest/core@26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5))': + dependencies: + '@jest/console': 26.6.2 + '@jest/reporters': 26.6.2 + '@jest/test-result': 26.6.2 + '@jest/transform': 26.6.2 + '@jest/types': 26.6.2 + '@types/node': 22.15.3 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 26.6.2 + jest-config: 26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + jest-haste-map: 26.6.2 + jest-message-util: 26.6.2 + jest-regex-util: 26.0.0 + jest-resolve: 26.6.2 + jest-resolve-dependencies: 26.6.3 + jest-runner: 26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + jest-runtime: 26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + jest-snapshot: 26.6.2 + jest-util: 26.6.2 + jest-validate: 26.6.2 + jest-watcher: 26.6.2 + micromatch: 4.0.8 + p-each-series: 2.2.0 + rimraf: 3.0.2 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + '@jest/core@27.5.1(node-notifier@8.0.2)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5))': + dependencies: + '@jest/console': 27.5.1 + '@jest/reporters': 27.5.1(node-notifier@8.0.2) + '@jest/test-result': 27.5.1 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.15.3 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.8.1 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 27.5.1 + jest-config: 27.5.1(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + jest-haste-map: 27.5.1 + jest-message-util: 27.5.1 + jest-regex-util: 27.5.1 + jest-resolve: 27.5.1 + jest-resolve-dependencies: 27.5.1 + jest-runner: 27.5.1 + jest-runtime: 27.5.1 + jest-snapshot: 27.5.1 + jest-util: 27.5.1 + jest-validate: 27.5.1 + jest-watcher: 27.5.1 + micromatch: 4.0.8 + rimraf: 3.0.2 + slash: 3.0.0 + strip-ansi: 6.0.1 + optionalDependencies: + node-notifier: 8.0.2 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + '@jest/environment@26.6.2': + dependencies: + '@jest/fake-timers': 26.6.2 + '@jest/types': 26.6.2 + '@types/node': 22.15.3 + jest-mock: 26.6.2 + + '@jest/environment@27.5.1': + dependencies: + '@jest/fake-timers': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.15.3 + jest-mock: 27.5.1 + + '@jest/fake-timers@26.6.2': + dependencies: + '@jest/types': 26.6.2 + '@sinonjs/fake-timers': 6.0.1 + '@types/node': 22.15.3 + jest-message-util: 26.6.2 + jest-mock: 26.6.2 + jest-util: 26.6.2 + + '@jest/fake-timers@27.5.1': + dependencies: + '@jest/types': 27.5.1 + '@sinonjs/fake-timers': 8.1.0 + '@types/node': 22.15.3 + jest-message-util: 27.5.1 + jest-mock: 27.5.1 + jest-util: 27.5.1 + + '@jest/globals@26.6.2': + dependencies: + '@jest/environment': 26.6.2 + '@jest/types': 26.6.2 + expect: 26.6.2 + + '@jest/globals@27.5.1': + dependencies: + '@jest/environment': 27.5.1 + '@jest/types': 27.5.1 + expect: 27.5.1 + + '@jest/reporters@26.6.2': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 26.6.2 + '@jest/test-result': 26.6.2 + '@jest/transform': 26.6.2 + '@jest/types': 26.6.2 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 4.0.3 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.7 + jest-haste-map: 26.6.2 + jest-resolve: 26.6.2 + jest-util: 26.6.2 + jest-worker: 26.6.2 + slash: 3.0.0 + source-map: 0.6.1 + string-length: 4.0.2 + terminal-link: 2.1.1 + v8-to-istanbul: 7.1.2 + optionalDependencies: + node-notifier: 8.0.2 + transitivePeerDependencies: + - supports-color + + '@jest/reporters@27.5.1(node-notifier@8.0.2)': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.15.3 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 5.2.1 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.7 + jest-haste-map: 27.5.1 + jest-resolve: 27.5.1 + jest-util: 27.5.1 + jest-worker: 27.5.1 + slash: 3.0.0 + source-map: 0.6.1 + string-length: 4.0.2 + terminal-link: 2.1.1 + v8-to-istanbul: 8.1.1 + optionalDependencies: + node-notifier: 8.0.2 + transitivePeerDependencies: + - supports-color + + '@jest/schemas@28.1.3': + dependencies: + '@sinclair/typebox': 0.24.51 + + '@jest/source-map@26.6.2': + dependencies: + callsites: 3.1.0 + graceful-fs: 4.2.11 + source-map: 0.6.1 + + '@jest/source-map@27.5.1': + dependencies: + callsites: 3.1.0 + graceful-fs: 4.2.11 + source-map: 0.6.1 + + '@jest/test-result@26.6.2': + dependencies: + '@jest/console': 26.6.2 + '@jest/types': 26.6.2 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 + + '@jest/test-result@27.5.1': + dependencies: + '@jest/console': 27.5.1 + '@jest/types': 27.5.1 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 + + '@jest/test-result@28.1.3': + dependencies: + '@jest/console': 28.1.3 + '@jest/types': 28.1.3 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 + + '@jest/test-sequencer@26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5))': + dependencies: + '@jest/test-result': 26.6.2 + graceful-fs: 4.2.11 + jest-haste-map: 26.6.2 + jest-runner: 26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + jest-runtime: 26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + '@jest/test-sequencer@27.5.1': + dependencies: + '@jest/test-result': 27.5.1 + graceful-fs: 4.2.11 + jest-haste-map: 27.5.1 + jest-runtime: 27.5.1 + transitivePeerDependencies: + - supports-color + + '@jest/transform@26.6.2': + dependencies: + '@babel/core': 7.18.6 + '@jest/types': 26.6.2 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 1.9.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 26.6.2 + jest-regex-util: 26.0.0 + jest-util: 26.6.2 + micromatch: 4.0.8 + pirates: 4.0.7 + slash: 3.0.0 + source-map: 0.6.1 + write-file-atomic: 3.0.3 + transitivePeerDependencies: + - supports-color + + '@jest/transform@27.5.1': + dependencies: + '@babel/core': 7.26.10 + '@jest/types': 27.5.1 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 1.9.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 27.5.1 + jest-regex-util: 27.5.1 + jest-util: 27.5.1 + micromatch: 4.0.8 + pirates: 4.0.7 + slash: 3.0.0 + source-map: 0.6.1 + write-file-atomic: 3.0.3 + transitivePeerDependencies: + - supports-color + + '@jest/types@26.6.2': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.15.3 + '@types/yargs': 15.0.19 + chalk: 4.1.2 + + '@jest/types@27.5.1': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.15.3 + '@types/yargs': 16.0.9 + chalk: 4.1.2 + + '@jest/types@28.1.3': + dependencies: + '@jest/schemas': 28.1.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.15.3 + '@types/yargs': 17.0.33 + chalk: 4.1.2 + + '@jridgewell/gen-mapping@0.3.8': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/source-map@0.3.6': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@juggle/resize-observer@3.4.0': {} + + '@leichtgewicht/ip-codec@2.0.5': {} + + '@ljharb/resumer@0.0.1': + dependencies: + '@ljharb/through': 2.3.14 + + '@ljharb/through@2.3.14': + dependencies: + call-bind: 1.0.8 + + '@mapbox/geojson-rewind@0.5.2': + dependencies: + get-stream: 6.0.1 + minimist: 1.2.8 + + '@mapbox/geojson-types@1.0.2': {} + + '@mapbox/jsonlint-lines-primitives@2.0.2': {} + + '@mapbox/mapbox-gl-supported@1.5.0(mapbox-gl@1.13.3)': + dependencies: + mapbox-gl: 1.13.3 + + '@mapbox/martini@0.2.0': {} + + '@mapbox/point-geometry@0.1.0': {} + + '@mapbox/tiny-sdf@1.2.5': {} + + '@mapbox/tiny-sdf@2.0.6': {} + + '@mapbox/unitbezier@0.0.0': {} + + '@mapbox/unitbezier@0.0.1': {} + + '@mapbox/vector-tile@1.3.1': + dependencies: + '@mapbox/point-geometry': 0.1.0 + + '@mapbox/whoots-js@3.1.0': {} + + '@maplibre/maplibre-gl-style-spec@19.3.3': + dependencies: + '@mapbox/jsonlint-lines-primitives': 2.0.2 + '@mapbox/unitbezier': 0.0.1 + json-stringify-pretty-compact: 3.0.0 + minimist: 1.2.8 + rw: 1.3.3 + sort-object: 3.0.3 + + '@mrmlnc/readdir-enhanced@2.2.1': + dependencies: + call-me-maybe: 1.0.2 + glob-to-regexp: 0.3.0 + + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': + dependencies: + eslint-scope: 5.1.1 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@1.1.3': {} + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 + + '@oceanbase/aliyun-theme@0.1.6': {} + + '@oceanbase/charts@0.4.5(@ant-design/icons@5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(reflect-metadata@0.1.14)': + dependencies: + '@ant-design/charts': 1.4.3(@ant-design/icons@5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(classnames@2.5.1)(lodash@4.17.21)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(reflect-metadata@0.1.14) + '@oceanbase/util': 0.4.2(react@16.14.0) + classnames: 2.5.1 + lodash: 4.17.21 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + tinycolor2: 1.6.0 + use-resize-observer: 9.1.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + transitivePeerDependencies: + - '@ant-design/icons' + - antd + - reflect-metadata + + '@oceanbase/design@0.4.10(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/cssinjs': 1.23.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ctrl/tinycolor': 4.1.0 + '@inline-svg-unique-id/react': 1.2.3(react@16.14.0) + '@oceanbase/aliyun-theme': 0.1.6 + '@oceanbase/icons': 0.4.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@oceanbase/util': 0.4.2(react@16.14.0) + ahooks: 2.10.14(react@16.14.0) + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + lodash: 4.17.21 + lottie-web: 5.12.2 + prop-types: 15.8.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + transitivePeerDependencies: + - date-fns + - luxon + - moment + - supports-color + + '@oceanbase/icons-svg@1.0.10': + dependencies: + '@rgrove/parse-xml': 2.0.4 + chalk: 4.1.2 + cpy: 8.1.2 + globby: 11.1.0 + insert-css: 2.0.0 + lodash.camelcase: 4.3.0 + lodash.template: 4.5.0 + lodash.upperfirst: 4.3.1 + ramda: 0.27.2 + svgo: 1.3.2 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + + '@oceanbase/icons@0.4.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/colors': 7.2.0 + '@ant-design/icons': 5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@oceanbase/icons-svg': 1.0.10 + lodash.camelcase: 4.3.0 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + transitivePeerDependencies: + - supports-color + + '@oceanbase/ui@0.4.13(@types/react@17.0.52)(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(date-fns@2.30.0)(encoding@0.1.13)(rc-field-form@2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/cssinjs': 1.23.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-components': 2.8.7(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(rc-field-form@2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@antv/g6': 3.4.10 + '@oceanbase/design': 0.4.10(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@oceanbase/icons': 0.4.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@oceanbase/util': 0.4.2(react@16.14.0) + ahooks: 2.10.14(react@16.14.0) + classnames: 2.5.1 + dayjs: 1.11.13 + diff: 5.2.0 + highlight.js: 11.11.1 + highlightjs-solidity: 2.0.6 + hoist-non-react-statics: 3.3.2 + lodash: 4.17.21 + moment: 2.30.1 + path-to-regexp: 7.2.0 + randexp: 0.5.3 + rc-picker: 4.11.3(date-fns@2.30.0)(dayjs@1.11.13)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-copy-to-clipboard: 5.1.0(react@16.14.0) + react-dom: 16.14.0(react@16.14.0) + react-json-view: 1.21.3(@types/react@17.0.52)(encoding@0.1.13)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react-split-pane: 0.1.92(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + screenfull: 6.0.2 + transitivePeerDependencies: + - '@types/react' + - antd + - date-fns + - encoding + - luxon + - rc-field-form + - supports-color + + '@oceanbase/util@0.4.2(react@16.14.0)': + dependencies: + ahooks: 2.10.14(react@16.14.0) + filesize: 10.1.6 + is-url: 1.2.4 + lodash: 4.17.21 + moment: 2.30.1 + query-string: 9.1.1 + react: 16.14.0 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pmmmwh/react-refresh-webpack-plugin@0.5.16(@types/webpack@4.41.40)(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.15.2(webpack@5.99.7))(webpack@5.99.7)': + dependencies: + ansi-html: 0.0.9 + core-js-pure: 3.41.0 + error-stack-parser: 2.1.4 + html-entities: 2.6.0 + loader-utils: 2.0.4 + react-refresh: 0.11.0 + schema-utils: 4.3.2 + source-map: 0.7.4 + webpack: 5.99.7 + optionalDependencies: + '@types/webpack': 4.41.40 + type-fest: 2.19.0 + webpack-dev-server: 4.15.2(webpack@5.99.7) + + '@probe.gl/env@3.6.0': + dependencies: + '@babel/runtime': 7.27.0 + + '@probe.gl/log@3.6.0': + dependencies: + '@babel/runtime': 7.27.0 + '@probe.gl/env': 3.6.0 + + '@probe.gl/stats@3.6.0': + dependencies: + '@babel/runtime': 7.27.0 + + '@qixian.cs/path-to-regexp@6.1.0': {} + + '@rc-component/async-validator@5.0.4': + dependencies: + '@babel/runtime': 7.27.0 + + '@rc-component/color-picker@2.0.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@ant-design/fast-color': 2.0.6 + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + '@rc-component/context@1.4.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@babel/runtime': 7.27.0 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + '@rc-component/mini-decimal@1.1.0': + dependencies: + '@babel/runtime': 7.27.0 + + '@rc-component/mutate-observer@1.1.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + '@rc-component/portal@1.1.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + '@rc-component/qrcode@1.0.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + '@rc-component/tour@1.15.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@babel/runtime': 7.27.0 + '@rc-component/portal': 1.1.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@rc-component/trigger': 2.2.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + '@rc-component/trigger@2.2.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@babel/runtime': 7.27.0 + '@rc-component/portal': 1.1.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-resize-observer: 1.4.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + '@rgrove/parse-xml@2.0.4': {} + + '@rollup/plugin-babel@5.3.1(@babel/core@7.26.10)(@types/babel__core@7.20.5)(rollup@2.79.2)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-module-imports': 7.25.9 + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) + rollup: 2.79.2 + optionalDependencies: + '@types/babel__core': 7.20.5 + transitivePeerDependencies: + - supports-color + + '@rollup/plugin-node-resolve@11.2.1(rollup@2.79.2)': + dependencies: + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) + '@types/resolve': 1.17.1 + builtin-modules: 3.3.0 + deepmerge: 4.3.1 + is-module: 1.0.0 + resolve: 1.22.10 + rollup: 2.79.2 + + '@rollup/plugin-replace@2.4.2(rollup@2.79.2)': + dependencies: + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) + magic-string: 0.25.9 + rollup: 2.79.2 + + '@rollup/pluginutils@3.1.0(rollup@2.79.2)': + dependencies: + '@types/estree': 0.0.39 + estree-walker: 1.0.1 + picomatch: 2.3.1 + rollup: 2.79.2 + + '@rtsao/scc@1.1.0': {} + + '@rushstack/eslint-patch@1.11.0': {} + + '@sentry-internal/feedback@7.120.3': + dependencies: + '@sentry/core': 7.120.3 + '@sentry/types': 7.120.3 + '@sentry/utils': 7.120.3 + + '@sentry-internal/replay-canvas@7.120.3': + dependencies: + '@sentry/core': 7.120.3 + '@sentry/replay': 7.120.3 + '@sentry/types': 7.120.3 + '@sentry/utils': 7.120.3 + + '@sentry-internal/tracing@7.120.3': + dependencies: + '@sentry/core': 7.120.3 + '@sentry/types': 7.120.3 + '@sentry/utils': 7.120.3 + + '@sentry/browser@7.120.3': + dependencies: + '@sentry-internal/feedback': 7.120.3 + '@sentry-internal/replay-canvas': 7.120.3 + '@sentry-internal/tracing': 7.120.3 + '@sentry/core': 7.120.3 + '@sentry/integrations': 7.120.3 + '@sentry/replay': 7.120.3 + '@sentry/types': 7.120.3 + '@sentry/utils': 7.120.3 + + '@sentry/core@7.120.3': + dependencies: + '@sentry/types': 7.120.3 + '@sentry/utils': 7.120.3 + + '@sentry/integrations@7.120.3': + dependencies: + '@sentry/core': 7.120.3 + '@sentry/types': 7.120.3 + '@sentry/utils': 7.120.3 + localforage: 1.10.0 + + '@sentry/react@7.120.3(react@16.14.0)': + dependencies: + '@sentry/browser': 7.120.3 + '@sentry/core': 7.120.3 + '@sentry/types': 7.120.3 + '@sentry/utils': 7.120.3 + hoist-non-react-statics: 3.3.2 + react: 16.14.0 + + '@sentry/replay@7.120.3': + dependencies: + '@sentry-internal/tracing': 7.120.3 + '@sentry/core': 7.120.3 + '@sentry/types': 7.120.3 + '@sentry/utils': 7.120.3 + + '@sentry/tracing@7.120.3': + dependencies: + '@sentry-internal/tracing': 7.120.3 + + '@sentry/types@7.120.3': {} + + '@sentry/utils@7.120.3': + dependencies: + '@sentry/types': 7.120.3 + + '@sinclair/typebox@0.24.51': {} + + '@sinonjs/commons@1.8.6': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@6.0.1': + dependencies: + '@sinonjs/commons': 1.8.6 + + '@sinonjs/fake-timers@8.1.0': + dependencies: + '@sinonjs/commons': 1.8.6 + + '@surma/rollup-plugin-off-main-thread@2.2.3': + dependencies: + ejs: 3.1.10 + json5: 2.2.3 + magic-string: 0.25.9 + string.prototype.matchall: 4.0.12 + + '@svgr/babel-plugin-add-jsx-attribute@5.4.0': {} + + '@svgr/babel-plugin-remove-jsx-attribute@5.4.0': {} + + '@svgr/babel-plugin-remove-jsx-empty-expression@5.0.1': {} + + '@svgr/babel-plugin-replace-jsx-attribute-value@5.0.1': {} + + '@svgr/babel-plugin-svg-dynamic-title@5.4.0': {} + + '@svgr/babel-plugin-svg-em-dimensions@5.4.0': {} + + '@svgr/babel-plugin-transform-react-native-svg@5.4.0': {} + + '@svgr/babel-plugin-transform-svg-component@5.5.0': {} + + '@svgr/babel-preset@5.5.0': + dependencies: + '@svgr/babel-plugin-add-jsx-attribute': 5.4.0 + '@svgr/babel-plugin-remove-jsx-attribute': 5.4.0 + '@svgr/babel-plugin-remove-jsx-empty-expression': 5.0.1 + '@svgr/babel-plugin-replace-jsx-attribute-value': 5.0.1 + '@svgr/babel-plugin-svg-dynamic-title': 5.4.0 + '@svgr/babel-plugin-svg-em-dimensions': 5.4.0 + '@svgr/babel-plugin-transform-react-native-svg': 5.4.0 + '@svgr/babel-plugin-transform-svg-component': 5.5.0 + + '@svgr/core@5.5.0': + dependencies: + '@svgr/plugin-jsx': 5.5.0 + camelcase: 6.3.0 + cosmiconfig: 7.1.0 + transitivePeerDependencies: + - supports-color + + '@svgr/hast-util-to-babel-ast@5.5.0': + dependencies: + '@babel/types': 7.27.0 + + '@svgr/plugin-jsx@5.5.0': + dependencies: + '@babel/core': 7.26.10 + '@svgr/babel-preset': 5.5.0 + '@svgr/hast-util-to-babel-ast': 5.5.0 + svg-parser: 2.0.4 + transitivePeerDependencies: + - supports-color + + '@svgr/plugin-svgo@5.5.0': + dependencies: + cosmiconfig: 7.1.0 + deepmerge: 4.3.1 + svgo: 1.3.2 + + '@svgr/webpack@5.5.0': + dependencies: + '@babel/core': 7.26.10 + '@babel/plugin-transform-react-constant-elements': 7.25.9(@babel/core@7.26.10) + '@babel/preset-env': 7.26.9(@babel/core@7.26.10) + '@babel/preset-react': 7.26.3(@babel/core@7.26.10) + '@svgr/core': 5.5.0 + '@svgr/plugin-jsx': 5.5.0 + '@svgr/plugin-svgo': 5.5.0 + loader-utils: 2.0.4 + transitivePeerDependencies: + - supports-color + + '@tootallnate/once@1.1.2': {} + + '@trysound/sax@0.2.0': {} + + '@tsconfig/node10@1.0.11': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + + '@turf/bbox-polygon@6.5.0': + dependencies: + '@turf/helpers': 6.5.0 + + '@turf/bbox@6.5.0': + dependencies: + '@turf/helpers': 6.5.0 + '@turf/meta': 6.5.0 + + '@turf/clone@6.5.0': + dependencies: + '@turf/helpers': 6.5.0 + + '@turf/helpers@6.5.0': {} + + '@turf/invariant@6.5.0': + dependencies: + '@turf/helpers': 6.5.0 + + '@turf/meta@6.5.0': + dependencies: + '@turf/helpers': 6.5.0 + + '@turf/polygon-to-line@6.5.0': + dependencies: + '@turf/helpers': 6.5.0 + '@turf/invariant': 6.5.0 + + '@turf/union@6.5.0': + dependencies: + '@turf/helpers': 6.5.0 + '@turf/invariant': 6.5.0 + polygon-clipping: 0.15.7 + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.7 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.27.0 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 + + '@types/babel__traverse@7.20.7': + dependencies: + '@babel/types': 7.27.0 + + '@types/body-parser@1.19.5': + dependencies: + '@types/connect': 3.4.38 + '@types/node': 22.15.3 + + '@types/bonjour@3.5.13': + dependencies: + '@types/node': 22.15.3 + + '@types/connect-history-api-fallback@1.5.4': + dependencies: + '@types/express-serve-static-core': 5.0.6 + '@types/node': 22.15.3 + + '@types/connect@3.4.38': + dependencies: + '@types/node': 22.15.3 + + '@types/crypto-js@4.2.2': {} + + '@types/d3-timer@1.0.12': {} + + '@types/d3-timer@2.0.3': {} + + '@types/eslint-scope@3.7.7': + dependencies: + '@types/eslint': 9.6.1 + '@types/estree': 1.0.7 + + '@types/eslint@8.56.12': + dependencies: + '@types/estree': 1.0.7 + '@types/json-schema': 7.0.15 + + '@types/eslint@9.6.1': + dependencies: + '@types/estree': 1.0.7 + '@types/json-schema': 7.0.15 + + '@types/estree@0.0.39': {} + + '@types/estree@1.0.7': {} + + '@types/express-serve-static-core@4.19.6': + dependencies: + '@types/node': 22.15.3 + '@types/qs': 6.9.18 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + + '@types/express-serve-static-core@5.0.6': + dependencies: + '@types/node': 22.15.3 + '@types/qs': 6.9.18 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + + '@types/express@4.17.21': + dependencies: + '@types/body-parser': 1.19.5 + '@types/express-serve-static-core': 4.19.6 + '@types/qs': 6.9.18 + '@types/serve-static': 1.15.7 + + '@types/geojson@7946.0.16': {} + + '@types/glob@7.2.0': + dependencies: + '@types/minimatch': 5.1.2 + '@types/node': 22.15.3 + + '@types/graceful-fs@4.1.9': + dependencies: + '@types/node': 22.15.3 + + '@types/history@4.7.11': {} + + '@types/history@5.0.0': + dependencies: + history: 5.3.0 + + '@types/hoist-non-react-statics@3.3.6': + dependencies: + '@types/react': 17.0.52 + hoist-non-react-statics: 3.3.2 + + '@types/html-minifier-terser@5.1.2': {} + + '@types/html-minifier-terser@6.1.0': {} + + '@types/http-errors@2.0.4': {} + + '@types/http-proxy@1.17.16': + dependencies: + '@types/node': 22.15.3 + + '@types/invariant@2.2.37': {} + + '@types/isomorphic-fetch@0.0.35': {} + + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/js-cookie@2.2.7': {} + + '@types/json-schema@7.0.15': {} + + '@types/json5@0.0.29': {} + + '@types/lodash@4.17.16': {} + + '@types/mapbox__point-geometry@0.1.4': {} + + '@types/mapbox__vector-tile@1.3.4': + dependencies: + '@types/geojson': 7946.0.16 + '@types/mapbox__point-geometry': 0.1.4 + '@types/pbf': 3.0.5 + + '@types/mime@1.3.5': {} + + '@types/minimatch@5.1.2': {} + + '@types/node-forge@1.3.11': + dependencies: + '@types/node': 22.15.3 + + '@types/node@18.19.87': + dependencies: + undici-types: 5.26.5 + + '@types/node@22.15.3': + dependencies: + undici-types: 6.21.0 + + '@types/normalize-package-data@2.4.4': {} + + '@types/parse-json@4.0.2': {} + + '@types/pbf@3.0.5': {} + + '@types/prettier@2.7.3': {} + + '@types/prop-types@15.7.14': {} + + '@types/q@1.5.8': {} + + '@types/qs@6.9.18': {} + + '@types/range-parser@1.2.7': {} + + '@types/react-dom@16.9.25(@types/react@16.14.63)': + dependencies: + '@types/react': 16.14.63 + + '@types/react-dom@17.0.2': + dependencies: + '@types/react': 17.0.52 + + '@types/react-helmet@6.1.11': + dependencies: + '@types/react': 17.0.52 + + '@types/react-redux@7.1.34': + dependencies: + '@types/hoist-non-react-statics': 3.3.6 + '@types/react': 17.0.52 + hoist-non-react-statics: 3.3.2 + redux: 4.2.1 + + '@types/react-router-config@5.0.2': + dependencies: + '@types/history': 5.0.0 + '@types/react': 17.0.52 + '@types/react-router': 5.1.20 + + '@types/react-router-dom@5.1.7': + dependencies: + '@types/history': 5.0.0 + '@types/react': 17.0.52 + '@types/react-router': 5.1.12 + + '@types/react-router-dom@5.3.3': + dependencies: + '@types/history': 4.7.11 + '@types/react': 17.0.52 + '@types/react-router': 5.1.20 + + '@types/react-router@5.1.12': + dependencies: + '@types/history': 5.0.0 + '@types/react': 17.0.52 + + '@types/react-router@5.1.20': + dependencies: + '@types/history': 4.7.11 + '@types/react': 17.0.52 + + '@types/react@16.14.63': + dependencies: + '@types/prop-types': 15.7.14 + '@types/scheduler': 0.16.8 + csstype: 3.1.3 + + '@types/react@17.0.52': + dependencies: + '@types/prop-types': 15.7.14 + '@types/scheduler': 0.26.0 + csstype: 3.1.3 + + '@types/resolve@1.17.1': + dependencies: + '@types/node': 22.15.3 + + '@types/retry@0.12.0': {} + + '@types/scheduler@0.16.8': {} + + '@types/scheduler@0.26.0': {} + + '@types/scroll-into-view@1.16.4': {} + + '@types/semver@7.7.0': {} + + '@types/send@0.17.4': + dependencies: + '@types/mime': 1.3.5 + '@types/node': 22.15.3 + + '@types/serve-index@1.9.4': + dependencies: + '@types/express': 4.17.21 + + '@types/serve-static@1.15.7': + dependencies: + '@types/http-errors': 2.0.4 + '@types/node': 22.15.3 + '@types/send': 0.17.4 + + '@types/sockjs@0.3.36': + dependencies: + '@types/node': 22.15.3 + + '@types/source-list-map@0.1.6': {} + + '@types/sql-formatter@2.3.0': {} + + '@types/stack-utils@2.0.3': {} + + '@types/supercluster@7.1.3': + dependencies: + '@types/geojson': 7946.0.16 + + '@types/tapable@1.0.12': {} + + '@types/trusted-types@2.0.7': {} + + '@types/uglify-js@3.17.5': + dependencies: + source-map: 0.6.1 + + '@types/validator@12.0.1': {} + + '@types/webpack-sources@3.2.3': + dependencies: + '@types/node': 22.15.3 + '@types/source-list-map': 0.1.6 + source-map: 0.7.4 + + '@types/webpack@4.41.40': + dependencies: + '@types/node': 22.15.3 + '@types/tapable': 1.0.12 + '@types/uglify-js': 3.17.5 + '@types/webpack-sources': 3.2.3 + anymatch: 3.1.3 + source-map: 0.6.1 + + '@types/ws@8.18.1': + dependencies: + '@types/node': 22.15.3 + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@15.0.19': + dependencies: + '@types/yargs-parser': 21.0.3 + + '@types/yargs@16.0.9': + dependencies: + '@types/yargs-parser': 21.0.3 + + '@types/yargs@17.0.33': + dependencies: + '@types/yargs-parser': 21.0.3 + + '@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5))(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5) + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/type-utils': 5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5) + '@typescript-eslint/utils': 5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5) + debug: 4.4.0 + eslint: 9.25.1(jiti@1.21.7) + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare-lite: 1.4.0 + semver: 7.7.1 + tsutils: 3.21.0(typescript@4.9.5) + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/experimental-utils@5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5)': + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5) + eslint: 9.25.1(jiti@1.21.7) + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/parser@5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5)': + dependencies: + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@4.9.5) + debug: 4.4.0 + eslint: 9.25.1(jiti@1.21.7) + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@5.62.0': + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + + '@typescript-eslint/type-utils@5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5)': + dependencies: + '@typescript-eslint/typescript-estree': 5.62.0(typescript@4.9.5) + '@typescript-eslint/utils': 5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5) + debug: 4.4.0 + eslint: 9.25.1(jiti@1.21.7) + tsutils: 3.21.0(typescript@4.9.5) + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@5.62.0': {} + + '@typescript-eslint/typescript-estree@5.62.0(typescript@4.9.5)': + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + debug: 4.4.0 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.7.1 + tsutils: 3.21.0(typescript@4.9.5) + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5)': + dependencies: + '@eslint-community/eslint-utils': 4.6.1(eslint@9.25.1(jiti@1.21.7)) + '@types/json-schema': 7.0.15 + '@types/semver': 7.7.0 + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@4.9.5) + eslint: 9.25.1(jiti@1.21.7) + eslint-scope: 5.1.1 + semver: 7.7.1 + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/visitor-keys@5.62.0': + dependencies: + '@typescript-eslint/types': 5.62.0 + eslint-visitor-keys: 3.4.3 + + '@umijs/ast@3.5.43': + dependencies: + '@umijs/utils': 3.5.43 + + '@umijs/babel-plugin-auto-css-modules@3.5.43': + dependencies: + '@umijs/utils': 3.5.43 + + '@umijs/babel-plugin-import-to-await-require@3.5.43': + dependencies: + '@umijs/utils': 3.5.43 + + '@umijs/babel-plugin-lock-core-js-3@3.5.43': + dependencies: + '@umijs/utils': 3.5.43 + core-js: 3.6.5 + + '@umijs/babel-plugin-no-anonymous-default-export@3.5.43': + dependencies: + '@umijs/utils': 3.5.43 + + '@umijs/babel-preset-umi@3.5.43': + dependencies: + '@babel/runtime': 7.18.6 + '@umijs/babel-plugin-auto-css-modules': 3.5.43 + '@umijs/babel-plugin-import-to-await-require': 3.5.43 + '@umijs/babel-plugin-lock-core-js-3': 3.5.43 + '@umijs/babel-plugin-no-anonymous-default-export': 3.5.43 + '@umijs/deps': 3.5.43 + '@umijs/utils': 3.5.43 + + '@umijs/bundler-utils@3.5.43(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@umijs/babel-preset-umi': 3.5.43 + '@umijs/types': 3.5.43(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0) + '@umijs/utils': 3.5.43 + transitivePeerDependencies: + - react + - react-dom + - react-router + + '@umijs/bundler-webpack@3.5.43(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@umijs/bundler-utils': 3.5.43(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0) + '@umijs/case-sensitive-paths-webpack-plugin': 1.0.1 + '@umijs/deps': 3.5.43 + '@umijs/types': 3.5.43(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0) + '@umijs/utils': 3.5.43 + jest-worker: 26.6.2 + node-libs-browser: 2.2.1 + normalize-url: 1.9.1 + postcss: 7.0.32 + postcss-flexbugs-fixes: 4.2.1 + postcss-loader: 3.0.0 + postcss-preset-env: 6.7.0 + postcss-safe-parser: 4.0.2 + terser: 5.14.2 + webpack-chain: 6.5.1 + transitivePeerDependencies: + - react + - react-dom + - react-router + + '@umijs/case-sensitive-paths-webpack-plugin@1.0.1': {} + + '@umijs/core@3.5.43': + dependencies: + '@umijs/ast': 3.5.43 + '@umijs/babel-preset-umi': 3.5.43 + '@umijs/deps': 3.5.43 + '@umijs/utils': 3.5.43 + + '@umijs/deps@3.5.43': + dependencies: + '@bloomberg/record-tuple-polyfill': 0.0.3 + chokidar: 3.5.1 + clipboardy: 2.3.0 + esbuild: 0.12.15 + jest-worker: 24.9.0 + prettier: 2.2.1 + regenerate: 1.4.2 + regenerate-unicode-properties: 10.0.1 + + '@umijs/openapi@1.13.0(chokidar@3.6.0)(encoding@0.1.13)(typescript@4.9.5)': + dependencies: + chalk: 4.1.2 + cosmiconfig: 9.0.0(typescript@4.9.5) + dayjs: 1.11.13 + glob: 7.2.3 + lodash: 4.17.21 + memoizee: 0.4.17 + mock.js: 0.2.0 + mockjs: 1.1.0 + node-fetch: 2.7.0(encoding@0.1.13) + nunjucks: 3.2.4(chokidar@3.6.0) + openapi3-ts: 2.0.2 + prettier: 2.8.8 + reserved-words: 0.1.2 + rimraf: 3.0.2 + swagger2openapi: 7.0.8(encoding@0.1.13) + tiny-pinyin: 1.3.2 + transitivePeerDependencies: + - chokidar + - encoding + - typescript + + '@umijs/plugin-access@2.4.3(@umijs/plugin-initial-state@2.4.0(umi@3.5.43(react-router@5.2.0(react@16.14.0))))(@umijs/plugin-model@2.6.2(umi@3.5.43(react-router@5.2.0(react@16.14.0))))(umi@3.5.43(react-router@5.2.0(react@16.14.0)))': + dependencies: + '@umijs/plugin-initial-state': 2.4.0(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + '@umijs/plugin-model': 2.6.2(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + umi: 3.5.43(react-router@5.2.0(react@16.14.0)) + + '@umijs/plugin-analytics@0.2.2(umi@3.5.43(react-router@5.2.0(react@16.14.0)))': + dependencies: + umi: 3.5.43(react-router@5.2.0(react@16.14.0)) + + '@umijs/plugin-antd@0.13.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(umi@3.5.43(react-router@5.2.0(react@16.14.0)))': + dependencies: + antd: 4.24.16(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + antd-mobile: 2.3.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + semver: 7.7.1 + umi: 3.5.43(react-router@5.2.0(react@16.14.0)) + transitivePeerDependencies: + - react + - react-dom + + '@umijs/plugin-crossorigin@1.2.1(umi@3.5.43(react-router@5.2.0(react@16.14.0)))': + dependencies: + umi: 3.5.43(react-router@5.2.0(react@16.14.0)) + + '@umijs/plugin-dva@0.13.0(dva-core@2.0.4(redux@4.2.1))(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0)(redbox-react@1.6.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(umi@3.5.43(react-router@5.2.0(react@16.14.0)))': + dependencies: + babel-plugin-dva-hmr: 0.4.2(redbox-react@1.6.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0)) + dva: 2.6.0-beta.23(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0) + dva-immer: 0.5.2(dva@2.6.0-beta.23(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0)) + dva-loading: 3.0.25(dva-core@2.0.4(redux@4.2.1)) + umi: 3.5.43(react-router@5.2.0(react@16.14.0)) + transitivePeerDependencies: + - dva-core + - react + - react-dom + - react-native + - react-router + - redbox-react + + '@umijs/plugin-helmet@1.1.3(react@16.14.0)(umi@3.5.43(react-router@5.2.0(react@16.14.0)))': + dependencies: + '@types/react-helmet': 6.1.11 + react-helmet: 6.1.0(react@16.14.0) + umi: 3.5.43(react-router@5.2.0(react@16.14.0)) + transitivePeerDependencies: + - react + + '@umijs/plugin-initial-state@2.4.0(umi@3.5.43(react-router@5.2.0(react@16.14.0)))': + dependencies: + umi: 3.5.43(react-router@5.2.0(react@16.14.0)) + + '@umijs/plugin-layout@0.18.1(@ant-design/icons@5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@ant-design/pro-layout@7.22.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@umijs/plugin-initial-state@2.4.0(umi@3.5.43(react-router@5.2.0(react@16.14.0))))(@umijs/plugin-locale@0.15.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(umi@3.5.43(react-router@5.2.0(react@16.14.0))))(@umijs/plugin-model@2.6.2(umi@3.5.43(react-router@5.2.0(react@16.14.0))))(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(umi@3.5.43(react-router@5.2.0(react@16.14.0)))': + dependencies: + '@ant-design/icons': 5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/pro-layout': 7.22.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@umijs/plugin-initial-state': 2.4.0(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + '@umijs/plugin-locale': 0.15.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + '@umijs/plugin-model': 2.6.2(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + '@umijs/route-utils': 2.2.2 + antd: 4.24.16(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + lodash: 4.17.21 + path-to-regexp: 1.9.0 + umi: 3.5.43(react-router@5.2.0(react@16.14.0)) + transitivePeerDependencies: + - react + - react-dom + + '@umijs/plugin-locale@0.15.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(umi@3.5.43(react-router@5.2.0(react@16.14.0)))': + dependencies: + '@ant-design/icons': 4.8.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@formatjs/intl-pluralrules': 1.5.9 + '@formatjs/intl-relativetimeformat': 4.5.16 + intl: 1.2.5 + moment: 2.30.1 + react-intl: 3.12.1(react@16.14.0) + umi: 3.5.43(react-router@5.2.0(react@16.14.0)) + warning: 4.0.3 + transitivePeerDependencies: + - react + - react-dom + + '@umijs/plugin-model@2.6.2(umi@3.5.43(react-router@5.2.0(react@16.14.0)))': + dependencies: + fast-deep-equal: 3.1.1 + umi: 3.5.43(react-router@5.2.0(react@16.14.0)) + + '@umijs/plugin-openapi@1.3.3(chokidar@3.6.0)(encoding@0.1.13)(typescript@4.9.5)(umi@3.5.43(react-router@5.2.0(react@16.14.0)))': + dependencies: + '@umijs/openapi': 1.13.0(chokidar@3.6.0)(encoding@0.1.13)(typescript@4.9.5) + serve-static: 1.16.2 + swagger-ui-dist: 4.19.1 + umi: 3.5.43(react-router@5.2.0(react@16.14.0)) + transitivePeerDependencies: + - chokidar + - encoding + - supports-color + - typescript + + '@umijs/plugin-request@2.8.0(react@16.14.0)(umi@3.5.43(react-router@5.2.0(react@16.14.0)))': + dependencies: + '@ahooksjs/use-request': 2.8.15(react@16.14.0) + umi: 3.5.43(react-router@5.2.0(react@16.14.0)) + umi-request: 1.4.0 + transitivePeerDependencies: + - react + + '@umijs/plugin-test@1.0.2(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5))(umi@3.5.43(react-router@5.2.0(react@16.14.0)))': + dependencies: + '@umijs/test': 3.5.43(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + umi: 3.5.43(react-router@5.2.0(react@16.14.0)) + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + '@umijs/preset-built-in@3.5.43(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@types/react-router-config': 5.0.2 + '@umijs/babel-preset-umi': 3.5.43 + '@umijs/bundler-webpack': 3.5.43(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0) + '@umijs/core': 3.5.43 + '@umijs/deps': 3.5.43 + '@umijs/renderer-mpa': 3.5.43(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@umijs/renderer-react': 3.5.43(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0) + '@umijs/runtime': 3.5.43(react@16.14.0) + '@umijs/server': 3.5.43 + '@umijs/types': 3.5.43(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0) + '@umijs/utils': 3.5.43 + ansi-html: 0.0.9 + core-js: 3.6.5 + core-js-pure: 3.41.0 + error-stack-parser: 2.1.4 + es-module-lexer: 0.7.1 + es5-imcompatible-versions: 0.1.90 + history-with-query: 4.10.4 + html-entities: 2.6.0 + mime: 1.4.1 + react: 16.14.0 + react-refresh: 0.10.0 + react-router: 5.2.0(react@16.14.0) + react-router-config: 5.1.1(react-router@5.2.0(react@16.14.0))(react@16.14.0) + react-router-dom: 5.2.0(react@16.14.0) + regenerator-runtime: 0.13.5 + schema-utils: 3.3.0 + transitivePeerDependencies: + - react-dom + + '@umijs/preset-react@1.8.32(@ant-design/icons@5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@ant-design/pro-layout@7.22.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(dva-core@2.0.4(redux@4.2.1))(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0)(redbox-react@1.6.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5))(umi@3.5.43(react-router@5.2.0(react@16.14.0)))': + dependencies: + '@umijs/plugin-access': 2.4.3(@umijs/plugin-initial-state@2.4.0(umi@3.5.43(react-router@5.2.0(react@16.14.0))))(@umijs/plugin-model@2.6.2(umi@3.5.43(react-router@5.2.0(react@16.14.0))))(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + '@umijs/plugin-analytics': 0.2.2(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + '@umijs/plugin-antd': 0.13.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + '@umijs/plugin-crossorigin': 1.2.1(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + '@umijs/plugin-dva': 0.13.0(dva-core@2.0.4(redux@4.2.1))(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0)(redbox-react@1.6.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + '@umijs/plugin-helmet': 1.1.3(react@16.14.0)(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + '@umijs/plugin-initial-state': 2.4.0(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + '@umijs/plugin-layout': 0.18.1(@ant-design/icons@5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@ant-design/pro-layout@7.22.4(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(@umijs/plugin-initial-state@2.4.0(umi@3.5.43(react-router@5.2.0(react@16.14.0))))(@umijs/plugin-locale@0.15.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(umi@3.5.43(react-router@5.2.0(react@16.14.0))))(@umijs/plugin-model@2.6.2(umi@3.5.43(react-router@5.2.0(react@16.14.0))))(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + '@umijs/plugin-locale': 0.15.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + '@umijs/plugin-model': 2.6.2(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + '@umijs/plugin-request': 2.8.0(react@16.14.0)(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + '@umijs/plugin-test': 1.0.2(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5))(umi@3.5.43(react-router@5.2.0(react@16.14.0))) + umi: 3.5.43(react-router@5.2.0(react@16.14.0)) + transitivePeerDependencies: + - '@ant-design/icons' + - '@ant-design/pro-layout' + - bufferutil + - canvas + - dva-core + - react + - react-dom + - react-native + - react-router + - redbox-react + - supports-color + - ts-node + - utf-8-validate + + '@umijs/renderer-mpa@3.5.43(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@types/react': 16.14.63 + '@types/react-dom': 16.9.25(@types/react@16.14.63) + '@umijs/runtime': 3.5.43(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + '@umijs/renderer-react@3.5.43(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@types/react': 16.14.63 + '@types/react-dom': 16.9.25(@types/react@16.14.63) + '@types/react-router-config': 5.0.2 + '@umijs/runtime': 3.5.43(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + react-router-config: 5.1.1(react-router@5.2.0(react@16.14.0))(react@16.14.0) + transitivePeerDependencies: + - react-router + + '@umijs/route-utils@2.2.2': + dependencies: + '@qixian.cs/path-to-regexp': 6.1.0 + fast-deep-equal: 3.1.3 + lodash.isequal: 4.5.0 + memoize-one: 5.2.1 + + '@umijs/route-utils@4.0.1': {} + + '@umijs/runtime@3.5.43(react@16.14.0)': + dependencies: + '@types/react-router': 5.1.12 + '@types/react-router-dom': 5.1.7 + history-with-query: 4.10.4 + react: 16.14.0 + react-router: 5.2.0(react@16.14.0) + react-router-dom: 5.2.0(react@16.14.0) + use-subscription: 1.5.1(react@16.14.0) + + '@umijs/server@3.5.43': + dependencies: + '@umijs/core': 3.5.43 + '@umijs/deps': 3.5.43 + '@umijs/utils': 3.5.43 + + '@umijs/test@3.5.43(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5))': + dependencies: + '@babel/core': 7.18.6 + '@umijs/babel-preset-umi': 3.5.43 + '@umijs/utils': 3.5.43 + babel-jest: 26.6.3(@babel/core@7.18.6) + core-js: 3.8.2 + identity-obj-proxy: 3.0.0 + jest: 26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + jest-cli: 26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + regenerator-runtime: 0.13.11 + whatwg-fetch: 3.6.20 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + '@umijs/types@3.5.43(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0)': + dependencies: + '@umijs/babel-preset-umi': 3.5.43 + '@umijs/core': 3.5.43 + '@umijs/deps': 3.5.43 + '@umijs/renderer-react': 3.5.43(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0) + '@umijs/server': 3.5.43 + '@umijs/utils': 3.5.43 + webpack-chain: 6.5.1 + transitivePeerDependencies: + - react + - react-dom + - react-router + + '@umijs/use-params@1.0.9(react@16.14.0)': + dependencies: + react: 16.14.0 + + '@umijs/utils@3.5.43': + dependencies: + '@umijs/babel-preset-umi': 3.5.43 + '@umijs/deps': 3.5.43 + + '@webassemblyjs/ast@1.14.1': + dependencies: + '@webassemblyjs/helper-numbers': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + + '@webassemblyjs/floating-point-hex-parser@1.13.2': {} + + '@webassemblyjs/helper-api-error@1.13.2': {} + + '@webassemblyjs/helper-buffer@1.14.1': {} + + '@webassemblyjs/helper-numbers@1.13.2': + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.13.2 + '@webassemblyjs/helper-api-error': 1.13.2 + '@xtuc/long': 4.2.2 + + '@webassemblyjs/helper-wasm-bytecode@1.13.2': {} + + '@webassemblyjs/helper-wasm-section@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/wasm-gen': 1.14.1 + + '@webassemblyjs/ieee754@1.13.2': + dependencies: + '@xtuc/ieee754': 1.2.0 + + '@webassemblyjs/leb128@1.13.2': + dependencies: + '@xtuc/long': 4.2.2 + + '@webassemblyjs/utf8@1.13.2': {} + + '@webassemblyjs/wasm-edit@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/helper-wasm-section': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-opt': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + '@webassemblyjs/wast-printer': 1.14.1 + + '@webassemblyjs/wasm-gen@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 + + '@webassemblyjs/wasm-opt@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + + '@webassemblyjs/wasm-parser@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-api-error': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 + + '@webassemblyjs/wast-printer@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@xtuc/long': 4.2.2 + + '@webgpu/glslang@0.0.15': {} + + '@webgpu/types@0.0.31': {} + + '@webgpu/types@0.1.60': {} + + '@xobotyi/scrollbar-width@1.9.5': {} + + '@xtuc/ieee754@1.2.0': {} + + '@xtuc/long@4.2.2': {} + + a-sync-waterfall@1.0.1: {} + + abab@2.0.6: {} + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + acorn-globals@6.0.0: + dependencies: + acorn: 7.4.1 + acorn-walk: 7.2.0 + + acorn-jsx@5.3.2(acorn@8.14.1): + dependencies: + acorn: 8.14.1 + + acorn-walk@7.2.0: {} + + acorn-walk@8.3.4: + dependencies: + acorn: 8.14.1 + + acorn@7.4.1: {} + + acorn@8.14.1: {} + + add-dom-event-listener@1.1.0: + dependencies: + object-assign: 4.1.1 + + address@1.2.2: {} + + adjust-sourcemap-loader@4.0.0: + dependencies: + loader-utils: 2.0.4 + regex-parser: 2.3.1 + + adler-32@1.2.0: + dependencies: + exit-on-epipe: 1.0.1 + printj: 1.1.2 + + adler-32@1.3.1: {} + + agent-base@6.0.2: + dependencies: + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + + aggregate-error@3.1.0: + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + + ahooks@2.10.14(react@16.14.0): + dependencies: + '@ahooksjs/use-request': 2.8.15(react@16.14.0) + '@types/js-cookie': 2.2.7 + dayjs: 1.11.13 + intersection-observer: 0.7.0 + js-cookie: 2.2.1 + lodash.debounce: 4.0.8 + lodash.isequal: 4.5.0 + lodash.throttle: 4.1.1 + react: 16.14.0 + resize-observer-polyfill: 1.5.1 + screenfull: 5.2.0 + + ahooks@3.8.4(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + dayjs: 1.11.13 + intersection-observer: 0.12.2 + js-cookie: 3.0.5 + lodash: 4.17.21 + react: 16.14.0 + react-fast-compare: 3.2.2 + resize-observer-polyfill: 1.5.1 + screenfull: 5.2.0 + tslib: 2.8.1 + + ajv-errors@1.0.1(ajv@6.12.6): + dependencies: + ajv: 6.12.6 + + ajv-formats@2.1.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + + ajv-keywords@3.5.2(ajv@6.12.6): + dependencies: + ajv: 6.12.6 + + ajv-keywords@5.1.0(ajv@8.17.1): + dependencies: + ajv: 8.17.1 + fast-deep-equal: 3.1.3 + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.6 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + align-text@0.1.4: + dependencies: + kind-of: 3.2.2 + longest: 1.0.1 + repeat-string: 1.6.1 + + amdefine@1.0.1: {} + + ansi-colors@4.1.3: {} + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-html-community@0.0.8: {} + + ansi-html@0.0.9: {} + + ansi-regex@2.1.1: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@2.2.1: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansi-styles@6.2.1: {} + + antd-mobile@2.3.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + array-tree-filter: 2.1.0 + babel-runtime: 6.26.0 + classnames: 2.5.1 + normalize.css: 7.0.0 + rc-checkbox: 2.0.3 + rc-collapse: 1.9.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-slider: 8.2.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-swipeout: 2.0.11 + rmc-calendar: 1.1.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rmc-cascader: 5.0.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rmc-date-picker: 6.0.10(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rmc-dialog: 1.1.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rmc-drawer: 0.4.11 + rmc-feedback: 2.0.0 + rmc-input-number: 1.0.5 + rmc-list-view: 0.11.5 + rmc-notification: 1.0.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rmc-nuka-carousel: 3.0.1 + rmc-picker: 5.0.10(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rmc-pull-to-refresh: 1.0.13 + rmc-steps: 1.0.1 + rmc-tabs: 1.2.29 + rmc-tooltip: 1.0.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + transitivePeerDependencies: + - react + - react-dom + + antd-style@3.7.1(@types/react@17.0.52)(antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@ant-design/cssinjs': 1.23.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@babel/runtime': 7.27.0 + '@emotion/cache': 11.14.0 + '@emotion/css': 11.13.5 + '@emotion/react': 11.14.0(@types/react@17.0.52)(react@16.14.0) + '@emotion/serialize': 1.3.3 + '@emotion/utils': 1.4.2 + antd: 5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + use-merge-value: 1.2.0(react@16.14.0) + transitivePeerDependencies: + - '@types/react' + - react-dom + - supports-color + + antd@4.24.16(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@ant-design/colors': 6.0.0 + '@ant-design/icons': 4.8.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/react-slick': 1.0.2(react@16.14.0) + '@babel/runtime': 7.27.0 + '@ctrl/tinycolor': 3.6.1 + classnames: 2.5.1 + copy-to-clipboard: 3.3.3 + lodash: 4.17.21 + moment: 2.30.1 + rc-cascader: 3.7.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-checkbox: 3.0.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-collapse: 3.4.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-dialog: 9.0.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-drawer: 6.3.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-dropdown: 4.0.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-field-form: 1.38.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-image: 5.13.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-input: 0.1.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-input-number: 7.3.11(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-mentions: 1.13.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-menu: 9.8.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-notification: 4.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-pagination: 3.2.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-picker: 2.7.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-progress: 3.4.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-rate: 2.9.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-resize-observer: 1.4.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-segmented: 2.3.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-select: 14.1.18(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-slider: 10.0.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-steps: 5.0.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-switch: 3.2.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-table: 7.26.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-tabs: 12.5.10(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-textarea: 0.4.7(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-tooltip: 5.2.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-tree: 5.7.12(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-tree-select: 5.5.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-trigger: 5.3.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-upload: 4.3.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + scroll-into-view-if-needed: 2.2.31 + + antd@5.24.8(date-fns@2.30.0)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@ant-design/colors': 7.2.0 + '@ant-design/cssinjs': 1.23.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/cssinjs-utils': 1.1.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/fast-color': 2.0.6 + '@ant-design/icons': 5.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@ant-design/react-slick': 1.1.2(react@16.14.0) + '@babel/runtime': 7.27.0 + '@rc-component/color-picker': 2.0.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@rc-component/mutate-observer': 1.1.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@rc-component/qrcode': 1.0.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@rc-component/tour': 1.15.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@rc-component/trigger': 2.2.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + copy-to-clipboard: 3.3.3 + dayjs: 1.11.13 + rc-cascader: 3.33.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-checkbox: 3.5.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-collapse: 3.9.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-dialog: 9.6.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-drawer: 7.2.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-dropdown: 4.2.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-field-form: 2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-image: 7.11.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-input: 1.8.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-input-number: 9.5.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-mentions: 2.20.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-menu: 9.16.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-notification: 5.6.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-pagination: 5.1.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-picker: 4.11.3(date-fns@2.30.0)(dayjs@1.11.13)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-progress: 4.0.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-rate: 2.13.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-resize-observer: 1.4.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-segmented: 2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-select: 14.16.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-slider: 11.1.8(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-steps: 6.0.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-switch: 4.1.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-table: 7.50.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-tabs: 15.6.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-textarea: 1.10.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-tooltip: 6.4.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-tree: 5.13.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-tree-select: 5.27.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-upload: 4.8.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + scroll-into-view-if-needed: 3.1.0 + throttle-debounce: 5.0.2 + transitivePeerDependencies: + - date-fns + - luxon + - moment + + any-promise@1.3.0: {} + + anymatch@1.3.2: + dependencies: + micromatch: 2.3.11 + normalize-path: 2.1.1 + optional: true + + anymatch@2.0.0: + dependencies: + micromatch: 3.1.10 + normalize-path: 2.1.1 + transitivePeerDependencies: + - supports-color + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + arch@2.2.0: {} + + arg@4.1.3: {} + + arg@5.0.2: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + aria-query@5.3.2: {} + + arr-diff@2.0.0: + dependencies: + arr-flatten: 1.1.0 + optional: true + + arr-diff@4.0.0: {} + + arr-flatten@1.1.0: {} + + arr-union@3.1.0: {} + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + array-flatten@1.1.1: {} + + array-includes@3.1.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + is-string: 1.1.1 + + array-tree-filter@2.1.0: {} + + array-union@1.0.2: + dependencies: + array-uniq: 1.0.3 + + array-union@2.1.0: {} + + array-uniq@1.0.3: {} + + array-unique@0.2.1: + optional: true + + array-unique@0.3.2: {} + + array.prototype.findlast@1.2.5: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.1.0 + + array.prototype.findlastindex@1.2.6: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.1.0 + + array.prototype.flat@1.3.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-shim-unscopables: 1.1.0 + + array.prototype.flatmap@1.3.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-shim-unscopables: 1.1.0 + + array.prototype.reduce@1.0.8: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-array-method-boxes-properly: 1.0.0 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + is-string: 1.1.1 + + array.prototype.tosorted@1.1.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-shim-unscopables: 1.1.0 + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 + + arrify@2.0.1: {} + + as-number@1.0.0: {} + + asap@2.0.6: {} + + asn1.js@4.10.1: + dependencies: + bn.js: 4.12.2 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + + assert@1.5.1: + dependencies: + object.assign: 4.1.7 + util: 0.10.4 + + assign-symbols@1.0.0: {} + + ast-types-flow@0.0.8: {} + + astral-regex@2.0.0: {} + + async-each@1.0.6: + optional: true + + async-function@1.0.0: {} + + async-validator@1.11.5: {} + + async-validator@4.2.5: {} + + async@3.2.6: {} + + asynckit@0.4.0: {} + + at-least-node@1.0.0: {} + + atob@2.1.2: {} + + autoprefixer@10.4.21(postcss@8.5.3): + dependencies: + browserslist: 4.24.4 + caniuse-lite: 1.0.30001715 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.1.1 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + autoprefixer@9.8.8: + dependencies: + browserslist: 4.24.4 + caniuse-lite: 1.0.30001715 + normalize-range: 0.1.2 + num2fraction: 1.2.2 + picocolors: 0.2.1 + postcss: 7.0.32 + postcss-value-parser: 4.2.0 + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + axe-core@4.10.3: {} + + axios@0.30.0: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.2 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + axobject-query@4.1.0: {} + + babel-cli@6.26.0: + dependencies: + babel-core: 6.26.3 + babel-polyfill: 6.26.0 + babel-register: 6.26.0 + babel-runtime: 6.26.0 + commander: 2.20.3 + convert-source-map: 1.9.0 + fs-readdir-recursive: 1.1.0 + glob: 7.2.3 + lodash: 4.17.21 + output-file-sync: 1.1.2 + path-is-absolute: 1.0.1 + slash: 1.0.0 + source-map: 0.5.7 + v8flags: 2.1.1 + optionalDependencies: + chokidar: 1.7.0 + transitivePeerDependencies: + - supports-color + + babel-code-frame@6.26.0: + dependencies: + chalk: 1.1.3 + esutils: 2.0.3 + js-tokens: 3.0.2 + + babel-core@6.26.3: + dependencies: + babel-code-frame: 6.26.0 + babel-generator: 6.26.1 + babel-helpers: 6.24.1 + babel-messages: 6.23.0 + babel-register: 6.26.0 + babel-runtime: 6.26.0 + babel-template: 6.26.0 + babel-traverse: 6.26.0 + babel-types: 6.26.0 + babylon: 6.18.0 + convert-source-map: 1.9.0 + debug: 2.6.9 + json5: 0.5.1 + lodash: 4.17.21 + minimatch: 3.1.2 + path-is-absolute: 1.0.1 + private: 0.1.8 + slash: 1.0.0 + source-map: 0.5.7 + transitivePeerDependencies: + - supports-color + + babel-generator@6.26.1: + dependencies: + babel-messages: 6.23.0 + babel-runtime: 6.26.0 + babel-types: 6.26.0 + detect-indent: 4.0.0 + jsesc: 1.3.0 + lodash: 4.17.21 + source-map: 0.5.7 + trim-right: 1.0.1 + + babel-helper-call-delegate@6.24.1: + dependencies: + babel-helper-hoist-variables: 6.24.1 + babel-runtime: 6.26.0 + babel-traverse: 6.26.0 + babel-types: 6.26.0 + transitivePeerDependencies: + - supports-color + + babel-helper-define-map@6.26.0: + dependencies: + babel-helper-function-name: 6.24.1 + babel-runtime: 6.26.0 + babel-types: 6.26.0 + lodash: 4.17.21 + transitivePeerDependencies: + - supports-color + + babel-helper-function-name@6.24.1: + dependencies: + babel-helper-get-function-arity: 6.24.1 + babel-runtime: 6.26.0 + babel-template: 6.26.0 + babel-traverse: 6.26.0 + babel-types: 6.26.0 + transitivePeerDependencies: + - supports-color + + babel-helper-get-function-arity@6.24.1: + dependencies: + babel-runtime: 6.26.0 + babel-types: 6.26.0 + + babel-helper-hoist-variables@6.24.1: + dependencies: + babel-runtime: 6.26.0 + babel-types: 6.26.0 + + babel-helper-optimise-call-expression@6.24.1: + dependencies: + babel-runtime: 6.26.0 + babel-types: 6.26.0 + + babel-helper-regex@6.26.0: + dependencies: + babel-runtime: 6.26.0 + babel-types: 6.26.0 + lodash: 4.17.21 + + babel-helper-replace-supers@6.24.1: + dependencies: + babel-helper-optimise-call-expression: 6.24.1 + babel-messages: 6.23.0 + babel-runtime: 6.26.0 + babel-template: 6.26.0 + babel-traverse: 6.26.0 + babel-types: 6.26.0 + transitivePeerDependencies: + - supports-color + + babel-helpers@6.24.1: + dependencies: + babel-runtime: 6.26.0 + babel-template: 6.26.0 + transitivePeerDependencies: + - supports-color + + babel-jest@26.6.3(@babel/core@7.18.6): + dependencies: + '@babel/core': 7.18.6 + '@jest/transform': 26.6.2 + '@jest/types': 26.6.2 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 26.6.2(@babel/core@7.18.6) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + + babel-jest@27.5.1(@babel/core@7.26.10): + dependencies: + '@babel/core': 7.26.10 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 27.5.1(@babel/core@7.26.10) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + + babel-loader@8.4.1(@babel/core@7.26.10)(webpack@5.99.7): + dependencies: + '@babel/core': 7.26.10 + find-cache-dir: 3.3.2 + loader-utils: 2.0.4 + make-dir: 3.1.0 + schema-utils: 2.7.1 + webpack: 5.99.7 + + babel-messages@6.23.0: + dependencies: + babel-runtime: 6.26.0 + + babel-plugin-check-es2015-constants@6.22.0: + dependencies: + babel-runtime: 6.26.0 + + babel-plugin-dva-hmr@0.4.2(redbox-react@1.6.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0)): + dependencies: + redbox-react: 1.6.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + + babel-plugin-istanbul@6.1.1: + dependencies: + '@babel/helper-plugin-utils': 7.26.5 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-jest-hoist@26.6.2: + dependencies: + '@babel/template': 7.27.0 + '@babel/types': 7.27.0 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.20.7 + + babel-plugin-jest-hoist@27.5.1: + dependencies: + '@babel/template': 7.27.0 + '@babel/types': 7.27.0 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.20.7 + + babel-plugin-macros@3.1.0: + dependencies: + '@babel/runtime': 7.27.0 + cosmiconfig: 7.1.0 + resolve: 1.22.10 + + babel-plugin-named-asset-import@0.3.8(@babel/core@7.26.10): + dependencies: + '@babel/core': 7.26.10 + + babel-plugin-polyfill-corejs2@0.4.13(@babel/core@7.26.10): + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/core': 7.26.10 + '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.26.10) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.11.1(@babel/core@7.26.10): + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.26.10) + core-js-compat: 3.41.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-regenerator@0.6.4(@babel/core@7.26.10): + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.26.10) + transitivePeerDependencies: + - supports-color + + babel-plugin-transform-es2015-arrow-functions@6.22.0: + dependencies: + babel-runtime: 6.26.0 + + babel-plugin-transform-es2015-block-scoped-functions@6.22.0: + dependencies: + babel-runtime: 6.26.0 + + babel-plugin-transform-es2015-block-scoping@6.26.0: + dependencies: + babel-runtime: 6.26.0 + babel-template: 6.26.0 + babel-traverse: 6.26.0 + babel-types: 6.26.0 + lodash: 4.17.21 + transitivePeerDependencies: + - supports-color + + babel-plugin-transform-es2015-classes@6.24.1: + dependencies: + babel-helper-define-map: 6.26.0 + babel-helper-function-name: 6.24.1 + babel-helper-optimise-call-expression: 6.24.1 + babel-helper-replace-supers: 6.24.1 + babel-messages: 6.23.0 + babel-runtime: 6.26.0 + babel-template: 6.26.0 + babel-traverse: 6.26.0 + babel-types: 6.26.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-transform-es2015-computed-properties@6.24.1: + dependencies: + babel-runtime: 6.26.0 + babel-template: 6.26.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-transform-es2015-destructuring@6.23.0: + dependencies: + babel-runtime: 6.26.0 + + babel-plugin-transform-es2015-duplicate-keys@6.24.1: + dependencies: + babel-runtime: 6.26.0 + babel-types: 6.26.0 + + babel-plugin-transform-es2015-for-of@6.23.0: + dependencies: + babel-runtime: 6.26.0 + + babel-plugin-transform-es2015-function-name@6.24.1: + dependencies: + babel-helper-function-name: 6.24.1 + babel-runtime: 6.26.0 + babel-types: 6.26.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-transform-es2015-literals@6.22.0: + dependencies: + babel-runtime: 6.26.0 + + babel-plugin-transform-es2015-modules-amd@6.24.1: + dependencies: + babel-plugin-transform-es2015-modules-commonjs: 6.26.2 + babel-runtime: 6.26.0 + babel-template: 6.26.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-transform-es2015-modules-commonjs@6.26.2: + dependencies: + babel-plugin-transform-strict-mode: 6.24.1 + babel-runtime: 6.26.0 + babel-template: 6.26.0 + babel-types: 6.26.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-transform-es2015-modules-systemjs@6.24.1: + dependencies: + babel-helper-hoist-variables: 6.24.1 + babel-runtime: 6.26.0 + babel-template: 6.26.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-transform-es2015-modules-umd@6.24.1: + dependencies: + babel-plugin-transform-es2015-modules-amd: 6.24.1 + babel-runtime: 6.26.0 + babel-template: 6.26.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-transform-es2015-object-super@6.24.1: + dependencies: + babel-helper-replace-supers: 6.24.1 + babel-runtime: 6.26.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-transform-es2015-parameters@6.24.1: + dependencies: + babel-helper-call-delegate: 6.24.1 + babel-helper-get-function-arity: 6.24.1 + babel-runtime: 6.26.0 + babel-template: 6.26.0 + babel-traverse: 6.26.0 + babel-types: 6.26.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-transform-es2015-shorthand-properties@6.24.1: + dependencies: + babel-runtime: 6.26.0 + babel-types: 6.26.0 + + babel-plugin-transform-es2015-spread@6.22.0: + dependencies: + babel-runtime: 6.26.0 + + babel-plugin-transform-es2015-sticky-regex@6.24.1: + dependencies: + babel-helper-regex: 6.26.0 + babel-runtime: 6.26.0 + babel-types: 6.26.0 + + babel-plugin-transform-es2015-template-literals@6.22.0: + dependencies: + babel-runtime: 6.26.0 + + babel-plugin-transform-es2015-typeof-symbol@6.23.0: + dependencies: + babel-runtime: 6.26.0 + + babel-plugin-transform-es2015-unicode-regex@6.24.1: + dependencies: + babel-helper-regex: 6.26.0 + babel-runtime: 6.26.0 + regexpu-core: 2.0.0 + + babel-plugin-transform-react-remove-prop-types@0.4.24: {} + + babel-plugin-transform-regenerator@6.26.0: + dependencies: + regenerator-transform: 0.10.1 + + babel-plugin-transform-strict-mode@6.24.1: + dependencies: + babel-runtime: 6.26.0 + babel-types: 6.26.0 + + babel-polyfill@6.26.0: + dependencies: + babel-runtime: 6.26.0 + core-js: 2.6.12 + regenerator-runtime: 0.10.5 + + babel-preset-current-node-syntax@1.1.0(@babel/core@7.18.6): + dependencies: + '@babel/core': 7.18.6 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.18.6) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.18.6) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.18.6) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.18.6) + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.18.6) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.18.6) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.18.6) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.18.6) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.18.6) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.18.6) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.18.6) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.18.6) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.18.6) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.18.6) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.18.6) + + babel-preset-current-node-syntax@1.1.0(@babel/core@7.26.10): + dependencies: + '@babel/core': 7.26.10 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.26.10) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.26.10) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.26.10) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.26.10) + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.10) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.26.10) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.26.10) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.26.10) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.10) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.10) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.26.10) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.26.10) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.10) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.10) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.26.10) + + babel-preset-es2015@6.24.1: + dependencies: + babel-plugin-check-es2015-constants: 6.22.0 + babel-plugin-transform-es2015-arrow-functions: 6.22.0 + babel-plugin-transform-es2015-block-scoped-functions: 6.22.0 + babel-plugin-transform-es2015-block-scoping: 6.26.0 + babel-plugin-transform-es2015-classes: 6.24.1 + babel-plugin-transform-es2015-computed-properties: 6.24.1 + babel-plugin-transform-es2015-destructuring: 6.23.0 + babel-plugin-transform-es2015-duplicate-keys: 6.24.1 + babel-plugin-transform-es2015-for-of: 6.23.0 + babel-plugin-transform-es2015-function-name: 6.24.1 + babel-plugin-transform-es2015-literals: 6.22.0 + babel-plugin-transform-es2015-modules-amd: 6.24.1 + babel-plugin-transform-es2015-modules-commonjs: 6.26.2 + babel-plugin-transform-es2015-modules-systemjs: 6.24.1 + babel-plugin-transform-es2015-modules-umd: 6.24.1 + babel-plugin-transform-es2015-object-super: 6.24.1 + babel-plugin-transform-es2015-parameters: 6.24.1 + babel-plugin-transform-es2015-shorthand-properties: 6.24.1 + babel-plugin-transform-es2015-spread: 6.22.0 + babel-plugin-transform-es2015-sticky-regex: 6.24.1 + babel-plugin-transform-es2015-template-literals: 6.22.0 + babel-plugin-transform-es2015-typeof-symbol: 6.23.0 + babel-plugin-transform-es2015-unicode-regex: 6.24.1 + babel-plugin-transform-regenerator: 6.26.0 + transitivePeerDependencies: + - supports-color + + babel-preset-jest@26.6.2(@babel/core@7.18.6): + dependencies: + '@babel/core': 7.18.6 + babel-plugin-jest-hoist: 26.6.2 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.18.6) + + babel-preset-jest@27.5.1(@babel/core@7.26.10): + dependencies: + '@babel/core': 7.26.10 + babel-plugin-jest-hoist: 27.5.1 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.10) + + babel-preset-react-app@10.1.0: + dependencies: + '@babel/core': 7.26.10 + '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.26.10) + '@babel/plugin-proposal-decorators': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.26.10) + '@babel/plugin-proposal-numeric-separator': 7.18.6(@babel/core@7.26.10) + '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.26.10) + '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.26.10) + '@babel/plugin-proposal-private-property-in-object': 7.21.11(@babel/core@7.26.10) + '@babel/plugin-transform-flow-strip-types': 7.26.5(@babel/core@7.26.10) + '@babel/plugin-transform-react-display-name': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-runtime': 7.26.10(@babel/core@7.26.10) + '@babel/preset-env': 7.26.9(@babel/core@7.26.10) + '@babel/preset-react': 7.26.3(@babel/core@7.26.10) + '@babel/preset-typescript': 7.27.0(@babel/core@7.26.10) + '@babel/runtime': 7.27.0 + babel-plugin-macros: 3.1.0 + babel-plugin-transform-react-remove-prop-types: 0.4.24 + transitivePeerDependencies: + - supports-color + + babel-register@6.26.0: + dependencies: + babel-core: 6.26.3 + babel-runtime: 6.26.0 + core-js: 2.6.12 + home-or-tmp: 2.0.0 + lodash: 4.17.21 + mkdirp: 0.5.6 + source-map-support: 0.4.18 + transitivePeerDependencies: + - supports-color + + babel-runtime@6.26.0: + dependencies: + core-js: 2.6.12 + regenerator-runtime: 0.11.1 + + babel-template@6.26.0: + dependencies: + babel-runtime: 6.26.0 + babel-traverse: 6.26.0 + babel-types: 6.26.0 + babylon: 6.18.0 + lodash: 4.17.21 + transitivePeerDependencies: + - supports-color + + babel-traverse@6.26.0: + dependencies: + babel-code-frame: 6.26.0 + babel-messages: 6.23.0 + babel-runtime: 6.26.0 + babel-types: 6.26.0 + babylon: 6.18.0 + debug: 2.6.9 + globals: 9.18.0 + invariant: 2.2.4 + lodash: 4.17.21 + transitivePeerDependencies: + - supports-color + + babel-types@6.26.0: + dependencies: + babel-runtime: 6.26.0 + esutils: 2.0.3 + lodash: 4.17.21 + to-fast-properties: 1.0.3 + + babylon@6.18.0: {} + + balanced-match@1.0.2: {} + + base16@1.0.0: {} + + base64-js@1.5.1: {} + + base@0.11.2: + dependencies: + cache-base: 1.0.1 + class-utils: 0.3.6 + component-emitter: 1.3.1 + define-property: 1.0.0 + isobject: 3.0.1 + mixin-deep: 1.3.2 + pascalcase: 0.1.1 + + batch-processor@1.0.0: {} + + batch@0.6.1: {} + + bfj@7.1.0: + dependencies: + bluebird: 3.7.2 + check-types: 11.2.3 + hoopy: 0.1.4 + jsonpath: 1.1.1 + tryer: 1.0.1 + + big.js@5.2.2: {} + + bignumber.js@9.3.0: {} + + binary-extensions@1.13.1: + optional: true + + binary-extensions@2.3.0: {} + + bindings@1.5.0: + dependencies: + file-uri-to-path: 1.0.0 + optional: true + + bluebird@3.7.2: {} + + bn.js@4.12.2: {} + + bn.js@5.2.2: {} + + body-parser@1.20.3: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.13.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + bonjour-service@1.3.0: + dependencies: + fast-deep-equal: 3.1.3 + multicast-dns: 7.2.5 + + boolbase@1.0.0: {} + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@1.8.5: + dependencies: + expand-range: 1.8.2 + preserve: 0.2.0 + repeat-element: 1.1.4 + optional: true + + braces@2.3.2: + dependencies: + arr-flatten: 1.1.0 + array-unique: 0.3.2 + extend-shallow: 2.0.1 + fill-range: 4.0.0 + isobject: 3.0.1 + repeat-element: 1.1.4 + snapdragon: 0.8.2 + snapdragon-node: 2.1.1 + split-string: 3.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + brorand@1.1.0: {} + + browser-process-hrtime@1.0.0: {} + + browserify-aes@1.2.0: + dependencies: + buffer-xor: 1.0.3 + cipher-base: 1.0.6 + create-hash: 1.2.0 + evp_bytestokey: 1.0.3 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + browserify-cipher@1.0.1: + dependencies: + browserify-aes: 1.2.0 + browserify-des: 1.0.2 + evp_bytestokey: 1.0.3 + + browserify-des@1.0.2: + dependencies: + cipher-base: 1.0.6 + des.js: 1.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + browserify-rsa@4.1.1: + dependencies: + bn.js: 5.2.2 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + + browserify-sign@4.2.3: + dependencies: + bn.js: 5.2.2 + browserify-rsa: 4.1.1 + create-hash: 1.2.0 + create-hmac: 1.1.7 + elliptic: 6.6.1 + hash-base: 3.0.5 + inherits: 2.0.4 + parse-asn1: 5.1.7 + readable-stream: 2.3.8 + safe-buffer: 5.2.1 + + browserify-zlib@0.2.0: + dependencies: + pako: 1.0.11 + + browserslist@4.24.4: + dependencies: + caniuse-lite: 1.0.30001715 + electron-to-chromium: 1.5.143 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.24.4) + + bser@2.1.1: + dependencies: + node-int64: 0.4.0 + + buffer-from@1.1.2: {} + + buffer-xor@1.0.3: {} + + buffer@4.9.2: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + isarray: 1.0.0 + + builtin-modules@3.3.0: {} + + builtin-status-codes@3.0.0: {} + + bytes@3.1.2: {} + + bytewise-core@1.2.3: + dependencies: + typewise-core: 1.2.0 + + bytewise@1.1.0: + dependencies: + bytewise-core: 1.2.3 + typewise: 1.0.3 + + cache-base@1.0.1: + dependencies: + collection-visit: 1.0.0 + component-emitter: 1.3.1 + get-value: 2.0.6 + has-value: 1.0.0 + isobject: 3.0.1 + set-value: 2.0.1 + to-object-path: 0.3.0 + union-value: 1.0.1 + unset-value: 1.0.0 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + call-me-maybe@1.0.2: {} + + caller-callsite@2.0.0: + dependencies: + callsites: 2.0.0 + + caller-path@2.0.0: + dependencies: + caller-callsite: 2.0.0 + + callsites@2.0.0: {} + + callsites@3.1.0: {} + + camel-case@4.1.2: + dependencies: + pascal-case: 3.1.2 + tslib: 2.8.1 + + camelcase-css@2.0.1: {} + + camelcase@1.2.1: {} + + camelcase@5.3.1: {} + + camelcase@6.3.0: {} + + caniuse-api@3.0.0: + dependencies: + browserslist: 4.24.4 + caniuse-lite: 1.0.30001715 + lodash.memoize: 4.1.2 + lodash.uniq: 4.5.0 + + caniuse-lite@1.0.30001715: {} + + capture-exit@2.0.0: + dependencies: + rsvp: 4.8.5 + + case-sensitive-paths-webpack-plugin@2.4.0: {} + + center-align@0.1.3: + dependencies: + align-text: 0.1.4 + lazy-cache: 1.0.4 + + cfb@1.2.2: + dependencies: + adler-32: 1.3.1 + crc-32: 1.2.2 + + chalk@1.1.3: + dependencies: + ansi-styles: 2.2.1 + escape-string-regexp: 1.0.5 + has-ansi: 2.0.0 + strip-ansi: 3.0.1 + supports-color: 2.0.0 + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + change-emitter@0.1.6: {} + + char-regex@1.0.2: {} + + char-regex@2.0.2: {} + + check-types@11.2.3: {} + + chokidar@1.7.0: + dependencies: + anymatch: 1.3.2 + async-each: 1.0.6 + glob-parent: 2.0.0 + inherits: 2.0.4 + is-binary-path: 1.0.1 + is-glob: 2.0.1 + path-is-absolute: 1.0.1 + readdirp: 2.2.1 + optionalDependencies: + fsevents: 1.2.13 + transitivePeerDependencies: + - supports-color + optional: true + + chokidar@3.5.1: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.5.0 + optionalDependencies: + fsevents: 2.3.3 + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chrome-trace-event@1.0.4: {} + + ci-info@1.6.0: {} + + ci-info@2.0.0: {} + + ci-info@3.9.0: {} + + cipher-base@1.0.6: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + + cjs-module-lexer@0.6.0: {} + + cjs-module-lexer@1.4.3: {} + + clamp@1.0.1: {} + + class-utils@0.3.6: + dependencies: + arr-union: 3.1.0 + define-property: 0.2.5 + isobject: 3.0.1 + static-extend: 0.1.2 + + classnames@2.5.1: {} + + clean-css@4.2.4: + dependencies: + source-map: 0.6.1 + + clean-css@5.3.3: + dependencies: + source-map: 0.6.1 + + clean-stack@2.2.0: {} + + cli-cursor@3.1.0: + dependencies: + restore-cursor: 3.1.0 + + cli-truncate@2.1.0: + dependencies: + slice-ansi: 3.0.0 + string-width: 4.2.3 + + clipboardy@2.3.0: + dependencies: + arch: 2.2.0 + execa: 1.0.0 + is-wsl: 2.2.0 + + cliui@2.1.0: + dependencies: + center-align: 0.1.3 + right-align: 0.1.3 + wordwrap: 0.0.2 + + cliui@6.0.0: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + + cliui@7.0.4: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + co@4.6.0: {} + + coa@2.0.2: + dependencies: + '@types/q': 1.5.8 + chalk: 2.4.2 + q: 1.5.1 + + codepage@1.15.0: {} + + collect-v8-coverage@1.0.2: {} + + collection-visit@1.0.0: + dependencies: + map-visit: 1.0.0 + object-visit: 1.0.1 + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + + color@3.2.1: + dependencies: + color-convert: 1.9.3 + color-string: 1.9.1 + + colord@2.9.3: {} + + colorette@2.0.20: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@10.0.1: {} + + commander@13.1.0: {} + + commander@2.20.3: {} + + commander@4.1.1: {} + + commander@5.1.0: {} + + commander@6.2.1: {} + + commander@7.2.0: {} + + commander@8.3.0: {} + + common-tags@1.8.2: {} + + commondir@1.0.1: {} + + component-classes@1.2.6: + dependencies: + component-indexof: 0.0.3 + + component-emitter@1.3.1: {} + + component-indexof@0.0.3: {} + + compressible@2.0.18: + dependencies: + mime-db: 1.54.0 + + compression@1.8.0: + dependencies: + bytes: 3.1.2 + compressible: 2.0.18 + debug: 2.6.9 + negotiator: 0.6.4 + on-headers: 1.0.2 + safe-buffer: 5.2.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + compute-scroll-into-view@1.0.20: {} + + compute-scroll-into-view@3.1.1: {} + + concat-map@0.0.1: {} + + confusing-browser-globals@1.0.11: {} + + connect-history-api-fallback@2.0.0: {} + + connected-react-router@6.5.2(history@4.10.1)(react-redux@7.2.9(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0)(redux@4.2.1): + dependencies: + history: 4.10.1 + immutable: 3.8.2 + prop-types: 15.8.1 + react: 16.14.0 + react-redux: 7.2.9(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react-router: 5.2.0(react@16.14.0) + redux: 4.2.1 + seamless-immutable: 7.1.4 + + console-browserify@1.2.0: {} + + constants-browserify@1.0.0: {} + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + contour_plot@0.0.1: {} + + convert-source-map@1.9.0: {} + + convert-source-map@2.0.0: {} + + cookie-signature@1.0.6: {} + + cookie@0.7.1: {} + + copy-descriptor@0.1.1: {} + + copy-to-clipboard@3.3.3: + dependencies: + toggle-selection: 1.0.6 + + core-js-compat@3.41.0: + dependencies: + browserslist: 4.24.4 + + core-js-pure@3.41.0: {} + + core-js@1.2.7: {} + + core-js@2.6.12: {} + + core-js@3.41.0: {} + + core-js@3.6.5: {} + + core-js@3.8.2: {} + + core-util-is@1.0.3: {} + + cosmiconfig@5.2.1: + dependencies: + import-fresh: 2.0.0 + is-directory: 0.3.1 + js-yaml: 3.14.1 + parse-json: 4.0.0 + + cosmiconfig@6.0.0: + dependencies: + '@types/parse-json': 4.0.2 + import-fresh: 3.3.1 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + + cosmiconfig@7.1.0: + dependencies: + '@types/parse-json': 4.0.2 + import-fresh: 3.3.1 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + + cosmiconfig@9.0.0(typescript@4.9.5): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + parse-json: 5.2.0 + optionalDependencies: + typescript: 4.9.5 + + cp-file@7.0.0: + dependencies: + graceful-fs: 4.2.11 + make-dir: 3.1.0 + nested-error-stacks: 2.1.1 + p-event: 4.2.0 + + cpy@8.1.2: + dependencies: + arrify: 2.0.1 + cp-file: 7.0.0 + globby: 9.2.0 + has-glob: 1.0.0 + junk: 3.1.0 + nested-error-stacks: 2.1.1 + p-all: 2.1.0 + p-filter: 2.1.0 + p-map: 3.0.0 + transitivePeerDependencies: + - supports-color + + crc-32@1.2.2: {} + + create-ecdh@4.0.4: + dependencies: + bn.js: 4.12.2 + elliptic: 6.6.1 + + create-hash@1.2.0: + dependencies: + cipher-base: 1.0.6 + inherits: 2.0.4 + md5.js: 1.3.5 + ripemd160: 2.0.2 + sha.js: 2.4.11 + + create-hmac@1.1.7: + dependencies: + cipher-base: 1.0.6 + create-hash: 1.2.0 + inherits: 2.0.4 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.11 + + create-react-class@15.7.0: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + + create-require@1.1.1: {} + + cross-fetch@3.2.0(encoding@0.1.13): + dependencies: + node-fetch: 2.7.0(encoding@0.1.13) + transitivePeerDependencies: + - encoding + + cross-spawn@5.1.0: + dependencies: + lru-cache: 4.1.5 + shebang-command: 1.2.0 + which: 1.3.1 + + cross-spawn@6.0.6: + dependencies: + nice-try: 1.0.5 + path-key: 2.0.1 + semver: 5.7.2 + shebang-command: 1.2.0 + which: 1.3.1 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + crypto-browserify@3.12.1: + dependencies: + browserify-cipher: 1.0.1 + browserify-sign: 4.2.3 + create-ecdh: 4.0.4 + create-hash: 1.2.0 + create-hmac: 1.1.7 + diffie-hellman: 5.0.3 + hash-base: 3.0.5 + inherits: 2.0.4 + pbkdf2: 3.1.2 + public-encrypt: 4.0.3 + randombytes: 2.1.0 + randomfill: 1.0.4 + + crypto-js@4.2.0: {} + + crypto-random-string@2.0.0: {} + + crypto-random-string@5.0.0: + dependencies: + type-fest: 2.19.0 + + css-animation@1.6.1: + dependencies: + babel-runtime: 6.26.0 + component-classes: 1.2.6 + + css-blank-pseudo@0.1.4: + dependencies: + postcss: 7.0.32 + + css-blank-pseudo@3.0.3(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + css-box-model@1.2.1: + dependencies: + tiny-invariant: 1.3.3 + + css-declaration-sorter@6.4.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + css-has-pseudo@0.10.0: + dependencies: + postcss: 7.0.32 + postcss-selector-parser: 5.0.0 + + css-has-pseudo@3.0.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + css-in-js-utils@3.1.0: + dependencies: + hyphenate-style-name: 1.1.0 + + css-loader@6.11.0(webpack@5.99.7): + dependencies: + icss-utils: 5.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-modules-extract-imports: 3.1.0(postcss@8.5.3) + postcss-modules-local-by-default: 4.2.0(postcss@8.5.3) + postcss-modules-scope: 3.2.1(postcss@8.5.3) + postcss-modules-values: 4.0.0(postcss@8.5.3) + postcss-value-parser: 4.2.0 + semver: 7.7.1 + optionalDependencies: + webpack: 5.99.7 + + css-minimizer-webpack-plugin@3.4.1(webpack@5.99.7): + dependencies: + cssnano: 5.1.15(postcss@8.5.3) + jest-worker: 27.5.1 + postcss: 8.5.3 + schema-utils: 4.3.2 + serialize-javascript: 6.0.2 + source-map: 0.6.1 + webpack: 5.99.7 + + css-prefers-color-scheme@3.1.1: + dependencies: + postcss: 7.0.32 + + css-prefers-color-scheme@6.0.3(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + css-select-base-adapter@0.1.1: {} + + css-select@2.1.0: + dependencies: + boolbase: 1.0.0 + css-what: 3.4.2 + domutils: 1.7.0 + nth-check: 1.0.2 + + css-select@4.3.0: + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 4.3.1 + domutils: 2.8.0 + nth-check: 2.1.1 + + css-tree@1.0.0-alpha.37: + dependencies: + mdn-data: 2.0.4 + source-map: 0.6.1 + + css-tree@1.1.3: + dependencies: + mdn-data: 2.0.14 + source-map: 0.6.1 + + css-what@3.4.2: {} + + css-what@6.1.0: {} + + csscolorparser@1.0.3: {} + + cssdb@4.4.0: {} + + cssdb@7.11.2: {} + + cssesc@2.0.0: {} + + cssesc@3.0.0: {} + + cssnano-preset-default@5.2.14(postcss@8.5.3): + dependencies: + css-declaration-sorter: 6.4.1(postcss@8.5.3) + cssnano-utils: 3.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-calc: 8.2.4(postcss@8.5.3) + postcss-colormin: 5.3.1(postcss@8.5.3) + postcss-convert-values: 5.1.3(postcss@8.5.3) + postcss-discard-comments: 5.1.2(postcss@8.5.3) + postcss-discard-duplicates: 5.1.0(postcss@8.5.3) + postcss-discard-empty: 5.1.1(postcss@8.5.3) + postcss-discard-overridden: 5.1.0(postcss@8.5.3) + postcss-merge-longhand: 5.1.7(postcss@8.5.3) + postcss-merge-rules: 5.1.4(postcss@8.5.3) + postcss-minify-font-values: 5.1.0(postcss@8.5.3) + postcss-minify-gradients: 5.1.1(postcss@8.5.3) + postcss-minify-params: 5.1.4(postcss@8.5.3) + postcss-minify-selectors: 5.2.1(postcss@8.5.3) + postcss-normalize-charset: 5.1.0(postcss@8.5.3) + postcss-normalize-display-values: 5.1.0(postcss@8.5.3) + postcss-normalize-positions: 5.1.1(postcss@8.5.3) + postcss-normalize-repeat-style: 5.1.1(postcss@8.5.3) + postcss-normalize-string: 5.1.0(postcss@8.5.3) + postcss-normalize-timing-functions: 5.1.0(postcss@8.5.3) + postcss-normalize-unicode: 5.1.1(postcss@8.5.3) + postcss-normalize-url: 5.1.0(postcss@8.5.3) + postcss-normalize-whitespace: 5.1.1(postcss@8.5.3) + postcss-ordered-values: 5.1.3(postcss@8.5.3) + postcss-reduce-initial: 5.1.2(postcss@8.5.3) + postcss-reduce-transforms: 5.1.0(postcss@8.5.3) + postcss-svgo: 5.1.0(postcss@8.5.3) + postcss-unique-selectors: 5.1.1(postcss@8.5.3) + + cssnano-utils@3.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + cssnano@5.1.15(postcss@8.5.3): + dependencies: + cssnano-preset-default: 5.2.14(postcss@8.5.3) + lilconfig: 2.1.0 + postcss: 8.5.3 + yaml: 1.10.2 + + csso@4.2.0: + dependencies: + css-tree: 1.1.3 + + cssom@0.3.8: {} + + cssom@0.4.4: {} + + cssstyle@2.3.0: + dependencies: + cssom: 0.3.8 + + csstype@3.1.3: {} + + d3-array@1.2.4: {} + + d3-array@2.12.1: + dependencies: + internmap: 1.0.1 + + d3-collection@1.0.7: {} + + d3-color@1.4.1: {} + + d3-color@3.1.0: {} + + d3-dispatch@2.0.0: {} + + d3-dsv@1.2.0: + dependencies: + commander: 2.20.3 + iconv-lite: 0.4.24 + rw: 1.3.3 + + d3-ease@1.0.7: {} + + d3-force@2.1.1: + dependencies: + d3-dispatch: 2.0.0 + d3-quadtree: 2.0.0 + d3-timer: 2.0.0 + + d3-format@1.4.5: {} + + d3-hexbin@0.2.2: {} + + d3-hierarchy@2.0.0: {} + + d3-interpolate@1.4.0: + dependencies: + d3-color: 1.4.1 + + d3-interpolate@3.0.1: + dependencies: + d3-color: 3.1.0 + + d3-quadtree@2.0.0: {} + + d3-regression@1.3.10: {} + + d3-scale@2.2.2: + dependencies: + d3-array: 1.2.4 + d3-collection: 1.0.7 + d3-format: 1.4.5 + d3-interpolate: 1.4.0 + d3-time: 1.1.0 + d3-time-format: 2.3.0 + + d3-time-format@2.3.0: + dependencies: + d3-time: 1.1.0 + + d3-time@1.1.0: {} + + d3-timer@1.0.10: {} + + d3-timer@2.0.0: {} + + d@1.0.2: + dependencies: + es5-ext: 0.10.64 + type: 2.7.3 + + dagre-compound@0.0.11(dagre@0.8.5): + dependencies: + dagre: 0.8.5 + + dagre@0.8.5: + dependencies: + graphlib: 2.1.8 + lodash: 4.17.21 + + damerau-levenshtein@1.0.8: {} + + data-urls@2.0.0: + dependencies: + abab: 2.0.6 + whatwg-mimetype: 2.3.0 + whatwg-url: 8.7.0 + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + date-fns@2.30.0: + dependencies: + '@babel/runtime': 7.27.0 + + dayjs@1.11.13: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@3.2.7: + dependencies: + ms: 2.1.3 + + debug@4.4.0: + dependencies: + ms: 2.1.3 + + decamelize@1.2.0: {} + + decimal.js@10.5.0: {} + + decode-uri-component@0.2.2: {} + + decode-uri-component@0.4.1: {} + + dedent@0.7.0: {} + + deep-equal@1.1.2: + dependencies: + is-arguments: 1.2.0 + is-date-object: 1.1.0 + is-regex: 1.1.4 + object-is: 1.1.6 + object-keys: 1.1.1 + regexp.prototype.flags: 1.5.4 + + deep-is@0.1.4: {} + + deepmerge@1.5.2: {} + + deepmerge@4.3.1: {} + + default-gateway@6.0.3: + dependencies: + execa: 5.1.1 + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-lazy-prop@2.0.0: {} + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + define-property@0.2.5: + dependencies: + is-descriptor: 0.1.7 + + define-property@1.0.0: + dependencies: + is-descriptor: 1.0.3 + + define-property@2.0.2: + dependencies: + is-descriptor: 1.0.3 + isobject: 3.0.1 + + defined@1.0.1: {} + + delayed-stream@1.0.0: {} + + depd@1.1.2: {} + + depd@2.0.0: {} + + dequal@2.0.3: {} + + des.js@1.1.0: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + + destroy@1.2.0: {} + + detect-browser@4.8.0: {} + + detect-browser@5.3.0: {} + + detect-indent@4.0.0: + dependencies: + repeating: 2.0.1 + + detect-newline@3.1.0: {} + + detect-node@2.1.0: {} + + detect-port-alt@1.1.6: + dependencies: + address: 1.2.2 + debug: 2.6.9 + transitivePeerDependencies: + - supports-color + + didyoumean@1.2.2: {} + + diff-sequences@26.6.2: {} + + diff-sequences@27.5.1: {} + + diff@4.0.2: {} + + diff@5.2.0: {} + + diffie-hellman@5.0.3: + dependencies: + bn.js: 4.12.2 + miller-rabin: 4.0.1 + randombytes: 2.1.0 + + dir-glob@2.2.2: + dependencies: + path-type: 3.0.0 + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dlv@1.1.3: {} + + dns-packet@5.6.1: + dependencies: + '@leichtgewicht/ip-codec': 2.0.5 + + doctrine@2.1.0: + dependencies: + esutils: 2.0.3 + + dom-align@1.12.4: {} + + dom-converter@0.2.0: + dependencies: + utila: 0.4.0 + + dom-scroll-into-view@1.2.1: {} + + dom-serializer@0.2.2: + dependencies: + domelementtype: 2.3.0 + entities: 2.2.0 + + dom-serializer@1.4.1: + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + + dom-walk@0.1.2: {} + + domain-browser@1.2.0: {} + + domelementtype@1.3.1: {} + + domelementtype@2.3.0: {} + + domexception@2.0.1: + dependencies: + webidl-conversions: 5.0.0 + + domhandler@4.3.1: + dependencies: + domelementtype: 2.3.0 + + domutils@1.7.0: + dependencies: + dom-serializer: 0.2.2 + domelementtype: 1.3.1 + + domutils@2.8.0: + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + + dot-case@3.0.4: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + + dotenv-expand@5.1.0: {} + + dotenv@10.0.0: {} + + dotenv@16.5.0: {} + + dotignore@0.1.2: + dependencies: + minimatch: 3.1.2 + + draft-js@0.10.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + fbjs: 0.8.18 + immutable: 3.7.6 + object-assign: 4.1.1 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + drange@1.1.1: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + duplexer@0.1.2: {} + + dva-core@2.0.4(redux@4.2.1): + dependencies: + '@babel/runtime': 7.27.0 + flatten: 1.0.3 + global: 4.4.0 + invariant: 2.2.4 + is-plain-object: 2.0.4 + redux: 4.2.1 + redux-saga: 0.16.2 + warning: 3.0.0 + + dva-immer@0.5.2(dva@2.6.0-beta.23(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0)): + dependencies: + '@babel/runtime': 7.27.0 + dva: 2.6.0-beta.23(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0) + immer: 7.0.15 + + dva-loading@3.0.25(dva-core@2.0.4(redux@4.2.1)): + dependencies: + '@babel/runtime': 7.27.0 + dva-core: 2.0.4(redux@4.2.1) + + dva@2.6.0-beta.23(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + '@types/isomorphic-fetch': 0.0.35 + '@types/react-redux': 7.1.34 + '@types/react-router-dom': 5.3.3 + connected-react-router: 6.5.2(history@4.10.1)(react-redux@7.2.9(react-dom@16.14.0(react@16.14.0))(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0)(redux@4.2.1) + dva-core: 2.0.4(redux@4.2.1) + global: 4.4.0 + history: 4.10.1 + invariant: 2.2.4 + isomorphic-fetch: 2.2.1 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + react-redux: 7.2.9(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react-router-dom: 5.3.4(react@16.14.0) + redux: 4.2.1 + transitivePeerDependencies: + - react-native + - react-router + + earcut@2.2.4: {} + + eastasianwidth@0.2.0: {} + + ee-first@1.1.1: {} + + ejs@3.1.10: + dependencies: + jake: 10.9.2 + + electron-to-chromium@1.5.143: {} + + element-resize-detector@1.2.4: + dependencies: + batch-processor: 1.0.0 + + elliptic@6.6.1: + dependencies: + bn.js: 4.12.2 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + + emittery@0.10.2: {} + + emittery@0.7.2: {} + + emittery@0.8.1: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + emojis-list@3.0.0: {} + + encodeurl@1.0.2: {} + + encodeurl@2.0.0: {} + + encoding@0.1.13: + dependencies: + iconv-lite: 0.6.3 + + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + + enhanced-resolve@5.18.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + + enquirer@2.4.1: + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + + entities@2.2.0: {} + + env-paths@2.2.1: {} + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + error-stack-parser@1.3.6: + dependencies: + stackframe: 0.3.1 + + error-stack-parser@2.1.4: + dependencies: + stackframe: 1.3.4 + + es-abstract@1.23.9: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-regex: 1.2.1 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.3 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.7 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.19 + + es-array-method-boxes-properly@1.0.0: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-iterator-helpers@1.2.1: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-set-tostringtag: 2.1.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + iterator.prototype: 1.1.5 + safe-array-concat: 1.1.3 + + es-module-lexer@0.7.1: {} + + es-module-lexer@1.7.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es-shim-unscopables@1.1.0: + dependencies: + hasown: 2.0.2 + + es-to-primitive@1.3.0: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + es5-ext@0.10.64: + dependencies: + es6-iterator: 2.0.3 + es6-symbol: 3.1.4 + esniff: 2.0.1 + next-tick: 1.1.0 + + es5-imcompatible-versions@0.1.90: {} + + es6-iterator@2.0.3: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-symbol: 3.1.4 + + es6-promise@3.3.1: {} + + es6-symbol@3.1.4: + dependencies: + d: 1.0.2 + ext: 1.7.0 + + es6-weak-map@2.0.3: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-iterator: 2.0.3 + es6-symbol: 3.1.4 + + esbuild@0.12.15: {} + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@2.0.0: {} + + escape-string-regexp@4.0.0: {} + + escodegen@1.14.3: + dependencies: + esprima: 4.0.1 + estraverse: 4.3.0 + esutils: 2.0.3 + optionator: 0.8.3 + optionalDependencies: + source-map: 0.6.1 + + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + + eslint-config-react-app@7.0.1(@babel/plugin-syntax-flow@7.26.0(@babel/core@7.26.10))(@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.10))(eslint@9.25.1(jiti@1.21.7))(jest@27.5.1(node-notifier@8.0.2)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)))(typescript@4.9.5): + dependencies: + '@babel/core': 7.26.10 + '@babel/eslint-parser': 7.27.0(@babel/core@7.26.10)(eslint@9.25.1(jiti@1.21.7)) + '@rushstack/eslint-patch': 1.11.0 + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5))(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5) + '@typescript-eslint/parser': 5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5) + babel-preset-react-app: 10.1.0 + confusing-browser-globals: 1.0.11 + eslint: 9.25.1(jiti@1.21.7) + eslint-plugin-flowtype: 8.0.3(@babel/plugin-syntax-flow@7.26.0(@babel/core@7.26.10))(@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.10))(eslint@9.25.1(jiti@1.21.7)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5))(eslint@9.25.1(jiti@1.21.7)) + eslint-plugin-jest: 25.7.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5))(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5))(eslint@9.25.1(jiti@1.21.7))(jest@27.5.1(node-notifier@8.0.2)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)))(typescript@4.9.5) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.25.1(jiti@1.21.7)) + eslint-plugin-react: 7.37.5(eslint@9.25.1(jiti@1.21.7)) + eslint-plugin-react-hooks: 4.6.2(eslint@9.25.1(jiti@1.21.7)) + eslint-plugin-testing-library: 5.11.1(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5) + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - '@babel/plugin-syntax-flow' + - '@babel/plugin-transform-react-jsx' + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - jest + - supports-color + + eslint-import-resolver-node@0.3.9: + dependencies: + debug: 3.2.7 + is-core-module: 2.16.1 + resolve: 1.22.10 + transitivePeerDependencies: + - supports-color + + eslint-module-utils@2.12.0(@typescript-eslint/parser@5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint@9.25.1(jiti@1.21.7)): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5) + eslint: 9.25.1(jiti@1.21.7) + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + + eslint-plugin-flowtype@8.0.3(@babel/plugin-syntax-flow@7.26.0(@babel/core@7.26.10))(@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.10))(eslint@9.25.1(jiti@1.21.7)): + dependencies: + '@babel/plugin-syntax-flow': 7.26.0(@babel/core@7.26.10) + '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.10) + eslint: 9.25.1(jiti@1.21.7) + lodash: 4.17.21 + string-natural-compare: 3.0.1 + + eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5))(eslint@9.25.1(jiti@1.21.7)): + dependencies: + '@rtsao/scc': 1.1.0 + array-includes: 3.1.8 + array.prototype.findlastindex: 1.2.6 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 9.25.1(jiti@1.21.7) + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint@9.25.1(jiti@1.21.7)) + hasown: 2.0.2 + is-core-module: 2.16.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + string.prototype.trimend: 1.0.9 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + + eslint-plugin-jest@25.7.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5))(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5))(eslint@9.25.1(jiti@1.21.7))(jest@27.5.1(node-notifier@8.0.2)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)))(typescript@4.9.5): + dependencies: + '@typescript-eslint/experimental-utils': 5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5) + eslint: 9.25.1(jiti@1.21.7) + optionalDependencies: + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5))(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5) + jest: 27.5.1(node-notifier@8.0.2)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + transitivePeerDependencies: + - supports-color + - typescript + + eslint-plugin-jsx-a11y@6.10.2(eslint@9.25.1(jiti@1.21.7)): + dependencies: + aria-query: 5.3.2 + array-includes: 3.1.8 + array.prototype.flatmap: 1.3.3 + ast-types-flow: 0.0.8 + axe-core: 4.10.3 + axobject-query: 4.1.0 + damerau-levenshtein: 1.0.8 + emoji-regex: 9.2.2 + eslint: 9.25.1(jiti@1.21.7) + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + language-tags: 1.0.9 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + safe-regex-test: 1.1.0 + string.prototype.includes: 2.0.1 + + eslint-plugin-react-hooks@4.6.2(eslint@9.25.1(jiti@1.21.7)): + dependencies: + eslint: 9.25.1(jiti@1.21.7) + + eslint-plugin-react@7.37.5(eslint@9.25.1(jiti@1.21.7)): + dependencies: + array-includes: 3.1.8 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.3 + array.prototype.tosorted: 1.1.4 + doctrine: 2.1.0 + es-iterator-helpers: 1.2.1 + eslint: 9.25.1(jiti@1.21.7) + estraverse: 5.3.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.9 + object.fromentries: 2.0.8 + object.values: 1.2.1 + prop-types: 15.8.1 + resolve: 2.0.0-next.5 + semver: 6.3.1 + string.prototype.matchall: 4.0.12 + string.prototype.repeat: 1.0.0 + + eslint-plugin-testing-library@5.11.1(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5): + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5) + eslint: 9.25.1(jiti@1.21.7) + transitivePeerDependencies: + - supports-color + - typescript + + eslint-scope@5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + + eslint-scope@8.3.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@2.1.0: {} + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.0: {} + + eslint-webpack-plugin@3.2.0(eslint@9.25.1(jiti@1.21.7))(webpack@5.99.7): + dependencies: + '@types/eslint': 8.56.12 + eslint: 9.25.1(jiti@1.21.7) + jest-worker: 28.1.3 + micromatch: 4.0.8 + normalize-path: 3.0.0 + schema-utils: 4.3.2 + webpack: 5.99.7 + + eslint@9.25.1(jiti@1.21.7): + dependencies: + '@eslint-community/eslint-utils': 4.6.1(eslint@9.25.1(jiti@1.21.7)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.20.0 + '@eslint/config-helpers': 0.2.1 + '@eslint/core': 0.13.0 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.25.1 + '@eslint/plugin-kit': 0.2.8 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.2 + '@types/estree': 1.0.7 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.0 + escape-string-regexp: 4.0.0 + eslint-scope: 8.3.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 1.21.7 + transitivePeerDependencies: + - supports-color + + esniff@2.0.1: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + event-emitter: 0.3.5 + type: 2.7.3 + + espree@10.3.0: + dependencies: + acorn: 8.14.1 + acorn-jsx: 5.3.2(acorn@8.14.1) + eslint-visitor-keys: 4.2.0 + + esprima@1.2.2: {} + + esprima@4.0.1: {} + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@4.3.0: {} + + estraverse@5.3.0: {} + + estree-walker@1.0.1: {} + + esutils@2.0.3: {} + + etag@1.8.1: {} + + event-emitter@0.3.5: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + + eventemitter3@4.0.7: {} + + eventemitter3@5.0.1: {} + + events@3.3.0: {} + + evp_bytestokey@1.0.3: + dependencies: + md5.js: 1.3.5 + safe-buffer: 5.2.1 + + exec-sh@0.3.6: {} + + execa@0.8.0: + dependencies: + cross-spawn: 5.1.0 + get-stream: 3.0.0 + is-stream: 1.1.0 + npm-run-path: 2.0.2 + p-finally: 1.0.0 + signal-exit: 3.0.7 + strip-eof: 1.0.0 + + execa@1.0.0: + dependencies: + cross-spawn: 6.0.6 + get-stream: 4.1.0 + is-stream: 1.1.0 + npm-run-path: 2.0.2 + p-finally: 1.0.0 + signal-exit: 3.0.7 + strip-eof: 1.0.0 + + execa@4.1.0: + dependencies: + cross-spawn: 7.0.6 + get-stream: 5.2.0 + human-signals: 1.1.1 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + exenv@1.2.2: {} + + exit-on-epipe@1.0.1: {} + + exit@0.1.2: {} + + expand-brackets@0.1.5: + dependencies: + is-posix-bracket: 0.1.1 + optional: true + + expand-brackets@2.1.4: + dependencies: + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + posix-character-classes: 0.1.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + expand-range@1.8.2: + dependencies: + fill-range: 2.2.4 + optional: true + + expect@26.6.2: + dependencies: + '@jest/types': 26.6.2 + ansi-styles: 4.3.0 + jest-get-type: 26.3.0 + jest-matcher-utils: 26.6.2 + jest-message-util: 26.6.2 + jest-regex-util: 26.0.0 + + expect@27.5.1: + dependencies: + '@jest/types': 27.5.1 + jest-get-type: 27.5.1 + jest-matcher-utils: 27.5.1 + jest-message-util: 27.5.1 + + express@4.21.2: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.3 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.1 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.1 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.12 + proxy-addr: 2.0.7 + qs: 6.13.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.0 + serve-static: 1.16.2 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + ext@1.7.0: + dependencies: + type: 2.7.3 + + extend-shallow@2.0.1: + dependencies: + is-extendable: 0.1.1 + + extend-shallow@3.0.2: + dependencies: + assign-symbols: 1.0.0 + is-extendable: 1.0.1 + + extglob@0.3.2: + dependencies: + is-extglob: 1.0.0 + optional: true + + extglob@2.0.4: + dependencies: + array-unique: 0.3.2 + define-property: 1.0.0 + expand-brackets: 2.1.4 + extend-shallow: 2.0.1 + fragment-cache: 0.2.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + extrude-polyline@1.0.6: + dependencies: + as-number: 1.0.0 + gl-vec2: 1.3.0 + polyline-miter-util: 1.0.1 + + fast-deep-equal@3.1.1: {} + + fast-deep-equal@3.1.3: {} + + fast-glob@2.2.7: + dependencies: + '@mrmlnc/readdir-enhanced': 2.2.1 + '@nodelib/fs.stat': 1.1.3 + glob-parent: 3.1.0 + is-glob: 4.0.3 + merge2: 1.4.1 + micromatch: 3.1.10 + transitivePeerDependencies: + - supports-color + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-safe-stringify@2.1.1: {} + + fast-shallow-equal@1.0.0: {} + + fast-uri@3.0.6: {} + + fastest-stable-stringify@2.0.2: {} + + fastq@1.19.1: + dependencies: + reusify: 1.1.0 + + faye-websocket@0.11.4: + dependencies: + websocket-driver: 0.7.4 + + fb-watchman@2.0.2: + dependencies: + bser: 2.1.1 + + fbemitter@3.0.0(encoding@0.1.13): + dependencies: + fbjs: 3.0.5(encoding@0.1.13) + transitivePeerDependencies: + - encoding + + fbjs-css-vars@1.0.2: {} + + fbjs@0.8.18: + dependencies: + core-js: 1.2.7 + isomorphic-fetch: 2.2.1 + loose-envify: 1.4.0 + object-assign: 4.1.1 + promise: 7.3.1 + setimmediate: 1.0.5 + ua-parser-js: 0.7.40 + + fbjs@3.0.5(encoding@0.1.13): + dependencies: + cross-fetch: 3.2.0(encoding@0.1.13) + fbjs-css-vars: 1.0.2 + loose-envify: 1.4.0 + object-assign: 4.1.1 + promise: 7.3.1 + setimmediate: 1.0.5 + ua-parser-js: 1.0.40 + transitivePeerDependencies: + - encoding + + fecha@4.2.3: {} + + fflate@0.8.2: {} + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + file-loader@6.2.0(webpack@5.99.7): + dependencies: + loader-utils: 2.0.4 + schema-utils: 3.3.0 + webpack: 5.99.7 + + file-saver@2.0.5: {} + + file-uri-to-path@1.0.0: + optional: true + + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + + filename-regex@2.0.1: + optional: true + + filesize@10.1.6: {} + + filesize@8.0.7: {} + + fill-range@2.2.4: + dependencies: + is-number: 2.1.0 + isobject: 2.1.0 + randomatic: 3.1.1 + repeat-element: 1.1.4 + repeat-string: 1.6.1 + optional: true + + fill-range@4.0.0: + dependencies: + extend-shallow: 2.0.1 + is-number: 3.0.0 + repeat-string: 1.6.1 + to-regex-range: 2.1.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + filter-obj@1.1.0: {} + + filter-obj@5.1.0: {} + + finalhandler@1.3.1: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + find-cache-dir@3.3.2: + dependencies: + commondir: 1.0.1 + make-dir: 3.1.0 + pkg-dir: 4.2.0 + + find-root@1.1.0: {} + + find-up@3.0.0: + dependencies: + locate-path: 3.0.0 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flatted@3.3.3: {} + + flatten@1.0.3: {} + + flux@4.0.4(encoding@0.1.13)(react@16.14.0): + dependencies: + fbemitter: 3.0.0(encoding@0.1.13) + fbjs: 3.0.5(encoding@0.1.13) + react: 16.14.0 + transitivePeerDependencies: + - encoding + + fmin@0.0.2: + dependencies: + contour_plot: 0.0.1 + json2module: 0.0.3 + rollup: 0.25.8 + tape: 4.17.0 + uglify-js: 2.8.29 + + follow-redirects@1.15.9: {} + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + for-in@1.0.2: {} + + for-own@0.1.5: + dependencies: + for-in: 1.0.2 + optional: true + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + fork-ts-checker-webpack-plugin@6.5.3(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5)(webpack@5.99.7): + dependencies: + '@babel/code-frame': 7.26.2 + '@types/json-schema': 7.0.15 + chalk: 4.1.2 + chokidar: 3.6.0 + cosmiconfig: 6.0.0 + deepmerge: 4.3.1 + fs-extra: 9.1.0 + glob: 7.2.3 + memfs: 3.5.3 + minimatch: 3.1.2 + schema-utils: 2.7.0 + semver: 7.7.1 + tapable: 1.1.3 + typescript: 4.9.5 + webpack: 5.99.7 + optionalDependencies: + eslint: 9.25.1(jiti@1.21.7) + + form-data@3.0.3: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + mime-types: 2.1.35 + + form-data@4.0.2: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + mime-types: 2.1.35 + + forwarded@0.2.0: {} + + frac@1.1.2: {} + + fraction.js@4.3.7: {} + + fragment-cache@0.2.1: + dependencies: + map-cache: 0.2.2 + + fresh@0.5.2: {} + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-extra@9.1.0: + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-monkey@1.0.6: {} + + fs-readdir-recursive@1.1.0: {} + + fs.realpath@1.0.0: {} + + fsevents@1.2.13: + dependencies: + bindings: 1.5.0 + nan: 2.22.2 + optional: true + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.1.8: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 + + functions-have-names@1.2.3: {} + + gensync@1.0.0-beta.2: {} + + geojson-vt@3.2.1: {} + + get-caller-file@2.0.5: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-own-enumerable-property-symbols@3.0.2: {} + + get-package-type@0.1.0: {} + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-stream@3.0.0: {} + + get-stream@4.1.0: + dependencies: + pump: 3.0.2 + + get-stream@5.2.0: + dependencies: + pump: 3.0.2 + + get-stream@6.0.1: {} + + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + + get-value@2.0.6: {} + + gl-matrix@3.4.3: {} + + gl-vec2@1.3.0: {} + + glob-base@0.3.0: + dependencies: + glob-parent: 2.0.0 + is-glob: 2.0.1 + optional: true + + glob-parent@2.0.0: + dependencies: + is-glob: 2.0.1 + optional: true + + glob-parent@3.1.0: + dependencies: + is-glob: 3.1.0 + path-dirname: 1.0.2 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob-to-regexp@0.3.0: {} + + glob-to-regexp@0.4.1: {} + + glob@10.4.5: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + global-modules@2.0.0: + dependencies: + global-prefix: 3.0.0 + + global-prefix@3.0.0: + dependencies: + ini: 1.3.8 + kind-of: 6.0.3 + which: 1.3.1 + + global@4.4.0: + dependencies: + min-document: 2.19.0 + process: 0.11.10 + + globals@11.12.0: {} + + globals@14.0.0: {} + + globals@9.18.0: {} + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + globby@9.2.0: + dependencies: + '@types/glob': 7.2.0 + array-union: 1.0.2 + dir-glob: 2.2.2 + fast-glob: 2.2.7 + glob: 7.2.3 + ignore: 4.0.6 + pify: 4.0.1 + slash: 2.0.0 + transitivePeerDependencies: + - supports-color + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + graphlib@2.1.8: + dependencies: + lodash: 4.17.21 + + grid-index@1.1.0: {} + + growly@1.3.0: + optional: true + + gzip-size@6.0.0: + dependencies: + duplexer: 0.1.2 + + hammerjs@2.0.8: {} + + handle-thing@2.0.1: {} + + harmony-reflect@1.6.2: {} + + has-ansi@2.0.0: + dependencies: + ansi-regex: 2.1.1 + + has-bigints@1.1.0: {} + + has-flag@1.0.0: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + has-glob@1.0.0: + dependencies: + is-glob: 3.1.0 + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + has-value@0.3.1: + dependencies: + get-value: 2.0.6 + has-values: 0.1.4 + isobject: 2.1.0 + + has-value@1.0.0: + dependencies: + get-value: 2.0.6 + has-values: 1.0.0 + isobject: 3.0.1 + + has-values@0.1.4: {} + + has-values@1.0.0: + dependencies: + is-number: 3.0.0 + kind-of: 4.0.0 + + has@1.0.4: {} + + hash-base@3.0.5: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + + hash.js@1.1.7: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + he@1.2.0: {} + + highlight.js@11.11.1: {} + + highlightjs-solidity@2.0.6: {} + + history-with-query@4.10.4: + dependencies: + '@babel/runtime': 7.27.0 + loose-envify: 1.4.0 + query-string: 6.14.1 + resolve-pathname: 3.0.0 + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + value-equal: 1.0.1 + + history@4.10.1: + dependencies: + '@babel/runtime': 7.27.0 + loose-envify: 1.4.0 + resolve-pathname: 3.0.0 + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + value-equal: 1.0.1 + + history@5.3.0: + dependencies: + '@babel/runtime': 7.27.0 + + hmac-drbg@1.0.1: + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + + hoist-non-react-statics@1.2.0: {} + + hoist-non-react-statics@3.3.2: + dependencies: + react-is: 16.13.1 + + home-or-tmp@2.0.0: + dependencies: + os-homedir: 1.0.2 + os-tmpdir: 1.0.2 + + hoopy@0.1.4: {} + + hosted-git-info@2.8.9: {} + + hpack.js@2.1.6: + dependencies: + inherits: 2.0.4 + obuf: 1.1.2 + readable-stream: 2.3.8 + wbuf: 1.7.3 + + html-encoding-sniffer@2.0.1: + dependencies: + whatwg-encoding: 1.0.5 + + html-entities@2.6.0: {} + + html-escaper@2.0.2: {} + + html-minifier-terser@5.1.1: + dependencies: + camel-case: 4.1.2 + clean-css: 4.2.4 + commander: 4.1.1 + he: 1.2.0 + param-case: 3.0.4 + relateurl: 0.2.7 + terser: 4.8.1 + + html-minifier-terser@6.1.0: + dependencies: + camel-case: 4.1.2 + clean-css: 5.3.3 + commander: 8.3.0 + he: 1.2.0 + param-case: 3.0.4 + relateurl: 0.2.7 + terser: 5.39.0 + + html-webpack-plugin@4.5.2(webpack@5.99.7): + dependencies: + '@types/html-minifier-terser': 5.1.2 + '@types/tapable': 1.0.12 + '@types/webpack': 4.41.40 + html-minifier-terser: 5.1.1 + loader-utils: 1.4.2 + lodash: 4.17.21 + pretty-error: 2.1.2 + tapable: 1.1.3 + util.promisify: 1.0.0 + webpack: 5.99.7 + + html-webpack-plugin@5.6.3(webpack@5.99.7): + dependencies: + '@types/html-minifier-terser': 6.1.0 + html-minifier-terser: 6.1.0 + lodash: 4.17.21 + pretty-error: 4.0.0 + tapable: 2.2.1 + optionalDependencies: + webpack: 5.99.7 + + htmlparser2@6.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + domutils: 2.8.0 + entities: 2.2.0 + + http-deceiver@1.2.7: {} + + http-errors@1.6.3: + dependencies: + depd: 1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.0 + statuses: 1.5.0 + + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + + http-parser-js@0.5.10: {} + + http-proxy-agent@4.0.1: + dependencies: + '@tootallnate/once': 1.1.2 + agent-base: 6.0.2 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + + http-proxy-middleware@2.0.9(@types/express@4.17.21): + dependencies: + '@types/http-proxy': 1.17.16 + http-proxy: 1.18.1 + is-glob: 4.0.3 + is-plain-obj: 3.0.0 + micromatch: 4.0.8 + optionalDependencies: + '@types/express': 4.17.21 + transitivePeerDependencies: + - debug + + http-proxy@1.18.1: + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.15.9 + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + + http2-client@1.3.5: {} + + https-browserify@1.0.0: {} + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + + human-signals@1.1.1: {} + + human-signals@2.1.0: {} + + hyphenate-style-name@1.1.0: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + icss-utils@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + idb@7.1.1: {} + + identity-obj-proxy@3.0.0: + dependencies: + harmony-reflect: 1.6.2 + + ieee754@1.2.1: {} + + ignore@4.0.6: {} + + ignore@5.3.2: {} + + immediate@3.0.6: {} + + immer@7.0.15: {} + + immer@9.0.21: {} + + immutable@3.7.6: {} + + immutable@3.8.2: {} + + import-cwd@2.1.0: + dependencies: + import-from: 2.1.0 + + import-fresh@2.0.0: + dependencies: + caller-path: 2.0.0 + resolve-from: 3.0.0 + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-from@2.1.0: + dependencies: + resolve-from: 3.0.0 + + import-local@3.2.0: + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + + imurmurhash@0.1.4: {} + + indent-string@4.0.0: {} + + indexes-of@1.0.1: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.3: {} + + inherits@2.0.4: {} + + ini@1.3.8: {} + + inline-style-prefixer@7.0.1: + dependencies: + css-in-js-utils: 3.1.0 + + insert-css@2.0.0: {} + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + + internmap@1.0.1: {} + + intersection-observer@0.12.2: {} + + intersection-observer@0.7.0: {} + + intl-format-cache@4.3.1: {} + + intl-messageformat-parser@3.6.4: + dependencies: + '@formatjs/intl-unified-numberformat': 3.3.7 + + intl-messageformat@7.8.4: + dependencies: + intl-format-cache: 4.3.1 + intl-messageformat-parser: 3.6.4 + + intl@1.2.5: {} + + invariant@2.2.4: + dependencies: + loose-envify: 1.4.0 + + inversify-inject-decorators@3.1.0: {} + + inversify@5.1.1: {} + + ipaddr.js@1.9.1: {} + + ipaddr.js@2.2.0: {} + + is-accessor-descriptor@1.0.1: + dependencies: + hasown: 2.0.2 + + is-any-array@2.0.1: {} + + is-arguments@1.2.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-arrayish@0.2.1: {} + + is-arrayish@0.3.2: {} + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-binary-path@1.0.1: + dependencies: + binary-extensions: 1.13.1 + optional: true + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-buffer@1.1.6: {} + + is-callable@1.2.7: {} + + is-ci@1.2.1: + dependencies: + ci-info: 1.6.0 + + is-ci@2.0.0: + dependencies: + ci-info: 2.0.0 + + is-class-hotfix@0.0.6: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-data-descriptor@1.0.1: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-descriptor@0.1.7: + dependencies: + is-accessor-descriptor: 1.0.1 + is-data-descriptor: 1.0.1 + + is-descriptor@1.0.3: + dependencies: + is-accessor-descriptor: 1.0.1 + is-data-descriptor: 1.0.1 + + is-directory@0.3.1: {} + + is-docker@2.2.1: {} + + is-dotfile@1.0.3: + optional: true + + is-equal-shallow@0.1.3: + dependencies: + is-primitive: 2.0.0 + optional: true + + is-extendable@0.1.1: {} + + is-extendable@1.0.1: + dependencies: + is-plain-object: 2.0.4 + + is-extglob@1.0.0: + optional: true + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-finite@1.1.0: {} + + is-fullwidth-code-point@3.0.0: {} + + is-generator-fn@2.1.0: {} + + is-generator-function@1.1.0: + dependencies: + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@2.0.1: + dependencies: + is-extglob: 1.0.0 + optional: true + + is-glob@3.1.0: + dependencies: + is-extglob: 2.1.1 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-map@2.0.3: {} + + is-module@1.0.0: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-number@2.1.0: + dependencies: + kind-of: 3.2.2 + optional: true + + is-number@3.0.0: + dependencies: + kind-of: 3.2.2 + + is-number@4.0.0: + optional: true + + is-number@7.0.0: {} + + is-obj@1.0.1: {} + + is-plain-obj@1.1.0: {} + + is-plain-obj@3.0.0: {} + + is-plain-object@2.0.4: + dependencies: + isobject: 3.0.1 + + is-posix-bracket@0.1.1: + optional: true + + is-potential-custom-element-name@1.0.1: {} + + is-primitive@2.0.0: + optional: true + + is-promise@2.2.2: {} + + is-regex@1.1.4: + dependencies: + call-bind: 1.0.8 + has-tostringtag: 1.0.2 + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-regexp@1.0.0: {} + + is-root@2.1.0: {} + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + + is-stream@1.1.0: {} + + is-stream@2.0.1: {} + + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-type-of@1.4.0: + dependencies: + core-util-is: 1.0.3 + is-class-hotfix: 0.0.6 + isstream: 0.1.2 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.19 + + is-typedarray@1.0.0: {} + + is-unicode-supported@0.1.0: {} + + is-url@1.2.4: {} + + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-windows@1.0.2: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + isarray@0.0.1: {} + + isarray@1.0.0: {} + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + isobject@2.1.0: + dependencies: + isarray: 1.0.0 + + isobject@3.0.1: {} + + isomorphic-fetch@2.2.1: + dependencies: + node-fetch: 1.7.3 + whatwg-fetch: 3.6.20 + + isstream@0.1.2: {} + + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-instrument@4.0.3: + dependencies: + '@babel/core': 7.18.6 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-instrument@5.2.1: + dependencies: + '@babel/core': 7.18.6 + '@babel/parser': 7.27.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@4.0.1: + dependencies: + debug: 4.4.0 + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.1.7: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + iterator.prototype@1.1.5: + dependencies: + define-data-property: 1.1.4 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + has-symbols: 1.1.0 + set-function-name: 2.0.2 + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jake@10.9.2: + dependencies: + async: 3.2.6 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + + javascript-stringify@2.1.0: {} + + jest-changed-files@26.6.2: + dependencies: + '@jest/types': 26.6.2 + execa: 4.1.0 + throat: 5.0.0 + + jest-changed-files@27.5.1: + dependencies: + '@jest/types': 27.5.1 + execa: 5.1.1 + throat: 6.0.2 + + jest-circus@27.5.1: + dependencies: + '@jest/environment': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.15.3 + chalk: 4.1.2 + co: 4.6.0 + dedent: 0.7.0 + expect: 27.5.1 + is-generator-fn: 2.1.0 + jest-each: 27.5.1 + jest-matcher-utils: 27.5.1 + jest-message-util: 27.5.1 + jest-runtime: 27.5.1 + jest-snapshot: 27.5.1 + jest-util: 27.5.1 + pretty-format: 27.5.1 + slash: 3.0.0 + stack-utils: 2.0.6 + throat: 6.0.2 + transitivePeerDependencies: + - supports-color + + jest-cli@26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)): + dependencies: + '@jest/core': 26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + '@jest/test-result': 26.6.2 + '@jest/types': 26.6.2 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + import-local: 3.2.0 + is-ci: 2.0.0 + jest-config: 26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + jest-util: 26.6.2 + jest-validate: 26.6.2 + prompts: 2.4.2 + yargs: 15.4.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + jest-cli@27.5.1(node-notifier@8.0.2)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)): + dependencies: + '@jest/core': 27.5.1(node-notifier@8.0.2)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + '@jest/test-result': 27.5.1 + '@jest/types': 27.5.1 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + import-local: 3.2.0 + jest-config: 27.5.1(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + jest-util: 27.5.1 + jest-validate: 27.5.1 + prompts: 2.4.2 + yargs: 16.2.0 + optionalDependencies: + node-notifier: 8.0.2 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + jest-config@26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)): + dependencies: + '@babel/core': 7.18.6 + '@jest/test-sequencer': 26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + '@jest/types': 26.6.2 + babel-jest: 26.6.3(@babel/core@7.18.6) + chalk: 4.1.2 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-environment-jsdom: 26.6.2 + jest-environment-node: 26.6.2 + jest-get-type: 26.3.0 + jest-jasmine2: 26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + jest-regex-util: 26.0.0 + jest-resolve: 26.6.2 + jest-util: 26.6.2 + jest-validate: 26.6.2 + micromatch: 4.0.8 + pretty-format: 26.6.2 + optionalDependencies: + ts-node: 10.9.2(@types/node@18.19.87)(typescript@4.9.5) + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + + jest-config@27.5.1(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)): + dependencies: + '@babel/core': 7.26.10 + '@jest/test-sequencer': 27.5.1 + '@jest/types': 27.5.1 + babel-jest: 27.5.1(@babel/core@7.26.10) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 27.5.1 + jest-environment-jsdom: 27.5.1 + jest-environment-node: 27.5.1 + jest-get-type: 27.5.1 + jest-jasmine2: 27.5.1 + jest-regex-util: 27.5.1 + jest-resolve: 27.5.1 + jest-runner: 27.5.1 + jest-util: 27.5.1 + jest-validate: 27.5.1 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 27.5.1 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + ts-node: 10.9.2(@types/node@18.19.87)(typescript@4.9.5) + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + + jest-diff@26.6.2: + dependencies: + chalk: 4.1.2 + diff-sequences: 26.6.2 + jest-get-type: 26.3.0 + pretty-format: 26.6.2 + + jest-diff@27.5.1: + dependencies: + chalk: 4.1.2 + diff-sequences: 27.5.1 + jest-get-type: 27.5.1 + pretty-format: 27.5.1 + + jest-docblock@26.0.0: + dependencies: + detect-newline: 3.1.0 + + jest-docblock@27.5.1: + dependencies: + detect-newline: 3.1.0 + + jest-each@26.6.2: + dependencies: + '@jest/types': 26.6.2 + chalk: 4.1.2 + jest-get-type: 26.3.0 + jest-util: 26.6.2 + pretty-format: 26.6.2 + + jest-each@27.5.1: + dependencies: + '@jest/types': 27.5.1 + chalk: 4.1.2 + jest-get-type: 27.5.1 + jest-util: 27.5.1 + pretty-format: 27.5.1 + + jest-environment-jsdom@26.6.2: + dependencies: + '@jest/environment': 26.6.2 + '@jest/fake-timers': 26.6.2 + '@jest/types': 26.6.2 + '@types/node': 22.15.3 + jest-mock: 26.6.2 + jest-util: 26.6.2 + jsdom: 16.7.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + + jest-environment-jsdom@27.5.1: + dependencies: + '@jest/environment': 27.5.1 + '@jest/fake-timers': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.15.3 + jest-mock: 27.5.1 + jest-util: 27.5.1 + jsdom: 16.7.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + + jest-environment-node@26.6.2: + dependencies: + '@jest/environment': 26.6.2 + '@jest/fake-timers': 26.6.2 + '@jest/types': 26.6.2 + '@types/node': 22.15.3 + jest-mock: 26.6.2 + jest-util: 26.6.2 + + jest-environment-node@27.5.1: + dependencies: + '@jest/environment': 27.5.1 + '@jest/fake-timers': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.15.3 + jest-mock: 27.5.1 + jest-util: 27.5.1 + + jest-get-type@26.3.0: {} + + jest-get-type@27.5.1: {} + + jest-haste-map@26.6.2: + dependencies: + '@jest/types': 26.6.2 + '@types/graceful-fs': 4.1.9 + '@types/node': 22.15.3 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 26.0.0 + jest-serializer: 26.6.2 + jest-util: 26.6.2 + jest-worker: 26.6.2 + micromatch: 4.0.8 + sane: 4.1.0 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + transitivePeerDependencies: + - supports-color + + jest-haste-map@27.5.1: + dependencies: + '@jest/types': 27.5.1 + '@types/graceful-fs': 4.1.9 + '@types/node': 22.15.3 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 27.5.1 + jest-serializer: 27.5.1 + jest-util: 27.5.1 + jest-worker: 27.5.1 + micromatch: 4.0.8 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + + jest-jasmine2@26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)): + dependencies: + '@babel/traverse': 7.27.0 + '@jest/environment': 26.6.2 + '@jest/source-map': 26.6.2 + '@jest/test-result': 26.6.2 + '@jest/types': 26.6.2 + '@types/node': 22.15.3 + chalk: 4.1.2 + co: 4.6.0 + expect: 26.6.2 + is-generator-fn: 2.1.0 + jest-each: 26.6.2 + jest-matcher-utils: 26.6.2 + jest-message-util: 26.6.2 + jest-runtime: 26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + jest-snapshot: 26.6.2 + jest-util: 26.6.2 + pretty-format: 26.6.2 + throat: 5.0.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + jest-jasmine2@27.5.1: + dependencies: + '@jest/environment': 27.5.1 + '@jest/source-map': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.15.3 + chalk: 4.1.2 + co: 4.6.0 + expect: 27.5.1 + is-generator-fn: 2.1.0 + jest-each: 27.5.1 + jest-matcher-utils: 27.5.1 + jest-message-util: 27.5.1 + jest-runtime: 27.5.1 + jest-snapshot: 27.5.1 + jest-util: 27.5.1 + pretty-format: 27.5.1 + throat: 6.0.2 + transitivePeerDependencies: + - supports-color + + jest-leak-detector@26.6.2: + dependencies: + jest-get-type: 26.3.0 + pretty-format: 26.6.2 + + jest-leak-detector@27.5.1: + dependencies: + jest-get-type: 27.5.1 + pretty-format: 27.5.1 + + jest-matcher-utils@26.6.2: + dependencies: + chalk: 4.1.2 + jest-diff: 26.6.2 + jest-get-type: 26.3.0 + pretty-format: 26.6.2 + + jest-matcher-utils@27.5.1: + dependencies: + chalk: 4.1.2 + jest-diff: 27.5.1 + jest-get-type: 27.5.1 + pretty-format: 27.5.1 + + jest-message-util@26.6.2: + dependencies: + '@babel/code-frame': 7.26.2 + '@jest/types': 26.6.2 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 26.6.2 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-message-util@27.5.1: + dependencies: + '@babel/code-frame': 7.26.2 + '@jest/types': 27.5.1 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 27.5.1 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-message-util@28.1.3: + dependencies: + '@babel/code-frame': 7.26.2 + '@jest/types': 28.1.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 28.1.3 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-mock@26.6.2: + dependencies: + '@jest/types': 26.6.2 + '@types/node': 22.15.3 + + jest-mock@27.5.1: + dependencies: + '@jest/types': 27.5.1 + '@types/node': 22.15.3 + + jest-pnp-resolver@1.2.3(jest-resolve@26.6.2): + optionalDependencies: + jest-resolve: 26.6.2 + + jest-pnp-resolver@1.2.3(jest-resolve@27.5.1): + optionalDependencies: + jest-resolve: 27.5.1 + + jest-regex-util@26.0.0: {} + + jest-regex-util@27.5.1: {} + + jest-regex-util@28.0.2: {} + + jest-resolve-dependencies@26.6.3: + dependencies: + '@jest/types': 26.6.2 + jest-regex-util: 26.0.0 + jest-snapshot: 26.6.2 + transitivePeerDependencies: + - supports-color + + jest-resolve-dependencies@27.5.1: + dependencies: + '@jest/types': 27.5.1 + jest-regex-util: 27.5.1 + jest-snapshot: 27.5.1 + transitivePeerDependencies: + - supports-color + + jest-resolve@26.6.2: + dependencies: + '@jest/types': 26.6.2 + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-pnp-resolver: 1.2.3(jest-resolve@26.6.2) + jest-util: 26.6.2 + read-pkg-up: 7.0.1 + resolve: 1.22.10 + slash: 3.0.0 + + jest-resolve@27.5.1: + dependencies: + '@jest/types': 27.5.1 + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 27.5.1 + jest-pnp-resolver: 1.2.3(jest-resolve@27.5.1) + jest-util: 27.5.1 + jest-validate: 27.5.1 + resolve: 1.22.10 + resolve.exports: 1.1.1 + slash: 3.0.0 + + jest-runner@26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)): + dependencies: + '@jest/console': 26.6.2 + '@jest/environment': 26.6.2 + '@jest/test-result': 26.6.2 + '@jest/types': 26.6.2 + '@types/node': 22.15.3 + chalk: 4.1.2 + emittery: 0.7.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + jest-docblock: 26.0.0 + jest-haste-map: 26.6.2 + jest-leak-detector: 26.6.2 + jest-message-util: 26.6.2 + jest-resolve: 26.6.2 + jest-runtime: 26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + jest-util: 26.6.2 + jest-worker: 26.6.2 + source-map-support: 0.5.21 + throat: 5.0.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + jest-runner@27.5.1: + dependencies: + '@jest/console': 27.5.1 + '@jest/environment': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.15.3 + chalk: 4.1.2 + emittery: 0.8.1 + graceful-fs: 4.2.11 + jest-docblock: 27.5.1 + jest-environment-jsdom: 27.5.1 + jest-environment-node: 27.5.1 + jest-haste-map: 27.5.1 + jest-leak-detector: 27.5.1 + jest-message-util: 27.5.1 + jest-resolve: 27.5.1 + jest-runtime: 27.5.1 + jest-util: 27.5.1 + jest-worker: 27.5.1 + source-map-support: 0.5.21 + throat: 6.0.2 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + + jest-runtime@26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)): + dependencies: + '@jest/console': 26.6.2 + '@jest/environment': 26.6.2 + '@jest/fake-timers': 26.6.2 + '@jest/globals': 26.6.2 + '@jest/source-map': 26.6.2 + '@jest/test-result': 26.6.2 + '@jest/transform': 26.6.2 + '@jest/types': 26.6.2 + '@types/yargs': 15.0.19 + chalk: 4.1.2 + cjs-module-lexer: 0.6.0 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-config: 26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + jest-haste-map: 26.6.2 + jest-message-util: 26.6.2 + jest-mock: 26.6.2 + jest-regex-util: 26.0.0 + jest-resolve: 26.6.2 + jest-snapshot: 26.6.2 + jest-util: 26.6.2 + jest-validate: 26.6.2 + slash: 3.0.0 + strip-bom: 4.0.0 + yargs: 15.4.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + jest-runtime@27.5.1: + dependencies: + '@jest/environment': 27.5.1 + '@jest/fake-timers': 27.5.1 + '@jest/globals': 27.5.1 + '@jest/source-map': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + chalk: 4.1.2 + cjs-module-lexer: 1.4.3 + collect-v8-coverage: 1.0.2 + execa: 5.1.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 27.5.1 + jest-message-util: 27.5.1 + jest-mock: 27.5.1 + jest-regex-util: 27.5.1 + jest-resolve: 27.5.1 + jest-snapshot: 27.5.1 + jest-util: 27.5.1 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + + jest-serializer@26.6.2: + dependencies: + '@types/node': 22.15.3 + graceful-fs: 4.2.11 + + jest-serializer@27.5.1: + dependencies: + '@types/node': 22.15.3 + graceful-fs: 4.2.11 + + jest-snapshot@26.6.2: + dependencies: + '@babel/types': 7.27.0 + '@jest/types': 26.6.2 + '@types/babel__traverse': 7.20.7 + '@types/prettier': 2.7.3 + chalk: 4.1.2 + expect: 26.6.2 + graceful-fs: 4.2.11 + jest-diff: 26.6.2 + jest-get-type: 26.3.0 + jest-haste-map: 26.6.2 + jest-matcher-utils: 26.6.2 + jest-message-util: 26.6.2 + jest-resolve: 26.6.2 + natural-compare: 1.4.0 + pretty-format: 26.6.2 + semver: 7.7.1 + transitivePeerDependencies: + - supports-color + + jest-snapshot@27.5.1: + dependencies: + '@babel/core': 7.26.10 + '@babel/generator': 7.27.0 + '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.10) + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/babel__traverse': 7.20.7 + '@types/prettier': 2.7.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.10) + chalk: 4.1.2 + expect: 27.5.1 + graceful-fs: 4.2.11 + jest-diff: 27.5.1 + jest-get-type: 27.5.1 + jest-haste-map: 27.5.1 + jest-matcher-utils: 27.5.1 + jest-message-util: 27.5.1 + jest-util: 27.5.1 + natural-compare: 1.4.0 + pretty-format: 27.5.1 + semver: 7.7.1 + transitivePeerDependencies: + - supports-color + + jest-util@26.6.2: + dependencies: + '@jest/types': 26.6.2 + '@types/node': 22.15.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + is-ci: 2.0.0 + micromatch: 4.0.8 + + jest-util@27.5.1: + dependencies: + '@jest/types': 27.5.1 + '@types/node': 22.15.3 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + + jest-util@28.1.3: + dependencies: + '@jest/types': 28.1.3 + '@types/node': 22.15.3 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + + jest-validate@26.6.2: + dependencies: + '@jest/types': 26.6.2 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 26.3.0 + leven: 3.1.0 + pretty-format: 26.6.2 + + jest-validate@27.5.1: + dependencies: + '@jest/types': 27.5.1 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 27.5.1 + leven: 3.1.0 + pretty-format: 27.5.1 + + jest-watch-typeahead@1.1.0(jest@27.5.1(node-notifier@8.0.2)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5))): + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + jest: 27.5.1(node-notifier@8.0.2)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + jest-regex-util: 28.0.2 + jest-watcher: 28.1.3 + slash: 4.0.0 + string-length: 5.0.1 + strip-ansi: 7.1.0 + + jest-watcher@26.6.2: + dependencies: + '@jest/test-result': 26.6.2 + '@jest/types': 26.6.2 + '@types/node': 22.15.3 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + jest-util: 26.6.2 + string-length: 4.0.2 + + jest-watcher@27.5.1: + dependencies: + '@jest/test-result': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.15.3 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + jest-util: 27.5.1 + string-length: 4.0.2 + + jest-watcher@28.1.3: + dependencies: + '@jest/test-result': 28.1.3 + '@jest/types': 28.1.3 + '@types/node': 22.15.3 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.10.2 + jest-util: 28.1.3 + string-length: 4.0.2 + + jest-worker@24.9.0: + dependencies: + merge-stream: 2.0.0 + supports-color: 6.1.0 + + jest-worker@26.6.2: + dependencies: + '@types/node': 22.15.3 + merge-stream: 2.0.0 + supports-color: 7.2.0 + + jest-worker@27.5.1: + dependencies: + '@types/node': 22.15.3 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jest-worker@28.1.3: + dependencies: + '@types/node': 22.15.3 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jest@26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)): + dependencies: + '@jest/core': 26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + import-local: 3.2.0 + jest-cli: 26.6.3(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + jest@27.5.1(node-notifier@8.0.2)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)): + dependencies: + '@jest/core': 27.5.1(node-notifier@8.0.2)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + import-local: 3.2.0 + jest-cli: 27.5.1(node-notifier@8.0.2)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + optionalDependencies: + node-notifier: 8.0.2 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + jiti@1.21.7: {} + + jquery-mousewheel@3.2.2: + dependencies: + jquery: 3.7.1 + + jquery@3.7.1: {} + + js-base64@2.6.4: {} + + js-base64@3.7.7: {} + + js-cookie@2.2.1: {} + + js-cookie@3.0.5: {} + + js-tokens@3.0.2: {} + + js-tokens@4.0.0: {} + + js-yaml@3.14.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsdom@16.7.0: + dependencies: + abab: 2.0.6 + acorn: 8.14.1 + acorn-globals: 6.0.0 + cssom: 0.4.4 + cssstyle: 2.3.0 + data-urls: 2.0.0 + decimal.js: 10.5.0 + domexception: 2.0.1 + escodegen: 2.1.0 + form-data: 3.0.3 + html-encoding-sniffer: 2.0.1 + http-proxy-agent: 4.0.1 + https-proxy-agent: 5.0.1 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.20 + parse5: 6.0.1 + saxes: 5.0.1 + symbol-tree: 3.2.4 + tough-cookie: 4.1.4 + w3c-hr-time: 1.0.2 + w3c-xmlserializer: 2.0.0 + webidl-conversions: 6.1.0 + whatwg-encoding: 1.0.5 + whatwg-mimetype: 2.3.0 + whatwg-url: 8.7.0 + ws: 7.5.10 + xml-name-validator: 3.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + jsencrypt-ext@2.1.2: + dependencies: + jsencrypt: 3.3.2 + + jsencrypt@3.3.2: {} + + jsesc@0.5.0: {} + + jsesc@1.3.0: {} + + jsesc@3.0.2: {} + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-parse-better-errors@1.0.2: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-schema@0.4.0: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json-stringify-pretty-compact@3.0.0: {} + + json2module@0.0.3: + dependencies: + rw: 1.3.3 + + json2mq@0.2.0: + dependencies: + string-convert: 0.2.1 + + json5@0.5.1: {} + + json5@1.0.2: + dependencies: + minimist: 1.2.8 + + json5@2.2.3: {} + + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsonpath@1.1.1: + dependencies: + esprima: 1.2.2 + static-eval: 2.0.2 + underscore: 1.12.1 + + jsonpointer@5.0.1: {} + + jsx-ast-utils@3.3.5: + dependencies: + array-includes: 3.1.8 + array.prototype.flat: 1.3.3 + object.assign: 4.1.7 + object.values: 1.2.1 + + junk@3.1.0: {} + + kdbush@3.0.0: {} + + kdbush@4.0.2: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kind-of@3.2.2: + dependencies: + is-buffer: 1.1.6 + + kind-of@4.0.0: + dependencies: + is-buffer: 1.1.6 + + kind-of@6.0.3: {} + + kleur@3.0.3: {} + + klona@2.0.6: {} + + language-subtag-registry@0.3.23: {} + + language-tags@1.0.9: + dependencies: + language-subtag-registry: 0.3.23 + + launch-editor@2.10.0: + dependencies: + picocolors: 1.1.1 + shell-quote: 1.8.2 + + lazy-cache@1.0.4: {} + + leven@3.1.0: {} + + levn@0.3.0: + dependencies: + prelude-ls: 1.1.2 + type-check: 0.3.2 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lie@3.1.1: + dependencies: + immediate: 3.0.6 + + lilconfig@2.1.0: {} + + lilconfig@3.1.3: {} + + lines-and-columns@1.2.4: {} + + lint-staged@10.5.4: + dependencies: + chalk: 4.1.2 + cli-truncate: 2.1.0 + commander: 6.2.1 + cosmiconfig: 7.1.0 + debug: 4.4.0 + dedent: 0.7.0 + enquirer: 2.4.1 + execa: 4.1.0 + listr2: 3.14.0(enquirer@2.4.1) + log-symbols: 4.1.0 + micromatch: 4.0.8 + normalize-path: 3.0.0 + please-upgrade-node: 3.2.0 + string-argv: 0.3.1 + stringify-object: 3.3.0 + transitivePeerDependencies: + - supports-color + + listr2@3.14.0(enquirer@2.4.1): + dependencies: + cli-truncate: 2.1.0 + colorette: 2.0.20 + log-update: 4.0.0 + p-map: 4.0.0 + rfdc: 1.4.1 + rxjs: 7.8.2 + through: 2.3.8 + wrap-ansi: 7.0.0 + optionalDependencies: + enquirer: 2.4.1 + + loader-runner@4.3.0: {} + + loader-utils@1.4.2: + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 1.0.2 + + loader-utils@2.0.4: + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 2.2.3 + + loader-utils@3.3.1: {} + + localforage@1.10.0: + dependencies: + lie: 3.1.1 + + locate-path@3.0.0: + dependencies: + p-locate: 3.0.0 + path-exists: 3.0.0 + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash-es@4.17.21: {} + + lodash._reinterpolate@3.0.0: {} + + lodash.camelcase@4.3.0: {} + + lodash.curry@4.1.1: {} + + lodash.debounce@4.0.8: {} + + lodash.flow@3.5.0: {} + + lodash.isequal@4.5.0: {} + + lodash.memoize@4.1.2: {} + + lodash.merge@4.6.2: {} + + lodash.sortby@4.7.0: {} + + lodash.template@4.5.0: + dependencies: + lodash._reinterpolate: 3.0.0 + lodash.templatesettings: 4.2.0 + + lodash.templatesettings@4.2.0: + dependencies: + lodash._reinterpolate: 3.0.0 + + lodash.throttle@4.1.1: {} + + lodash.uniq@4.5.0: {} + + lodash.upperfirst@4.3.1: {} + + lodash@4.17.21: {} + + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + + log-update@4.0.0: + dependencies: + ansi-escapes: 4.3.2 + cli-cursor: 3.1.0 + slice-ansi: 4.0.0 + wrap-ansi: 6.2.0 + + longest@1.0.1: {} + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + lottie-web@5.12.2: {} + + lower-case@2.0.2: + dependencies: + tslib: 2.8.1 + + lru-cache@10.4.3: {} + + lru-cache@4.1.5: + dependencies: + pseudomap: 1.0.2 + yallist: 2.1.2 + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lru-queue@0.1.0: + dependencies: + es5-ext: 0.10.64 + + magic-string@0.25.9: + dependencies: + sourcemap-codec: 1.4.8 + + make-dir@3.1.0: + dependencies: + semver: 6.3.1 + + make-dir@4.0.0: + dependencies: + semver: 7.7.1 + + make-error@1.3.6: {} + + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 + + mana-common@0.3.2: {} + + mana-syringe@0.2.2: + dependencies: + inversify: 5.1.1 + + map-cache@0.2.2: {} + + map-visit@1.0.0: + dependencies: + object-visit: 1.0.1 + + mapbox-gl@1.13.3: + dependencies: + '@mapbox/geojson-rewind': 0.5.2 + '@mapbox/geojson-types': 1.0.2 + '@mapbox/jsonlint-lines-primitives': 2.0.2 + '@mapbox/mapbox-gl-supported': 1.5.0(mapbox-gl@1.13.3) + '@mapbox/point-geometry': 0.1.0 + '@mapbox/tiny-sdf': 1.2.5 + '@mapbox/unitbezier': 0.0.0 + '@mapbox/vector-tile': 1.3.1 + '@mapbox/whoots-js': 3.1.0 + csscolorparser: 1.0.3 + earcut: 2.2.4 + geojson-vt: 3.2.1 + gl-matrix: 3.4.3 + grid-index: 1.1.0 + murmurhash-js: 1.0.0 + pbf: 3.3.0 + potpack: 1.0.2 + quickselect: 2.0.0 + rw: 1.3.3 + supercluster: 7.1.5 + tinyqueue: 2.0.3 + vt-pbf: 3.1.3 + + maplibre-gl@3.6.2: + dependencies: + '@mapbox/geojson-rewind': 0.5.2 + '@mapbox/jsonlint-lines-primitives': 2.0.2 + '@mapbox/point-geometry': 0.1.0 + '@mapbox/tiny-sdf': 2.0.6 + '@mapbox/unitbezier': 0.0.1 + '@mapbox/vector-tile': 1.3.1 + '@mapbox/whoots-js': 3.1.0 + '@maplibre/maplibre-gl-style-spec': 19.3.3 + '@types/geojson': 7946.0.16 + '@types/mapbox__point-geometry': 0.1.4 + '@types/mapbox__vector-tile': 1.3.4 + '@types/pbf': 3.0.5 + '@types/supercluster': 7.1.3 + earcut: 2.2.4 + geojson-vt: 3.2.1 + gl-matrix: 3.4.3 + global-prefix: 3.0.0 + kdbush: 4.0.2 + murmurhash-js: 1.0.0 + pbf: 3.3.0 + potpack: 2.0.0 + quickselect: 2.0.0 + supercluster: 8.0.1 + tinyqueue: 2.0.3 + vt-pbf: 3.1.3 + + material-colors@1.2.6: {} + + math-intrinsics@1.1.0: {} + + math-random@1.0.4: + optional: true + + md5.js@1.3.5: + dependencies: + hash-base: 3.0.5 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + mdn-data@2.0.14: {} + + mdn-data@2.0.4: {} + + media-typer@0.3.0: {} + + memfs@3.5.3: + dependencies: + fs-monkey: 1.0.6 + + memoize-one@5.2.1: {} + + memoizee@0.4.17: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-weak-map: 2.0.3 + event-emitter: 0.3.5 + is-promise: 2.2.2 + lru-queue: 0.1.0 + next-tick: 1.1.0 + timers-ext: 0.1.8 + + merge-descriptors@1.0.3: {} + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + methods@1.1.2: {} + + micromatch@2.3.11: + dependencies: + arr-diff: 2.0.0 + array-unique: 0.2.1 + braces: 1.8.5 + expand-brackets: 0.1.5 + extglob: 0.3.2 + filename-regex: 2.0.1 + is-extglob: 1.0.0 + is-glob: 2.0.1 + kind-of: 3.2.2 + normalize-path: 2.1.1 + object.omit: 2.0.1 + parse-glob: 3.0.4 + regex-cache: 0.4.4 + optional: true + + micromatch@3.1.10: + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + braces: 2.3.2 + define-property: 2.0.2 + extend-shallow: 3.0.2 + extglob: 2.0.4 + fragment-cache: 0.2.1 + kind-of: 6.0.3 + nanomatch: 1.2.13 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + miller-rabin@4.0.1: + dependencies: + bn.js: 4.12.2 + brorand: 1.1.0 + + mime-db@1.52.0: {} + + mime-db@1.54.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@1.4.1: {} + + mime@1.6.0: {} + + mimic-fn@2.1.0: {} + + min-document@2.19.0: + dependencies: + dom-walk: 0.1.2 + + mini-create-react-context@0.4.1(prop-types@15.8.1)(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + prop-types: 15.8.1 + react: 16.14.0 + tiny-warning: 1.0.3 + + mini-css-extract-plugin@1.6.2(webpack@5.99.7): + dependencies: + loader-utils: 2.0.4 + schema-utils: 3.3.0 + webpack: 5.99.7 + webpack-sources: 1.4.3 + + mini-css-extract-plugin@2.9.2(webpack@5.99.7): + dependencies: + schema-utils: 4.3.2 + tapable: 2.2.1 + webpack: 5.99.7 + + minimalistic-assert@1.0.1: {} + + minimalistic-crypto-utils@1.0.1: {} + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.1 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minimist@1.2.8: {} + + minipass@7.1.2: {} + + mixin-deep@1.3.2: + dependencies: + for-in: 1.0.2 + is-extendable: 1.0.1 + + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 + + ml-array-max@1.2.4: + dependencies: + is-any-array: 2.0.1 + + ml-array-min@1.2.3: + dependencies: + is-any-array: 2.0.1 + + ml-array-rescale@1.3.7: + dependencies: + is-any-array: 2.0.1 + ml-array-max: 1.2.4 + ml-array-min: 1.2.3 + + ml-matrix@6.12.1: + dependencies: + is-any-array: 2.0.1 + ml-array-rescale: 1.3.7 + + ml-matrix@6.5.0: + dependencies: + ml-array-rescale: 1.3.7 + + mock-property@1.0.3: + dependencies: + define-data-property: 1.1.4 + functions-have-names: 1.2.3 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + hasown: 2.0.2 + isarray: 2.0.5 + + mock.js@0.2.0: {} + + mockjs@1.1.0: + dependencies: + commander: 13.1.0 + + moment@2.30.1: {} + + mousetrap@1.6.5: {} + + ms@2.0.0: {} + + ms@2.1.3: {} + + multicast-dns@7.2.5: + dependencies: + dns-packet: 5.6.1 + thunky: 1.1.0 + + murmurhash-js@1.0.0: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + nan@2.22.2: + optional: true + + nano-css@5.6.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + css-tree: 1.1.3 + csstype: 3.1.3 + fastest-stable-stringify: 2.0.2 + inline-style-prefixer: 7.0.1 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + rtl-css-js: 1.16.1 + stacktrace-js: 2.0.2 + stylis: 4.3.6 + + nanoid@3.3.11: {} + + nanomatch@1.2.13: + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + define-property: 2.0.2 + extend-shallow: 3.0.2 + fragment-cache: 0.2.1 + is-windows: 1.0.2 + kind-of: 6.0.3 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + natural-compare-lite@1.4.0: {} + + natural-compare@1.4.0: {} + + negotiator@0.6.3: {} + + negotiator@0.6.4: {} + + neo-async@2.6.2: {} + + nested-error-stacks@2.1.1: {} + + next-tick@1.1.0: {} + + nice-try@1.0.5: {} + + no-case@3.0.4: + dependencies: + lower-case: 2.0.2 + tslib: 2.8.1 + + node-fetch-h2@2.3.0: + dependencies: + http2-client: 1.3.5 + + node-fetch@1.7.3: + dependencies: + encoding: 0.1.13 + is-stream: 1.1.0 + + node-fetch@2.7.0(encoding@0.1.13): + dependencies: + whatwg-url: 5.0.0 + optionalDependencies: + encoding: 0.1.13 + + node-forge@1.3.1: {} + + node-int64@0.4.0: {} + + node-libs-browser@2.2.1: + dependencies: + assert: 1.5.1 + browserify-zlib: 0.2.0 + buffer: 4.9.2 + console-browserify: 1.2.0 + constants-browserify: 1.0.0 + crypto-browserify: 3.12.1 + domain-browser: 1.2.0 + events: 3.3.0 + https-browserify: 1.0.0 + os-browserify: 0.3.0 + path-browserify: 0.0.1 + process: 0.11.10 + punycode: 1.4.1 + querystring-es3: 0.2.1 + readable-stream: 2.3.8 + stream-browserify: 2.0.2 + stream-http: 2.8.3 + string_decoder: 1.3.0 + timers-browserify: 2.0.12 + tty-browserify: 0.0.0 + url: 0.11.4 + util: 0.11.1 + vm-browserify: 1.1.2 + + node-notifier@8.0.2: + dependencies: + growly: 1.3.0 + is-wsl: 2.2.0 + semver: 7.7.1 + shellwords: 0.1.1 + uuid: 8.3.2 + which: 2.0.2 + optional: true + + node-readfiles@0.2.0: + dependencies: + es6-promise: 3.3.1 + + node-releases@2.0.19: {} + + normalize-package-data@2.5.0: + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.10 + semver: 5.7.2 + validate-npm-package-license: 3.0.4 + + normalize-path@1.0.0: {} + + normalize-path@2.1.1: + dependencies: + remove-trailing-separator: 1.1.0 + + normalize-path@3.0.0: {} + + normalize-range@0.1.2: {} + + normalize-url@1.9.1: + dependencies: + object-assign: 4.1.1 + prepend-http: 1.0.4 + query-string: 4.3.4 + sort-keys: 1.1.2 + + normalize-url@6.1.0: {} + + normalize.css@7.0.0: {} + + npm-run-path@2.0.2: + dependencies: + path-key: 2.0.1 + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + nth-check@1.0.2: + dependencies: + boolbase: 1.0.0 + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + num2fraction@1.2.2: {} + + numericjs@1.2.6: {} + + nunjucks@3.2.4(chokidar@3.6.0): + dependencies: + a-sync-waterfall: 1.0.1 + asap: 2.0.6 + commander: 5.1.0 + optionalDependencies: + chokidar: 3.6.0 + + nwsapi@2.2.20: {} + + oas-kit-common@1.0.8: + dependencies: + fast-safe-stringify: 2.1.1 + + oas-linter@3.2.2: + dependencies: + '@exodus/schemasafe': 1.3.0 + should: 13.2.3 + yaml: 1.10.2 + + oas-resolver@2.5.6: + dependencies: + node-fetch-h2: 2.3.0 + oas-kit-common: 1.0.8 + reftools: 1.1.9 + yaml: 1.10.2 + yargs: 17.7.2 + + oas-schema-walker@1.1.5: {} + + oas-validator@5.0.8: + dependencies: + call-me-maybe: 1.0.2 + oas-kit-common: 1.0.8 + oas-linter: 3.2.2 + oas-resolver: 2.5.6 + oas-schema-walker: 1.1.5 + reftools: 1.1.9 + should: 13.2.3 + yaml: 1.10.2 + + object-assign@4.1.1: {} + + object-copy@0.1.0: + dependencies: + copy-descriptor: 0.1.1 + define-property: 0.2.5 + kind-of: 3.2.2 + + object-hash@3.0.0: {} + + object-inspect@1.12.3: {} + + object-inspect@1.13.4: {} + + object-is@1.1.6: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + + object-keys@1.1.1: {} + + object-visit@1.0.1: + dependencies: + isobject: 3.0.1 + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + object.entries@1.1.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + object.fromentries@2.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-object-atoms: 1.1.1 + + object.getownpropertydescriptors@2.1.8: + dependencies: + array.prototype.reduce: 1.0.8 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-object-atoms: 1.1.1 + gopd: 1.2.0 + safe-array-concat: 1.1.3 + + object.groupby@1.0.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + + object.omit@2.0.1: + dependencies: + for-own: 0.1.5 + is-extendable: 0.1.1 + optional: true + + object.pick@1.3.0: + dependencies: + isobject: 3.0.1 + + object.values@1.2.1: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + obuf@1.1.2: {} + + omit.js@1.0.2: + dependencies: + babel-runtime: 6.26.0 + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + on-headers@1.0.2: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + + openapi3-ts@2.0.2: + dependencies: + yaml: 1.10.2 + + optionator@0.8.3: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.3.0 + prelude-ls: 1.1.2 + type-check: 0.3.2 + word-wrap: 1.2.5 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + os-browserify@0.3.0: {} + + os-homedir@1.0.2: {} + + os-tmpdir@1.0.2: {} + + output-file-sync@1.1.2: + dependencies: + graceful-fs: 4.2.11 + mkdirp: 0.5.6 + object-assign: 4.1.1 + + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + + p-all@2.1.0: + dependencies: + p-map: 2.1.0 + + p-each-series@2.2.0: {} + + p-event@4.2.0: + dependencies: + p-timeout: 3.2.0 + + p-filter@2.1.0: + dependencies: + p-map: 2.1.0 + + p-finally@1.0.0: {} + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@3.0.0: + dependencies: + p-limit: 2.3.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-map@2.1.0: {} + + p-map@3.0.0: + dependencies: + aggregate-error: 3.1.0 + + p-map@4.0.0: + dependencies: + aggregate-error: 3.1.0 + + p-retry@4.6.2: + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 + + p-timeout@3.2.0: + dependencies: + p-finally: 1.0.0 + + p-try@2.2.0: {} + + package-json-from-dist@1.0.1: {} + + pako@1.0.11: {} + + param-case@3.0.4: + dependencies: + dot-case: 3.0.4 + tslib: 2.8.1 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-asn1@5.1.7: + dependencies: + asn1.js: 4.10.1 + browserify-aes: 1.2.0 + evp_bytestokey: 1.0.3 + hash-base: 3.0.5 + pbkdf2: 3.1.2 + safe-buffer: 5.2.1 + + parse-glob@3.0.4: + dependencies: + glob-base: 0.3.0 + is-dotfile: 1.0.3 + is-extglob: 1.0.0 + is-glob: 2.0.1 + optional: true + + parse-json@4.0.0: + dependencies: + error-ex: 1.3.2 + json-parse-better-errors: 1.0.2 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.26.2 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse5@6.0.1: {} + + parseurl@1.3.3: {} + + pascal-case@3.1.2: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + + pascalcase@0.1.1: {} + + path-browserify@0.0.1: {} + + path-dirname@1.0.2: {} + + path-exists@3.0.0: {} + + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@2.0.1: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + path-to-regexp@0.1.12: {} + + path-to-regexp@1.9.0: + dependencies: + isarray: 0.0.1 + + path-to-regexp@7.2.0: {} + + path-to-regexp@8.2.0: {} + + path-type@3.0.0: + dependencies: + pify: 3.0.0 + + path-type@4.0.0: {} + + pbf@3.3.0: + dependencies: + ieee754: 1.2.1 + resolve-protobuf-schema: 2.1.0 + + pbkdf2@3.1.2: + dependencies: + create-hash: 1.2.0 + create-hmac: 1.1.7 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.11 + + pdfast@0.2.0: {} + + performance-now@2.1.0: {} + + picocolors@0.2.1: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + pify@2.3.0: {} + + pify@3.0.0: {} + + pify@4.0.1: {} + + pirates@4.0.7: {} + + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + + pkg-up@3.1.0: + dependencies: + find-up: 3.0.0 + + please-upgrade-node@3.2.0: + dependencies: + semver-compare: 1.0.0 + + pmtiles@2.11.0: + dependencies: + fflate: 0.8.2 + + polygon-clipping@0.15.7: + dependencies: + robust-predicates: 3.0.2 + splaytree: 3.1.2 + + polyline-miter-util@1.0.1: + dependencies: + gl-vec2: 1.3.0 + + polyline-normals@2.0.2: + dependencies: + polyline-miter-util: 1.0.1 + + posix-character-classes@0.1.1: {} + + possible-typed-array-names@1.1.0: {} + + postcss-attribute-case-insensitive@4.0.2: + dependencies: + postcss: 7.0.32 + postcss-selector-parser: 6.1.2 + + postcss-attribute-case-insensitive@5.0.2(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-browser-comments@4.0.0(browserslist@4.24.4)(postcss@8.5.3): + dependencies: + browserslist: 4.24.4 + postcss: 8.5.3 + + postcss-calc@8.2.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + postcss-value-parser: 4.2.0 + + postcss-clamp@4.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-color-functional-notation@2.0.1: + dependencies: + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + + postcss-color-functional-notation@4.2.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-color-gray@5.0.0: + dependencies: + '@csstools/convert-colors': 1.4.0 + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + + postcss-color-hex-alpha@5.0.3: + dependencies: + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + + postcss-color-hex-alpha@8.0.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-color-mod-function@3.0.3: + dependencies: + '@csstools/convert-colors': 1.4.0 + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + + postcss-color-rebeccapurple@4.0.1: + dependencies: + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + + postcss-color-rebeccapurple@7.1.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-colormin@5.3.1(postcss@8.5.3): + dependencies: + browserslist: 4.24.4 + caniuse-api: 3.0.0 + colord: 2.9.3 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-convert-values@5.1.3(postcss@8.5.3): + dependencies: + browserslist: 4.24.4 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-custom-media@7.0.8: + dependencies: + postcss: 7.0.32 + + postcss-custom-media@8.0.2(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-custom-properties@12.1.11(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-custom-properties@8.0.11: + dependencies: + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + + postcss-custom-selectors@5.1.2: + dependencies: + postcss: 7.0.32 + postcss-selector-parser: 5.0.0 + + postcss-custom-selectors@6.0.3(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-dir-pseudo-class@5.0.0: + dependencies: + postcss: 7.0.32 + postcss-selector-parser: 5.0.0 + + postcss-dir-pseudo-class@6.0.5(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-discard-comments@5.1.2(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-discard-duplicates@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-discard-empty@5.1.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-discard-overridden@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-double-position-gradients@1.0.0: + dependencies: + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + + postcss-double-position-gradients@3.1.2(postcss@8.5.3): + dependencies: + '@csstools/postcss-progressive-custom-properties': 1.3.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-env-function@2.0.2: + dependencies: + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + + postcss-env-function@4.0.6(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-flexbugs-fixes@4.2.1: + dependencies: + postcss: 7.0.32 + + postcss-flexbugs-fixes@5.0.2(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-focus-visible@4.0.0: + dependencies: + postcss: 7.0.32 + + postcss-focus-visible@6.0.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-focus-within@3.0.0: + dependencies: + postcss: 7.0.32 + + postcss-focus-within@5.0.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-font-variant@4.0.1: + dependencies: + postcss: 7.0.32 + + postcss-font-variant@5.0.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-gap-properties@2.0.0: + dependencies: + postcss: 7.0.32 + + postcss-gap-properties@3.0.5(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-image-set-function@3.0.1: + dependencies: + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + + postcss-image-set-function@4.0.7(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-import@15.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.10 + + postcss-initial@3.0.4: + dependencies: + postcss: 7.0.32 + + postcss-initial@4.0.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-js@4.0.1(postcss@8.5.3): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.5.3 + + postcss-lab-function@2.0.1: + dependencies: + '@csstools/convert-colors': 1.4.0 + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + + postcss-lab-function@4.2.1(postcss@8.5.3): + dependencies: + '@csstools/postcss-progressive-custom-properties': 1.3.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-less@6.0.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-load-config@2.1.2: + dependencies: + cosmiconfig: 5.2.1 + import-cwd: 2.1.0 + + postcss-load-config@4.0.2(postcss@8.5.3)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)): + dependencies: + lilconfig: 3.1.3 + yaml: 2.7.1 + optionalDependencies: + postcss: 8.5.3 + ts-node: 10.9.2(@types/node@18.19.87)(typescript@4.9.5) + + postcss-loader@3.0.0: + dependencies: + loader-utils: 1.4.2 + postcss: 7.0.32 + postcss-load-config: 2.1.2 + schema-utils: 1.0.0 + + postcss-loader@6.2.1(postcss@8.5.3)(webpack@5.99.7): + dependencies: + cosmiconfig: 7.1.0 + klona: 2.0.6 + postcss: 8.5.3 + semver: 7.7.1 + webpack: 5.99.7 + + postcss-logical@3.0.0: + dependencies: + postcss: 7.0.32 + + postcss-logical@5.0.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-media-minmax@4.0.0: + dependencies: + postcss: 7.0.32 + + postcss-media-minmax@5.0.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-merge-longhand@5.1.7(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + stylehacks: 5.1.1(postcss@8.5.3) + + postcss-merge-rules@5.1.4(postcss@8.5.3): + dependencies: + browserslist: 4.24.4 + caniuse-api: 3.0.0 + cssnano-utils: 3.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-minify-font-values@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-minify-gradients@5.1.1(postcss@8.5.3): + dependencies: + colord: 2.9.3 + cssnano-utils: 3.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-minify-params@5.1.4(postcss@8.5.3): + dependencies: + browserslist: 4.24.4 + cssnano-utils: 3.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-minify-selectors@5.2.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-modules-extract-imports@3.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-modules-local-by-default@4.2.0(postcss@8.5.3): + dependencies: + icss-utils: 5.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-selector-parser: 7.1.0 + postcss-value-parser: 4.2.0 + + postcss-modules-scope@3.2.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 7.1.0 + + postcss-modules-values@4.0.0(postcss@8.5.3): + dependencies: + icss-utils: 5.1.0(postcss@8.5.3) + postcss: 8.5.3 + + postcss-nested@6.2.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-nesting@10.2.0(postcss@8.5.3): + dependencies: + '@csstools/selector-specificity': 2.2.0(postcss-selector-parser@6.1.2) + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-nesting@7.0.1: + dependencies: + postcss: 7.0.32 + + postcss-normalize-charset@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-normalize-display-values@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-positions@5.1.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-repeat-style@5.1.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-string@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-timing-functions@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-unicode@5.1.1(postcss@8.5.3): + dependencies: + browserslist: 4.24.4 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-url@5.1.0(postcss@8.5.3): + dependencies: + normalize-url: 6.1.0 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-whitespace@5.1.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize@10.0.1(browserslist@4.24.4)(postcss@8.5.3): + dependencies: + '@csstools/normalize.css': 12.1.1 + browserslist: 4.24.4 + postcss: 8.5.3 + postcss-browser-comments: 4.0.0(browserslist@4.24.4)(postcss@8.5.3) + sanitize.css: 13.0.0 + + postcss-opacity-percentage@1.1.3(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-ordered-values@5.1.3(postcss@8.5.3): + dependencies: + cssnano-utils: 3.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-overflow-shorthand@2.0.0: + dependencies: + postcss: 7.0.32 + + postcss-overflow-shorthand@3.0.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-page-break@2.0.0: + dependencies: + postcss: 7.0.32 + + postcss-page-break@3.0.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-place@4.0.1: + dependencies: + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + + postcss-place@7.0.5(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-preset-env@6.7.0: + dependencies: + autoprefixer: 9.8.8 + browserslist: 4.24.4 + caniuse-lite: 1.0.30001715 + css-blank-pseudo: 0.1.4 + css-has-pseudo: 0.10.0 + css-prefers-color-scheme: 3.1.1 + cssdb: 4.4.0 + postcss: 7.0.32 + postcss-attribute-case-insensitive: 4.0.2 + postcss-color-functional-notation: 2.0.1 + postcss-color-gray: 5.0.0 + postcss-color-hex-alpha: 5.0.3 + postcss-color-mod-function: 3.0.3 + postcss-color-rebeccapurple: 4.0.1 + postcss-custom-media: 7.0.8 + postcss-custom-properties: 8.0.11 + postcss-custom-selectors: 5.1.2 + postcss-dir-pseudo-class: 5.0.0 + postcss-double-position-gradients: 1.0.0 + postcss-env-function: 2.0.2 + postcss-focus-visible: 4.0.0 + postcss-focus-within: 3.0.0 + postcss-font-variant: 4.0.1 + postcss-gap-properties: 2.0.0 + postcss-image-set-function: 3.0.1 + postcss-initial: 3.0.4 + postcss-lab-function: 2.0.1 + postcss-logical: 3.0.0 + postcss-media-minmax: 4.0.0 + postcss-nesting: 7.0.1 + postcss-overflow-shorthand: 2.0.0 + postcss-page-break: 2.0.0 + postcss-place: 4.0.1 + postcss-pseudo-class-any-link: 6.0.0 + postcss-replace-overflow-wrap: 3.0.0 + postcss-selector-matches: 4.0.0 + postcss-selector-not: 4.0.1 + + postcss-preset-env@7.8.3(postcss@8.5.3): + dependencies: + '@csstools/postcss-cascade-layers': 1.1.1(postcss@8.5.3) + '@csstools/postcss-color-function': 1.1.1(postcss@8.5.3) + '@csstools/postcss-font-format-keywords': 1.0.1(postcss@8.5.3) + '@csstools/postcss-hwb-function': 1.0.2(postcss@8.5.3) + '@csstools/postcss-ic-unit': 1.0.1(postcss@8.5.3) + '@csstools/postcss-is-pseudo-class': 2.0.7(postcss@8.5.3) + '@csstools/postcss-nested-calc': 1.0.0(postcss@8.5.3) + '@csstools/postcss-normalize-display-values': 1.0.1(postcss@8.5.3) + '@csstools/postcss-oklab-function': 1.1.1(postcss@8.5.3) + '@csstools/postcss-progressive-custom-properties': 1.3.0(postcss@8.5.3) + '@csstools/postcss-stepped-value-functions': 1.0.1(postcss@8.5.3) + '@csstools/postcss-text-decoration-shorthand': 1.0.0(postcss@8.5.3) + '@csstools/postcss-trigonometric-functions': 1.0.2(postcss@8.5.3) + '@csstools/postcss-unset-value': 1.0.2(postcss@8.5.3) + autoprefixer: 10.4.21(postcss@8.5.3) + browserslist: 4.24.4 + css-blank-pseudo: 3.0.3(postcss@8.5.3) + css-has-pseudo: 3.0.4(postcss@8.5.3) + css-prefers-color-scheme: 6.0.3(postcss@8.5.3) + cssdb: 7.11.2 + postcss: 8.5.3 + postcss-attribute-case-insensitive: 5.0.2(postcss@8.5.3) + postcss-clamp: 4.1.0(postcss@8.5.3) + postcss-color-functional-notation: 4.2.4(postcss@8.5.3) + postcss-color-hex-alpha: 8.0.4(postcss@8.5.3) + postcss-color-rebeccapurple: 7.1.1(postcss@8.5.3) + postcss-custom-media: 8.0.2(postcss@8.5.3) + postcss-custom-properties: 12.1.11(postcss@8.5.3) + postcss-custom-selectors: 6.0.3(postcss@8.5.3) + postcss-dir-pseudo-class: 6.0.5(postcss@8.5.3) + postcss-double-position-gradients: 3.1.2(postcss@8.5.3) + postcss-env-function: 4.0.6(postcss@8.5.3) + postcss-focus-visible: 6.0.4(postcss@8.5.3) + postcss-focus-within: 5.0.4(postcss@8.5.3) + postcss-font-variant: 5.0.0(postcss@8.5.3) + postcss-gap-properties: 3.0.5(postcss@8.5.3) + postcss-image-set-function: 4.0.7(postcss@8.5.3) + postcss-initial: 4.0.1(postcss@8.5.3) + postcss-lab-function: 4.2.1(postcss@8.5.3) + postcss-logical: 5.0.4(postcss@8.5.3) + postcss-media-minmax: 5.0.0(postcss@8.5.3) + postcss-nesting: 10.2.0(postcss@8.5.3) + postcss-opacity-percentage: 1.1.3(postcss@8.5.3) + postcss-overflow-shorthand: 3.0.4(postcss@8.5.3) + postcss-page-break: 3.0.4(postcss@8.5.3) + postcss-place: 7.0.5(postcss@8.5.3) + postcss-pseudo-class-any-link: 7.1.6(postcss@8.5.3) + postcss-replace-overflow-wrap: 4.0.0(postcss@8.5.3) + postcss-selector-not: 6.0.1(postcss@8.5.3) + postcss-value-parser: 4.2.0 + + postcss-pseudo-class-any-link@6.0.0: + dependencies: + postcss: 7.0.32 + postcss-selector-parser: 5.0.0 + + postcss-pseudo-class-any-link@7.1.6(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-reduce-initial@5.1.2(postcss@8.5.3): + dependencies: + browserslist: 4.24.4 + caniuse-api: 3.0.0 + postcss: 8.5.3 + + postcss-reduce-transforms@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-replace-overflow-wrap@3.0.0: + dependencies: + postcss: 7.0.32 + + postcss-replace-overflow-wrap@4.0.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-safe-parser@4.0.2: + dependencies: + postcss: 7.0.32 + + postcss-selector-matches@4.0.0: + dependencies: + balanced-match: 1.0.2 + postcss: 7.0.32 + + postcss-selector-not@4.0.1: + dependencies: + balanced-match: 1.0.2 + postcss: 7.0.32 + + postcss-selector-not@6.0.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-selector-parser@5.0.0: + dependencies: + cssesc: 2.0.0 + indexes-of: 1.0.1 + uniq: 1.0.1 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-selector-parser@7.1.0: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-strip-inline-comments@0.1.5: + dependencies: + postcss: 5.2.18 + + postcss-svgo@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + svgo: 2.8.0 + + postcss-unique-selectors@5.1.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-value-parser@4.2.0: {} + + postcss-values-parser@2.0.1: + dependencies: + flatten: 1.0.3 + indexes-of: 1.0.1 + uniq: 1.0.1 + + postcss@5.2.18: + dependencies: + chalk: 1.1.3 + js-base64: 2.6.4 + source-map: 0.5.7 + supports-color: 3.2.3 + + postcss@7.0.32: + dependencies: + chalk: 2.4.2 + source-map: 0.6.1 + supports-color: 6.1.0 + + postcss@7.0.39: + dependencies: + picocolors: 0.2.1 + source-map: 0.6.1 + + postcss@8.5.3: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + potpack@1.0.2: {} + + potpack@2.0.0: {} + + prelude-ls@1.1.2: {} + + prelude-ls@1.2.1: {} + + prepend-http@1.0.4: {} + + preserve@0.2.0: + optional: true + + prettier@2.2.1: {} + + prettier@2.8.8: {} + + pretty-bytes@5.6.0: {} + + pretty-error@2.1.2: + dependencies: + lodash: 4.17.21 + renderkid: 2.0.7 + + pretty-error@4.0.0: + dependencies: + lodash: 4.17.21 + renderkid: 3.0.0 + + pretty-format@26.6.2: + dependencies: + '@jest/types': 26.6.2 + ansi-regex: 5.0.1 + ansi-styles: 4.3.0 + react-is: 17.0.2 + + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + + pretty-format@28.1.3: + dependencies: + '@jest/schemas': 28.1.3 + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + printj@1.1.2: {} + + prism-react-renderer@1.3.5(react@16.14.0): + dependencies: + react: 16.14.0 + + prism-react@1.0.2(react@16.14.0): + dependencies: + react: 16.14.0 + recompose: 0.22.0(react@16.14.0) + + prism-redux@1.0.2: {} + + prism@4.1.2(react@16.14.0): + dependencies: + prism-react: 1.0.2(react@16.14.0) + prism-redux: 1.0.2 + transitivePeerDependencies: + - react + + private@0.1.8: {} + + probe.gl@3.6.0: + dependencies: + '@babel/runtime': 7.27.0 + '@probe.gl/env': 3.6.0 + '@probe.gl/log': 3.6.0 + '@probe.gl/stats': 3.6.0 + + process-nextick-args@2.0.1: {} + + process@0.11.10: {} + + promise@7.3.1: + dependencies: + asap: 2.0.6 + + promise@8.3.0: + dependencies: + asap: 2.0.6 + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + + protocol-buffers-schema@3.6.0: {} + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + proxy-from-env@1.1.0: {} + + pseudomap@1.0.2: {} + + psl@1.15.0: + dependencies: + punycode: 2.3.1 + + public-encrypt@4.0.3: + dependencies: + bn.js: 4.12.2 + browserify-rsa: 4.1.1 + create-hash: 1.2.0 + parse-asn1: 5.1.7 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + + pump@3.0.2: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + + punycode@1.4.1: {} + + punycode@2.3.1: {} + + pure-color@1.3.0: {} + + q@1.5.1: {} + + qs@6.13.0: + dependencies: + side-channel: 1.1.0 + + qs@6.14.0: + dependencies: + side-channel: 1.1.0 + + query-string@4.3.4: + dependencies: + object-assign: 4.1.1 + strict-uri-encode: 1.1.0 + + query-string@6.14.1: + dependencies: + decode-uri-component: 0.2.2 + filter-obj: 1.1.0 + split-on-first: 1.1.0 + strict-uri-encode: 2.0.0 + + query-string@8.2.0: + dependencies: + decode-uri-component: 0.4.1 + filter-obj: 5.1.0 + split-on-first: 3.0.0 + + query-string@9.1.1: + dependencies: + decode-uri-component: 0.4.1 + filter-obj: 5.1.0 + split-on-first: 3.0.0 + + querystring-es3@0.2.1: {} + + querystringify@2.2.0: {} + + queue-microtask@1.2.3: {} + + quickselect@2.0.0: {} + + raf-schd@4.0.3: {} + + raf@3.4.1: + dependencies: + performance-now: 2.1.0 + + ramda@0.27.2: {} + + randexp@0.5.3: + dependencies: + drange: 1.1.1 + ret: 0.2.2 + + randomatic@3.1.1: + dependencies: + is-number: 4.0.0 + kind-of: 6.0.3 + math-random: 1.0.4 + optional: true + + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + + randomfill@1.0.4: + dependencies: + randombytes: 2.1.0 + safe-buffer: 5.2.1 + + range-parser@1.2.1: {} + + raw-body@2.5.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + rc-align@2.4.5: + dependencies: + babel-runtime: 6.26.0 + dom-align: 1.12.4 + prop-types: 15.8.1 + rc-util: 4.21.1 + + rc-align@4.0.15(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + dom-align: 1.12.4 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + resize-observer-polyfill: 1.5.1 + + rc-animate@2.11.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + css-animation: 1.6.1 + prop-types: 15.8.1 + raf: 3.4.1 + rc-util: 4.21.1 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + react-lifecycles-compat: 3.0.4 + + rc-cascader@3.33.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-select: 14.16.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-tree: 5.13.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-cascader@3.7.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + array-tree-filter: 2.1.0 + classnames: 2.5.1 + rc-select: 14.1.18(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-tree: 5.7.12(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-checkbox@2.0.3: + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + prop-types: 15.8.1 + rc-util: 4.21.1 + + rc-checkbox@3.0.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-checkbox@3.5.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-collapse@1.9.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + classnames: 2.5.1 + css-animation: 1.6.1 + prop-types: 15.8.1 + rc-animate: 2.11.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + transitivePeerDependencies: + - react + - react-dom + + rc-collapse@3.4.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + shallowequal: 1.1.0 + + rc-collapse@3.9.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-dialog@9.0.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + '@rc-component/portal': 1.1.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-dialog@9.6.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + '@rc-component/portal': 1.1.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-drawer@6.3.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + '@rc-component/portal': 1.1.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-drawer@7.2.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + '@rc-component/portal': 1.1.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-dropdown@3.6.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-trigger: 5.3.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-dropdown@4.0.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-trigger: 5.3.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-dropdown@4.2.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + '@rc-component/trigger': 2.2.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-editor-core@0.8.10(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + draft-js: 0.10.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + immutable: 3.7.6 + lodash: 4.17.21 + prop-types: 15.8.1 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + setimmediate: 1.0.5 + + rc-editor-mention@1.1.13(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + dom-scroll-into-view: 1.2.1 + draft-js: 0.10.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + immutable: 3.7.6 + prop-types: 15.8.1 + rc-animate: 2.11.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-editor-core: 0.8.10(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-field-form@1.38.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + async-validator: 4.2.5 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-field-form@1.44.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + async-validator: 4.2.5 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-field-form@2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + '@rc-component/async-validator': 5.0.4 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-form@2.4.12(prop-types@15.8.1): + dependencies: + async-validator: 1.11.5 + babel-runtime: 6.26.0 + create-react-class: 15.7.0 + dom-scroll-into-view: 1.2.1 + hoist-non-react-statics: 3.3.2 + lodash: 4.17.21 + prop-types: 15.8.1 + rc-util: 4.21.1 + react-is: 16.13.1 + warning: 4.0.3 + + rc-gesture@0.0.22: + dependencies: + babel-runtime: 6.26.0 + + rc-image@5.13.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + '@rc-component/portal': 1.1.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + rc-dialog: 9.0.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-image@7.11.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + '@rc-component/portal': 1.1.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + rc-dialog: 9.6.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-input-number@7.3.11(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-input-number@9.5.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + '@rc-component/mini-decimal': 1.1.0 + classnames: 2.5.1 + rc-input: 1.8.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-input@0.1.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-input@1.8.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-mentions@1.13.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-menu: 9.8.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-textarea: 0.4.7(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-trigger: 5.3.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-mentions@2.20.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + '@rc-component/trigger': 2.2.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + rc-input: 1.8.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-menu: 9.16.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-textarea: 1.10.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-menu@9.16.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + '@rc-component/trigger': 2.2.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-overflow: 1.4.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-menu@9.8.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-overflow: 1.4.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-trigger: 5.3.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-motion@2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-notification@4.6.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-notification@5.6.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-overflow@1.4.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-resize-observer: 1.4.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-pagination@3.2.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-pagination@5.1.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-picker@2.7.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + date-fns: 2.30.0 + dayjs: 1.11.13 + moment: 2.30.1 + rc-trigger: 5.3.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + shallowequal: 1.1.0 + + rc-picker@4.11.3(date-fns@2.30.0)(dayjs@1.11.13)(moment@2.30.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + '@rc-component/trigger': 2.2.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + rc-overflow: 1.4.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-resize-observer: 1.4.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + optionalDependencies: + date-fns: 2.30.0 + dayjs: 1.11.13 + moment: 2.30.1 + + rc-progress@3.4.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-progress@4.0.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-rate@2.13.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-rate@2.9.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-resize-observer@0.2.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + resize-observer-polyfill: 1.5.1 + + rc-resize-observer@1.4.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + resize-observer-polyfill: 1.5.1 + + rc-segmented@2.3.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-segmented@2.7.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-select@14.1.18(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-overflow: 1.4.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-trigger: 5.3.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-virtual-list: 3.18.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-select@14.16.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + '@rc-component/trigger': 2.2.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-overflow: 1.4.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-virtual-list: 3.18.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-slider@10.0.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + shallowequal: 1.1.0 + + rc-slider@11.1.8(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-slider@8.2.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + prop-types: 15.8.1 + rc-tooltip: 3.7.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 4.21.1 + shallowequal: 1.1.0 + warning: 3.0.0 + transitivePeerDependencies: + - react + - react-dom + + rc-steps@5.0.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-steps@6.0.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-swipeout@2.0.11: + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + rc-gesture: 0.0.22 + react-native-swipeout: 2.3.6 + + rc-switch@3.2.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-switch@4.1.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-table@7.26.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-resize-observer: 1.4.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + shallowequal: 1.1.0 + + rc-table@7.50.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + '@rc-component/context': 1.4.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + rc-resize-observer: 1.4.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-virtual-list: 3.18.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-tabs@12.5.10(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-dropdown: 4.0.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-menu: 9.8.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-resize-observer: 1.4.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-tabs@15.6.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-dropdown: 4.2.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-menu: 9.16.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-resize-observer: 1.4.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-textarea@0.4.7(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-resize-observer: 1.4.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + shallowequal: 1.1.0 + + rc-textarea@1.10.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-input: 1.8.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-resize-observer: 1.4.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-tooltip@3.7.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + babel-runtime: 6.26.0 + prop-types: 15.8.1 + rc-trigger: 2.6.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + transitivePeerDependencies: + - react + - react-dom + + rc-tooltip@5.2.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-trigger: 5.3.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-tooltip@6.4.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + '@rc-component/trigger': 2.2.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-tree-select@5.27.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-select: 14.16.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-tree: 5.13.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-tree-select@5.5.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-select: 14.1.18(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-tree: 5.7.12(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-tree@5.13.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-virtual-list: 3.18.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-tree@5.7.12(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-virtual-list: 3.18.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-trigger@2.6.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + prop-types: 15.8.1 + rc-align: 2.4.5 + rc-animate: 2.11.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 4.21.1 + react-lifecycles-compat: 3.0.4 + transitivePeerDependencies: + - react + - react-dom + + rc-trigger@5.3.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-align: 4.0.15(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-motion: 2.9.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-upload@4.3.6(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-upload@4.8.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + rc-util@4.21.1: + dependencies: + add-dom-event-listener: 1.1.0 + prop-types: 15.8.1 + react-is: 16.13.1 + react-lifecycles-compat: 3.0.4 + shallowequal: 1.1.0 + + rc-util@5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + react-is: 18.3.1 + + rc-virtual-list@3.18.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + classnames: 2.5.1 + rc-resize-observer: 1.4.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 5.44.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + react-app-polyfill@3.0.0: + dependencies: + core-js: 3.41.0 + object-assign: 4.1.1 + promise: 8.3.0 + raf: 3.4.1 + regenerator-runtime: 0.13.11 + whatwg-fetch: 3.6.20 + + react-base16-styling@0.6.0: + dependencies: + base16: 1.0.0 + lodash.curry: 4.1.1 + lodash.flow: 3.5.0 + pure-color: 1.3.0 + + react-beautiful-dnd@12.2.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime-corejs2': 7.27.0 + css-box-model: 1.2.1 + memoize-one: 5.2.1 + raf-schd: 4.0.3 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + react-redux: 7.2.9(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + redux: 4.2.1 + use-memo-one: 1.1.3(react@16.14.0) + transitivePeerDependencies: + - react-native + + react-color@2.17.1(react@16.14.0): + dependencies: + '@icons/material': 0.2.4(react@16.14.0) + lodash: 4.17.21 + material-colors: 1.2.6 + prop-types: 15.8.1 + react: 16.14.0 + reactcss: 1.2.3(react@16.14.0) + tinycolor2: 1.6.0 + + react-color@2.17.3(react@16.14.0): + dependencies: + '@icons/material': 0.2.4(react@16.14.0) + lodash: 4.17.21 + material-colors: 1.2.6 + prop-types: 15.8.1 + react: 16.14.0 + reactcss: 1.2.3(react@16.14.0) + tinycolor2: 1.6.0 + + react-content-loader@5.1.4(react@16.14.0): + dependencies: + react: 16.14.0 + + react-copy-to-clipboard@5.1.0(react@16.14.0): + dependencies: + copy-to-clipboard: 3.3.3 + prop-types: 15.8.1 + react: 16.14.0 + + react-dev-utils@12.0.1(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5)(webpack@5.99.7): + dependencies: + '@babel/code-frame': 7.26.2 + address: 1.2.2 + browserslist: 4.24.4 + chalk: 4.1.2 + cross-spawn: 7.0.6 + detect-port-alt: 1.1.6 + escape-string-regexp: 4.0.0 + filesize: 8.0.7 + find-up: 5.0.0 + fork-ts-checker-webpack-plugin: 6.5.3(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5)(webpack@5.99.7) + global-modules: 2.0.0 + globby: 11.1.0 + gzip-size: 6.0.0 + immer: 9.0.21 + is-root: 2.1.0 + loader-utils: 3.3.1 + open: 8.4.2 + pkg-up: 3.1.0 + prompts: 2.4.2 + react-error-overlay: 6.1.0 + recursive-readdir: 2.2.3 + shell-quote: 1.8.2 + strip-ansi: 6.0.1 + text-table: 0.2.0 + webpack: 5.99.7 + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - eslint + - supports-color + - vue-template-compiler + + react-dom@16.14.0(react@16.14.0): + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + prop-types: 15.8.1 + react: 16.14.0 + scheduler: 0.19.1 + + react-error-overlay@6.1.0: {} + + react-fast-compare@3.2.2: {} + + react-helmet@6.1.0(react@16.14.0): + dependencies: + object-assign: 4.1.1 + prop-types: 15.8.1 + react: 16.14.0 + react-fast-compare: 3.2.2 + react-side-effect: 2.1.2(react@16.14.0) + + react-intl@3.12.1(react@16.14.0): + dependencies: + '@formatjs/intl-displaynames': 1.2.10 + '@formatjs/intl-listformat': 1.4.8 + '@formatjs/intl-relativetimeformat': 4.5.16 + '@formatjs/intl-unified-numberformat': 3.3.7 + '@formatjs/intl-utils': 2.3.0 + '@types/hoist-non-react-statics': 3.3.6 + '@types/invariant': 2.2.37 + hoist-non-react-statics: 3.3.2 + intl-format-cache: 4.3.1 + intl-messageformat: 7.8.4 + intl-messageformat-parser: 3.6.4 + react: 16.14.0 + shallow-equal: 1.2.1 + + react-is@16.13.1: {} + + react-is@17.0.2: {} + + react-is@18.3.1: {} + + react-json-view@1.21.3(@types/react@17.0.52)(encoding@0.1.13)(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + flux: 4.0.4(encoding@0.1.13)(react@16.14.0) + react: 16.14.0 + react-base16-styling: 0.6.0 + react-dom: 16.14.0(react@16.14.0) + react-lifecycles-compat: 3.0.4 + react-textarea-autosize: 8.5.9(@types/react@17.0.52)(react@16.14.0) + transitivePeerDependencies: + - '@types/react' + - encoding + + react-lifecycles-compat@3.0.4: {} + + react-native-swipeout@2.3.6: + dependencies: + create-react-class: 15.7.0 + prop-types: 15.8.1 + react-tween-state: 0.1.5 + + react-redux@7.2.9(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + '@types/react-redux': 7.1.34 + hoist-non-react-statics: 3.3.2 + loose-envify: 1.4.0 + prop-types: 15.8.1 + react: 16.14.0 + react-is: 17.0.2 + optionalDependencies: + react-dom: 16.14.0(react@16.14.0) + + react-refresh@0.10.0: {} + + react-refresh@0.11.0: {} + + react-resize-detector@7.1.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + lodash: 4.17.21 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + react-router-config@5.1.1(react-router@5.2.0(react@16.14.0))(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + react: 16.14.0 + react-router: 5.2.0(react@16.14.0) + + react-router-dom@5.2.0(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + history: 4.10.1 + loose-envify: 1.4.0 + prop-types: 15.8.1 + react: 16.14.0 + react-router: 5.2.0(react@16.14.0) + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + + react-router-dom@5.3.4(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + history: 4.10.1 + loose-envify: 1.4.0 + prop-types: 15.8.1 + react: 16.14.0 + react-router: 5.3.4(react@16.14.0) + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + + react-router@5.2.0(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + history: 4.10.1 + hoist-non-react-statics: 3.3.2 + loose-envify: 1.4.0 + mini-create-react-context: 0.4.1(prop-types@15.8.1)(react@16.14.0) + path-to-regexp: 1.9.0 + prop-types: 15.8.1 + react: 16.14.0 + react-is: 16.13.1 + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + + react-router@5.3.4(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + history: 4.10.1 + hoist-non-react-statics: 3.3.2 + loose-envify: 1.4.0 + path-to-regexp: 1.9.0 + prop-types: 15.8.1 + react: 16.14.0 + react-is: 16.13.1 + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + + react-scripts@5.0.1(@babel/plugin-syntax-flow@7.26.0(@babel/core@7.26.10))(@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.10))(@types/babel__core@7.20.5)(@types/webpack@4.41.40)(eslint@9.25.1(jiti@1.21.7))(node-notifier@8.0.2)(react@16.14.0)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5))(type-fest@2.19.0)(typescript@4.9.5): + dependencies: + '@babel/core': 7.26.10 + '@pmmmwh/react-refresh-webpack-plugin': 0.5.16(@types/webpack@4.41.40)(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.15.2(webpack@5.99.7))(webpack@5.99.7) + '@svgr/webpack': 5.5.0 + babel-jest: 27.5.1(@babel/core@7.26.10) + babel-loader: 8.4.1(@babel/core@7.26.10)(webpack@5.99.7) + babel-plugin-named-asset-import: 0.3.8(@babel/core@7.26.10) + babel-preset-react-app: 10.1.0 + bfj: 7.1.0 + browserslist: 4.24.4 + camelcase: 6.3.0 + case-sensitive-paths-webpack-plugin: 2.4.0 + css-loader: 6.11.0(webpack@5.99.7) + css-minimizer-webpack-plugin: 3.4.1(webpack@5.99.7) + dotenv: 10.0.0 + dotenv-expand: 5.1.0 + eslint: 9.25.1(jiti@1.21.7) + eslint-config-react-app: 7.0.1(@babel/plugin-syntax-flow@7.26.0(@babel/core@7.26.10))(@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.10))(eslint@9.25.1(jiti@1.21.7))(jest@27.5.1(node-notifier@8.0.2)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)))(typescript@4.9.5) + eslint-webpack-plugin: 3.2.0(eslint@9.25.1(jiti@1.21.7))(webpack@5.99.7) + file-loader: 6.2.0(webpack@5.99.7) + fs-extra: 10.1.0 + html-webpack-plugin: 5.6.3(webpack@5.99.7) + identity-obj-proxy: 3.0.0 + jest: 27.5.1(node-notifier@8.0.2)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + jest-resolve: 27.5.1 + jest-watch-typeahead: 1.1.0(jest@27.5.1(node-notifier@8.0.2)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5))) + mini-css-extract-plugin: 2.9.2(webpack@5.99.7) + postcss: 8.5.3 + postcss-flexbugs-fixes: 5.0.2(postcss@8.5.3) + postcss-loader: 6.2.1(postcss@8.5.3)(webpack@5.99.7) + postcss-normalize: 10.0.1(browserslist@4.24.4)(postcss@8.5.3) + postcss-preset-env: 7.8.3(postcss@8.5.3) + prompts: 2.4.2 + react: 16.14.0 + react-app-polyfill: 3.0.0 + react-dev-utils: 12.0.1(eslint@9.25.1(jiti@1.21.7))(typescript@4.9.5)(webpack@5.99.7) + react-refresh: 0.11.0 + resolve: 1.22.10 + resolve-url-loader: 4.0.0 + sass-loader: 12.6.0(webpack@5.99.7) + semver: 7.7.1 + source-map-loader: 3.0.2(webpack@5.99.7) + style-loader: 3.3.4(webpack@5.99.7) + tailwindcss: 3.4.17(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + terser-webpack-plugin: 5.3.14(webpack@5.99.7) + webpack: 5.99.7 + webpack-dev-server: 4.15.2(webpack@5.99.7) + webpack-manifest-plugin: 4.1.1(webpack@5.99.7) + workbox-webpack-plugin: 6.6.0(@types/babel__core@7.20.5)(webpack@5.99.7) + optionalDependencies: + fsevents: 2.3.3 + typescript: 4.9.5 + transitivePeerDependencies: + - '@babel/plugin-syntax-flow' + - '@babel/plugin-transform-react-jsx' + - '@parcel/css' + - '@rspack/core' + - '@swc/core' + - '@types/babel__core' + - '@types/webpack' + - bufferutil + - canvas + - clean-css + - csso + - debug + - esbuild + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - fibers + - node-notifier + - node-sass + - rework + - rework-visit + - sass + - sass-embedded + - sockjs-client + - supports-color + - ts-node + - type-fest + - uglify-js + - utf-8-validate + - vue-template-compiler + - webpack-cli + - webpack-hot-middleware + - webpack-plugin-serve + + react-side-effect@2.1.2(react@16.14.0): + dependencies: + react: 16.14.0 + + react-split-pane@0.1.92(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + prop-types: 15.8.1 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + react-lifecycles-compat: 3.0.4 + react-style-proptype: 3.2.2 + + react-sticky-mouse-tooltip@0.0.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + react-style-proptype@3.2.2: + dependencies: + prop-types: 15.8.1 + + react-textarea-autosize@8.5.9(@types/react@17.0.52)(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + react: 16.14.0 + use-composed-ref: 1.4.0(@types/react@17.0.52)(react@16.14.0) + use-latest: 1.3.0(@types/react@17.0.52)(react@16.14.0) + transitivePeerDependencies: + - '@types/react' + + react-tween-state@0.1.5: + dependencies: + raf: 3.4.1 + tween-functions: 1.2.0 + + react-universal-interface@0.6.2(react@16.14.0)(tslib@2.8.1): + dependencies: + react: 16.14.0 + tslib: 2.8.1 + + react-use@17.3.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@types/js-cookie': 2.2.7 + '@xobotyi/scrollbar-width': 1.9.5 + copy-to-clipboard: 3.3.3 + fast-deep-equal: 3.1.3 + fast-shallow-equal: 1.0.0 + js-cookie: 2.2.1 + nano-css: 5.6.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + react-universal-interface: 0.6.2(react@16.14.0)(tslib@2.8.1) + resize-observer-polyfill: 1.5.1 + screenfull: 5.2.0 + set-harmonic-interval: 1.0.1 + throttle-debounce: 3.0.1 + ts-easing: 0.2.0 + tslib: 2.8.1 + + react@16.14.0: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + prop-types: 15.8.1 + + reactcss@1.2.3(react@16.14.0): + dependencies: + lodash: 4.17.21 + react: 16.14.0 + + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + + read-pkg-up@7.0.1: + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + + read-pkg@5.2.0: + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@2.2.1: + dependencies: + graceful-fs: 4.2.11 + micromatch: 3.1.10 + readable-stream: 2.3.8 + transitivePeerDependencies: + - supports-color + optional: true + + readdirp@3.5.0: + dependencies: + picomatch: 2.3.1 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + recompose@0.22.0(react@16.14.0): + dependencies: + change-emitter: 0.1.6 + fbjs: 0.8.18 + hoist-non-react-statics: 1.2.0 + react: 16.14.0 + symbol-observable: 1.2.0 + + recursive-readdir@2.2.3: + dependencies: + minimatch: 3.1.2 + + redbox-react@1.6.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + error-stack-parser: 1.3.6 + object-assign: 4.1.1 + prop-types: 15.8.1 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + sourcemapped-stacktrace: 1.1.11 + + redux-saga@0.16.2: {} + + redux@4.2.1: + dependencies: + '@babel/runtime': 7.27.0 + + reflect-metadata@0.1.14: {} + + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + reftools@1.1.9: {} + + regenerate-unicode-properties@10.0.1: + dependencies: + regenerate: 1.4.2 + + regenerate-unicode-properties@10.2.0: + dependencies: + regenerate: 1.4.2 + + regenerate@1.4.2: {} + + regenerator-runtime@0.10.5: {} + + regenerator-runtime@0.11.1: {} + + regenerator-runtime@0.13.11: {} + + regenerator-runtime@0.13.5: {} + + regenerator-runtime@0.14.1: {} + + regenerator-transform@0.10.1: + dependencies: + babel-runtime: 6.26.0 + babel-types: 6.26.0 + private: 0.1.8 + + regenerator-transform@0.15.2: + dependencies: + '@babel/runtime': 7.27.0 + + regex-cache@0.4.4: + dependencies: + is-equal-shallow: 0.1.3 + optional: true + + regex-not@1.0.2: + dependencies: + extend-shallow: 3.0.2 + safe-regex: 1.1.0 + + regex-parser@2.3.1: {} + + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + regexpu-core@2.0.0: + dependencies: + regenerate: 1.4.2 + regjsgen: 0.2.0 + regjsparser: 0.1.5 + + regexpu-core@6.2.0: + dependencies: + regenerate: 1.4.2 + regenerate-unicode-properties: 10.2.0 + regjsgen: 0.8.0 + regjsparser: 0.12.0 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.2.0 + + regjsgen@0.2.0: {} + + regjsgen@0.8.0: {} + + regjsparser@0.1.5: + dependencies: + jsesc: 0.5.0 + + regjsparser@0.12.0: + dependencies: + jsesc: 3.0.2 + + regl@1.6.1: {} + + regl@1.7.0: {} + + relateurl@0.2.7: {} + + remove-trailing-separator@1.1.0: {} + + renderkid@2.0.7: + dependencies: + css-select: 4.3.0 + dom-converter: 0.2.0 + htmlparser2: 6.1.0 + lodash: 4.17.21 + strip-ansi: 3.0.1 + + renderkid@3.0.0: + dependencies: + css-select: 4.3.0 + dom-converter: 0.2.0 + htmlparser2: 6.1.0 + lodash: 4.17.21 + strip-ansi: 6.0.1 + + repeat-element@1.1.4: {} + + repeat-string@1.6.1: {} + + repeating@2.0.1: + dependencies: + is-finite: 1.1.0 + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + require-main-filename@2.0.0: {} + + requires-port@1.0.0: {} + + reserved-words@0.1.2: {} + + resize-observer-polyfill@1.5.1: {} + + resolve-cwd@3.0.0: + dependencies: + resolve-from: 5.0.0 + + resolve-from@3.0.0: {} + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve-pathname@3.0.0: {} + + resolve-protobuf-schema@2.1.0: + dependencies: + protocol-buffers-schema: 3.6.0 + + resolve-url-loader@4.0.0: + dependencies: + adjust-sourcemap-loader: 4.0.0 + convert-source-map: 1.9.0 + loader-utils: 2.0.4 + postcss: 7.0.39 + source-map: 0.6.1 + + resolve-url@0.2.1: {} + + resolve.exports@1.1.1: {} + + resolve@1.22.10: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + resolve@2.0.0-next.5: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + restore-cursor@3.1.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + + ret@0.1.15: {} + + ret@0.2.2: {} + + retry@0.13.1: {} + + reusify@1.1.0: {} + + rfdc@1.4.1: {} + + right-align@0.1.3: + dependencies: + align-text: 0.1.4 + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + ripemd160@2.0.2: + dependencies: + hash-base: 3.0.5 + inherits: 2.0.4 + + rmc-align@1.0.0: + dependencies: + babel-runtime: 6.26.0 + dom-align: 1.12.4 + rc-util: 4.21.1 + + rmc-calendar@1.1.4(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + babel-runtime: 6.26.0 + rc-animate: 2.11.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rmc-date-picker: 6.0.10(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + transitivePeerDependencies: + - react + - react-dom + + rmc-cascader@5.0.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + array-tree-filter: 2.1.0 + babel-runtime: 6.26.0 + rmc-picker: 5.0.10(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + transitivePeerDependencies: + - react + - react-dom + + rmc-date-picker@6.0.10(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + babel-runtime: 6.26.0 + rmc-picker: 5.0.10(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + transitivePeerDependencies: + - react + - react-dom + + rmc-dialog@1.1.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + babel-runtime: 6.26.0 + rc-animate: 2.11.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + transitivePeerDependencies: + - react + - react-dom + + rmc-drawer@0.4.11: + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + prop-types: 15.8.1 + + rmc-feedback@2.0.0: + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + + rmc-input-number@1.0.5: + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + rmc-feedback: 2.0.0 + + rmc-list-view@0.11.5: + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + fbjs: 0.8.18 + prop-types: 15.8.1 + warning: 3.0.0 + zscroller: 0.4.8 + + rmc-notification@1.0.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + prop-types: 15.8.1 + rc-animate: 2.11.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 4.21.1 + transitivePeerDependencies: + - react + - react-dom + + rmc-nuka-carousel@3.0.1: + dependencies: + exenv: 1.2.2 + raf: 3.4.1 + + rmc-picker@5.0.10(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + rmc-dialog: 1.1.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rmc-feedback: 2.0.0 + transitivePeerDependencies: + - react + - react-dom + + rmc-pull-to-refresh@1.0.13: + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + + rmc-steps@1.0.1: + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + + rmc-tabs@1.2.29: + dependencies: + babel-runtime: 6.26.0 + rc-gesture: 0.0.22 + + rmc-tooltip@1.0.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + babel-runtime: 6.26.0 + rmc-trigger: 1.0.12(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + transitivePeerDependencies: + - react + - react-dom + + rmc-trigger@1.0.12(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + babel-runtime: 6.26.0 + rc-animate: 2.11.1(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + rc-util: 4.21.1 + rmc-align: 1.0.0 + transitivePeerDependencies: + - react + - react-dom + + robust-predicates@3.0.2: {} + + rollup-plugin-terser@7.0.2(rollup@2.79.2): + dependencies: + '@babel/code-frame': 7.26.2 + jest-worker: 26.6.2 + rollup: 2.79.2 + serialize-javascript: 4.0.0 + terser: 5.39.0 + + rollup@0.25.8: + dependencies: + chalk: 1.1.3 + minimist: 1.2.8 + source-map-support: 0.3.3 + + rollup@2.79.2: + optionalDependencies: + fsevents: 2.3.3 + + rsvp@4.8.5: {} + + rtl-css-js@1.16.1: + dependencies: + '@babel/runtime': 7.27.0 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + runscript@1.6.0: + dependencies: + is-type-of: 1.4.0 + + rw@1.3.3: {} + + rxjs@6.6.7: + dependencies: + tslib: 1.14.1 + + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + + safe-array-concat@1.1.3: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + + safe-buffer@5.1.2: {} + + safe-buffer@5.2.1: {} + + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safe-regex@1.1.0: + dependencies: + ret: 0.1.15 + + safe-stable-stringify@2.5.0: {} + + safer-buffer@2.1.2: {} + + sane@4.1.0: + dependencies: + '@cnakazawa/watch': 1.0.4 + anymatch: 2.0.0 + capture-exit: 2.0.0 + exec-sh: 0.3.6 + execa: 1.0.0 + fb-watchman: 2.0.2 + micromatch: 3.1.10 + minimist: 1.2.8 + walker: 1.0.8 + transitivePeerDependencies: + - supports-color + + sanitize.css@13.0.0: {} + + sass-loader@12.6.0(webpack@5.99.7): + dependencies: + klona: 2.0.6 + neo-async: 2.6.2 + webpack: 5.99.7 + + sax@1.2.4: {} + + saxes@5.0.1: + dependencies: + xmlchars: 2.2.0 + + scheduler@0.19.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + + schema-utils@1.0.0: + dependencies: + ajv: 6.12.6 + ajv-errors: 1.0.1(ajv@6.12.6) + ajv-keywords: 3.5.2(ajv@6.12.6) + + schema-utils@2.7.0: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + + schema-utils@2.7.1: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + + schema-utils@3.3.0: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + + schema-utils@4.3.2: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) + ajv-keywords: 5.1.0(ajv@8.17.1) + + screenfull@5.2.0: {} + + screenfull@6.0.2: {} + + script-ext-html-webpack-plugin@2.1.5(html-webpack-plugin@4.5.2(webpack@5.99.7))(webpack@5.99.7): + dependencies: + debug: 4.4.0 + html-webpack-plugin: 4.5.2(webpack@5.99.7) + webpack: 5.99.7 + transitivePeerDependencies: + - supports-color + + scroll-into-view-if-needed@2.2.31: + dependencies: + compute-scroll-into-view: 1.0.20 + + scroll-into-view-if-needed@3.1.0: + dependencies: + compute-scroll-into-view: 3.1.1 + + scroll-into-view@1.16.2: {} + + seamless-immutable@7.1.4: {} + + select-hose@2.0.0: {} + + selfsigned@2.4.1: + dependencies: + '@types/node-forge': 1.3.11 + node-forge: 1.3.1 + + semver-compare@1.0.0: {} + + semver@5.7.2: {} + + semver@6.3.1: {} + + semver@7.7.1: {} + + send@0.19.0: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + + serialize-javascript@4.0.0: + dependencies: + randombytes: 2.1.0 + + serialize-javascript@6.0.2: + dependencies: + randombytes: 2.1.0 + + serve-index@1.9.1: + dependencies: + accepts: 1.3.8 + batch: 0.6.1 + debug: 2.6.9 + escape-html: 1.0.3 + http-errors: 1.6.3 + mime-types: 2.1.35 + parseurl: 1.3.3 + transitivePeerDependencies: + - supports-color + + serve-static@1.16.2: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.0 + transitivePeerDependencies: + - supports-color + + set-blocking@2.0.0: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + set-harmonic-interval@1.0.1: {} + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + + set-value@2.0.1: + dependencies: + extend-shallow: 2.0.1 + is-extendable: 0.1.1 + is-plain-object: 2.0.4 + split-string: 3.1.0 + + setimmediate@1.0.5: {} + + setprototypeof@1.1.0: {} + + setprototypeof@1.2.0: {} + + sha.js@2.4.11: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + + shallow-equal@1.2.1: {} + + shallowequal@1.1.0: {} + + shebang-command@1.2.0: + dependencies: + shebang-regex: 1.0.0 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@1.0.0: {} + + shebang-regex@3.0.0: {} + + shell-quote@1.8.2: {} + + shellwords@0.1.1: + optional: true + + should-equal@2.0.0: + dependencies: + should-type: 1.4.0 + + should-format@3.0.3: + dependencies: + should-type: 1.4.0 + should-type-adaptors: 1.1.0 + + should-type-adaptors@1.1.0: + dependencies: + should-type: 1.4.0 + should-util: 1.0.1 + + should-type@1.4.0: {} + + should-util@1.0.1: {} + + should@13.2.3: + dependencies: + should-equal: 2.0.0 + should-format: 3.0.3 + should-type: 1.4.0 + should-type-adaptors: 1.1.0 + should-util: 1.0.1 + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + + sisteransi@1.0.5: {} + + size-sensor@1.0.2: {} + + slash@1.0.0: {} + + slash@2.0.0: {} + + slash@3.0.0: {} + + slash@4.0.0: {} + + slice-ansi@3.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + + slice-ansi@4.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + + snapdragon-node@2.1.1: + dependencies: + define-property: 1.0.0 + isobject: 3.0.1 + snapdragon-util: 3.0.1 + + snapdragon-util@3.0.1: + dependencies: + kind-of: 3.2.2 + + snapdragon@0.8.2: + dependencies: + base: 0.11.2 + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + map-cache: 0.2.2 + source-map: 0.5.7 + source-map-resolve: 0.5.3 + use: 3.1.1 + transitivePeerDependencies: + - supports-color + + sockjs@0.3.24: + dependencies: + faye-websocket: 0.11.4 + uuid: 8.3.2 + websocket-driver: 0.7.4 + + sort-asc@0.2.0: {} + + sort-desc@0.2.0: {} + + sort-keys@1.1.2: + dependencies: + is-plain-obj: 1.1.0 + + sort-object@3.0.3: + dependencies: + bytewise: 1.1.0 + get-value: 2.0.6 + is-extendable: 0.1.1 + sort-asc: 0.2.0 + sort-desc: 0.2.0 + union-value: 1.0.1 + + source-list-map@2.0.1: {} + + source-map-js@1.2.1: {} + + source-map-loader@3.0.2(webpack@5.99.7): + dependencies: + abab: 2.0.6 + iconv-lite: 0.6.3 + source-map-js: 1.2.1 + webpack: 5.99.7 + + source-map-resolve@0.5.3: + dependencies: + atob: 2.1.2 + decode-uri-component: 0.2.2 + resolve-url: 0.2.1 + source-map-url: 0.4.1 + urix: 0.1.0 + + source-map-support@0.3.3: + dependencies: + source-map: 0.1.32 + + source-map-support@0.4.18: + dependencies: + source-map: 0.5.7 + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map-url@0.4.1: {} + + source-map@0.1.32: + dependencies: + amdefine: 1.0.1 + + source-map@0.5.6: {} + + source-map@0.5.7: {} + + source-map@0.6.1: {} + + source-map@0.7.4: {} + + source-map@0.8.0-beta.0: + dependencies: + whatwg-url: 7.1.0 + + sourcemap-codec@1.4.8: {} + + sourcemapped-stacktrace@1.1.11: + dependencies: + source-map: 0.5.6 + + spdx-correct@3.2.0: + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.21 + + spdx-exceptions@2.5.0: {} + + spdx-expression-parse@3.0.1: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.21 + + spdx-license-ids@3.0.21: {} + + spdy-transport@3.0.0: + dependencies: + debug: 4.4.0 + detect-node: 2.1.0 + hpack.js: 2.1.6 + obuf: 1.1.2 + readable-stream: 3.6.2 + wbuf: 1.7.3 + transitivePeerDependencies: + - supports-color + + spdy@4.0.2: + dependencies: + debug: 4.4.0 + handle-thing: 2.0.1 + http-deceiver: 1.2.7 + select-hose: 2.0.0 + spdy-transport: 3.0.0 + transitivePeerDependencies: + - supports-color + + splaytree@3.1.2: {} + + split-on-first@1.1.0: {} + + split-on-first@3.0.0: {} + + split-string@3.1.0: + dependencies: + extend-shallow: 3.0.2 + + sprintf-js@1.0.3: {} + + sql-formatter@2.3.4: + dependencies: + lodash: 4.17.21 + + ssf@0.11.2: + dependencies: + frac: 1.1.2 + + stable@0.1.8: {} + + stack-generator@2.0.10: + dependencies: + stackframe: 1.3.4 + + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + + stackframe@0.3.1: {} + + stackframe@1.3.4: {} + + stacktrace-gps@3.1.2: + dependencies: + source-map: 0.5.6 + stackframe: 1.3.4 + + stacktrace-js@2.0.2: + dependencies: + error-stack-parser: 2.1.4 + stack-generator: 2.0.10 + stacktrace-gps: 3.1.2 + + static-eval@2.0.2: + dependencies: + escodegen: 1.14.3 + + static-extend@0.1.2: + dependencies: + define-property: 0.2.5 + object-copy: 0.1.0 + + statuses@1.5.0: {} + + statuses@2.0.1: {} + + stream-browserify@2.0.2: + dependencies: + inherits: 2.0.4 + readable-stream: 2.3.8 + + stream-http@2.8.3: + dependencies: + builtin-status-codes: 3.0.0 + inherits: 2.0.4 + readable-stream: 2.3.8 + to-arraybuffer: 1.0.1 + xtend: 4.0.2 + + strict-uri-encode@1.1.0: {} + + strict-uri-encode@2.0.0: {} + + string-argv@0.3.1: {} + + string-convert@0.2.1: {} + + string-length@4.0.2: + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + + string-length@5.0.1: + dependencies: + char-regex: 2.0.2 + strip-ansi: 7.1.0 + + string-natural-compare@3.0.1: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + string.prototype.includes@2.0.1: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + + string.prototype.matchall@4.0.12: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + regexp.prototype.flags: 1.5.4 + set-function-name: 2.0.2 + side-channel: 1.1.0 + + string.prototype.repeat@1.0.0: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.23.9 + + string.prototype.trim@1.2.10: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-object-atoms: 1.1.1 + has-property-descriptors: 1.0.2 + + string.prototype.trimend@1.0.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + stringify-object@3.3.0: + dependencies: + get-own-enumerable-property-symbols: 3.0.2 + is-obj: 1.0.1 + is-regexp: 1.0.0 + + strip-ansi@3.0.1: + dependencies: + ansi-regex: 2.1.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + strip-bom@3.0.0: {} + + strip-bom@4.0.0: {} + + strip-comments@2.0.1: {} + + strip-eof@1.0.0: {} + + strip-final-newline@2.0.0: {} + + strip-indent@2.0.0: {} + + strip-json-comments@3.1.1: {} + + style-ext-html-webpack-plugin@4.1.3: + dependencies: + clean-css: 4.2.4 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + + style-loader@3.3.4(webpack@5.99.7): + dependencies: + webpack: 5.99.7 + + stylehacks@5.1.1(postcss@8.5.3): + dependencies: + browserslist: 4.24.4 + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + stylis@4.2.0: {} + + stylis@4.3.6: {} + + sucrase@3.35.0: + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + commander: 4.1.1 + glob: 10.4.5 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.7 + ts-interface-checker: 0.1.13 + + supercluster@7.1.5: + dependencies: + kdbush: 3.0.0 + + supercluster@8.0.1: + dependencies: + kdbush: 4.0.2 + + supports-color@2.0.0: {} + + supports-color@3.2.3: + dependencies: + has-flag: 1.0.0 + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@6.1.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-hyperlinks@2.3.0: + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + svg-parser@2.0.4: {} + + svgo@1.3.2: + dependencies: + chalk: 2.4.2 + coa: 2.0.2 + css-select: 2.1.0 + css-select-base-adapter: 0.1.1 + css-tree: 1.0.0-alpha.37 + csso: 4.2.0 + js-yaml: 3.14.1 + mkdirp: 0.5.6 + object.values: 1.2.1 + sax: 1.2.4 + stable: 0.1.8 + unquote: 1.1.1 + util.promisify: 1.0.1 + + svgo@2.8.0: + dependencies: + '@trysound/sax': 0.2.0 + commander: 7.2.0 + css-select: 4.3.0 + css-tree: 1.1.3 + csso: 4.2.0 + picocolors: 1.1.1 + stable: 0.1.8 + + swagger-ui-dist@4.19.1: {} + + swagger2openapi@7.0.8(encoding@0.1.13): + dependencies: + call-me-maybe: 1.0.2 + node-fetch: 2.7.0(encoding@0.1.13) + node-fetch-h2: 2.3.0 + node-readfiles: 0.2.0 + oas-kit-common: 1.0.8 + oas-resolver: 2.5.6 + oas-schema-walker: 1.1.5 + oas-validator: 5.0.8 + reftools: 1.1.9 + yaml: 1.10.2 + yargs: 17.7.2 + transitivePeerDependencies: + - encoding + + swr@2.3.3(react@16.14.0): + dependencies: + dequal: 2.0.3 + react: 16.14.0 + use-sync-external-store: 1.5.0(react@16.14.0) + + symbol-observable@1.2.0: {} + + symbol-tree@3.2.4: {} + + tailwindcss@3.4.17(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)): + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.6.0 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.3 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.7 + lilconfig: 3.1.3 + micromatch: 4.0.8 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.1.1 + postcss: 8.5.3 + postcss-import: 15.1.0(postcss@8.5.3) + postcss-js: 4.0.1(postcss@8.5.3) + postcss-load-config: 4.0.2(postcss@8.5.3)(ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5)) + postcss-nested: 6.2.0(postcss@8.5.3) + postcss-selector-parser: 6.1.2 + resolve: 1.22.10 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + + tapable@1.1.3: {} + + tapable@2.2.1: {} + + tape@4.17.0: + dependencies: + '@ljharb/resumer': 0.0.1 + '@ljharb/through': 2.3.14 + call-bind: 1.0.8 + deep-equal: 1.1.2 + defined: 1.0.1 + dotignore: 0.1.2 + for-each: 0.3.5 + glob: 7.2.3 + has: 1.0.4 + inherits: 2.0.4 + is-regex: 1.1.4 + minimist: 1.2.8 + mock-property: 1.0.3 + object-inspect: 1.12.3 + resolve: 1.22.10 + string.prototype.trim: 1.2.10 + + temp-dir@2.0.0: {} + + tempy@0.6.0: + dependencies: + is-stream: 2.0.1 + temp-dir: 2.0.0 + type-fest: 0.16.0 + unique-string: 2.0.0 + + terminal-link@2.1.1: + dependencies: + ansi-escapes: 4.3.2 + supports-hyperlinks: 2.3.0 + + terser-webpack-plugin@5.3.14(webpack@5.99.7): + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + jest-worker: 27.5.1 + schema-utils: 4.3.2 + serialize-javascript: 6.0.2 + terser: 5.39.0 + webpack: 5.99.7 + + terser@4.8.1: + dependencies: + acorn: 8.14.1 + commander: 2.20.3 + source-map: 0.6.1 + source-map-support: 0.5.21 + + terser@5.14.2: + dependencies: + '@jridgewell/source-map': 0.3.6 + acorn: 8.14.1 + commander: 2.20.3 + source-map-support: 0.5.21 + + terser@5.39.0: + dependencies: + '@jridgewell/source-map': 0.3.6 + acorn: 8.14.1 + commander: 2.20.3 + source-map-support: 0.5.21 + + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + + text-table@0.2.0: {} + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + throat@5.0.0: {} + + throat@6.0.2: {} + + throttle-debounce@3.0.1: {} + + throttle-debounce@5.0.2: {} + + through@2.3.8: {} + + thunky@1.1.0: {} + + timers-browserify@2.0.12: + dependencies: + setimmediate: 1.0.5 + + timers-ext@0.1.8: + dependencies: + es5-ext: 0.10.64 + next-tick: 1.1.0 + + tiny-invariant@1.3.3: {} + + tiny-pinyin@1.3.2: {} + + tiny-warning@1.0.3: {} + + tinycolor2@1.6.0: {} + + tinyqueue@2.0.3: {} + + tmpl@1.0.5: {} + + to-arraybuffer@1.0.1: {} + + to-fast-properties@1.0.3: {} + + to-object-path@0.3.0: + dependencies: + kind-of: 3.2.2 + + to-regex-range@2.1.1: + dependencies: + is-number: 3.0.0 + repeat-string: 1.6.1 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + to-regex@3.0.2: + dependencies: + define-property: 2.0.2 + extend-shallow: 3.0.2 + regex-not: 1.0.2 + safe-regex: 1.1.0 + + toggle-selection@1.0.6: {} + + toidentifier@1.0.1: {} + + topojson-client@3.1.0: + dependencies: + commander: 2.20.3 + + toposort@2.0.2: {} + + tough-cookie@4.1.4: + dependencies: + psl: 1.15.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + + tr46@0.0.3: {} + + tr46@1.0.1: + dependencies: + punycode: 2.3.1 + + tr46@2.1.0: + dependencies: + punycode: 2.3.1 + + trim-right@1.0.1: {} + + tryer@1.0.1: {} + + ts-easing@0.2.0: {} + + ts-interface-checker@0.1.13: {} + + ts-node@10.9.2(@types/node@18.19.87)(typescript@4.9.5): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 18.19.87 + acorn: 8.14.1 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 4.9.5 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + + tsconfig-paths@3.15.0: + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tslib@1.14.1: {} + + tslib@2.8.1: {} + + tsutils@3.21.0(typescript@4.9.5): + dependencies: + tslib: 1.14.1 + typescript: 4.9.5 + + tty-browserify@0.0.0: {} + + tween-functions@1.2.0: {} + + type-check@0.3.2: + dependencies: + prelude-ls: 1.1.2 + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-detect@4.0.8: {} + + type-fest@0.16.0: {} + + type-fest@0.21.3: {} + + type-fest@0.6.0: {} + + type-fest@0.8.1: {} + + type-fest@2.19.0: {} + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + type@2.7.3: {} + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.7: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + + typedarray-to-buffer@3.1.5: + dependencies: + is-typedarray: 1.0.0 + + typescript@4.9.5: {} + + typewise-core@1.2.0: {} + + typewise@1.0.3: + dependencies: + typewise-core: 1.2.0 + + ua-parser-js@0.7.40: {} + + ua-parser-js@1.0.40: {} + + uglify-js@2.8.29: + dependencies: + source-map: 0.5.7 + yargs: 3.10.0 + optionalDependencies: + uglify-to-browserify: 1.0.2 + + uglify-to-browserify@1.0.2: + optional: true + + umi-request@1.4.0: + dependencies: + isomorphic-fetch: 2.2.1 + qs: 6.14.0 + + umi@3.5.43(react-router@5.2.0(react@16.14.0)): + dependencies: + '@umijs/bundler-webpack': 3.5.43(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0) + '@umijs/core': 3.5.43 + '@umijs/deps': 3.5.43 + '@umijs/preset-built-in': 3.5.43(react-dom@16.14.0(react@16.14.0))(react@16.14.0) + '@umijs/runtime': 3.5.43(react@16.14.0) + '@umijs/types': 3.5.43(react-dom@16.14.0(react@16.14.0))(react-router@5.2.0(react@16.14.0))(react@16.14.0) + '@umijs/utils': 3.5.43 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + v8-compile-cache: 2.3.0 + transitivePeerDependencies: + - react-router + + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + + underscore@1.12.1: {} + + undici-types@5.26.5: {} + + undici-types@6.21.0: {} + + unicode-canonical-property-names-ecmascript@2.0.1: {} + + unicode-match-property-ecmascript@2.0.0: + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.1 + unicode-property-aliases-ecmascript: 2.1.0 + + unicode-match-property-value-ecmascript@2.2.0: {} + + unicode-property-aliases-ecmascript@2.1.0: {} + + union-value@1.0.1: + dependencies: + arr-union: 3.1.0 + get-value: 2.0.6 + is-extendable: 0.1.1 + set-value: 2.0.1 + + uniq@1.0.1: {} + + unique-string@2.0.0: + dependencies: + crypto-random-string: 2.0.0 + + universalify@0.2.0: {} + + universalify@2.0.1: {} + + unpipe@1.0.0: {} + + unquote@1.1.1: {} + + unset-value@1.0.0: + dependencies: + has-value: 0.3.1 + isobject: 3.0.1 + + upath@1.2.0: {} + + update-browserslist-db@1.1.3(browserslist@4.24.4): + dependencies: + browserslist: 4.24.4 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + urix@0.1.0: {} + + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + + url@0.11.4: + dependencies: + punycode: 1.4.1 + qs: 6.14.0 + + use-composed-ref@1.4.0(@types/react@17.0.52)(react@16.14.0): + dependencies: + react: 16.14.0 + optionalDependencies: + '@types/react': 17.0.52 + + use-deep-compare-effect@1.8.1(react@16.14.0): + dependencies: + '@babel/runtime': 7.27.0 + dequal: 2.0.3 + react: 16.14.0 + + use-isomorphic-layout-effect@1.2.0(@types/react@17.0.52)(react@16.14.0): + dependencies: + react: 16.14.0 + optionalDependencies: + '@types/react': 17.0.52 + + use-latest@1.3.0(@types/react@17.0.52)(react@16.14.0): + dependencies: + react: 16.14.0 + use-isomorphic-layout-effect: 1.2.0(@types/react@17.0.52)(react@16.14.0) + optionalDependencies: + '@types/react': 17.0.52 + + use-memo-one@1.1.3(react@16.14.0): + dependencies: + react: 16.14.0 + + use-merge-value@1.2.0(react@16.14.0): + dependencies: + react: 16.14.0 + + use-resize-observer@9.1.0(react-dom@16.14.0(react@16.14.0))(react@16.14.0): + dependencies: + '@juggle/resize-observer': 3.4.0 + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + + use-subscription@1.5.1(react@16.14.0): + dependencies: + object-assign: 4.1.1 + react: 16.14.0 + + use-sync-external-store@1.5.0(react@16.14.0): + dependencies: + react: 16.14.0 + + use@3.1.1: {} + + user-home@1.1.1: {} + + util-deprecate@1.0.2: {} + + util.promisify@1.0.0: + dependencies: + define-properties: 1.2.1 + object.getownpropertydescriptors: 2.1.8 + + util.promisify@1.0.1: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.23.9 + has-symbols: 1.1.0 + object.getownpropertydescriptors: 2.1.8 + + util@0.10.4: + dependencies: + inherits: 2.0.3 + + util@0.11.1: + dependencies: + inherits: 2.0.3 + + utila@0.4.0: {} + + utility-types@3.11.0: {} + + utils-merge@1.0.1: {} + + uuid@8.3.2: {} + + v8-compile-cache-lib@3.0.1: {} + + v8-compile-cache@2.3.0: {} + + v8-to-istanbul@7.1.2: + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 1.9.0 + source-map: 0.7.4 + + v8-to-istanbul@8.1.1: + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 1.9.0 + source-map: 0.7.4 + + v8flags@2.1.1: + dependencies: + user-home: 1.1.1 + + validate-npm-package-license@3.0.4: + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + + validator@13.15.0: {} + + value-equal@1.0.1: {} + + vary@1.1.2: {} + + viewport-mercator-project@6.2.3: + dependencies: + '@babel/runtime': 7.27.0 + gl-matrix: 3.4.3 + + vm-browserify@1.1.2: {} + + vt-pbf@3.1.3: + dependencies: + '@mapbox/point-geometry': 0.1.0 + '@mapbox/vector-tile': 1.3.1 + pbf: 3.3.0 + + w3c-hr-time@1.0.2: + dependencies: + browser-process-hrtime: 1.0.0 + + w3c-xmlserializer@2.0.0: + dependencies: + xml-name-validator: 3.0.0 + + walker@1.0.8: + dependencies: + makeerror: 1.0.12 + + warning@3.0.0: + dependencies: + loose-envify: 1.4.0 + + warning@4.0.3: + dependencies: + loose-envify: 1.4.0 + + watchpack@2.4.2: + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + + wbuf@1.7.3: + dependencies: + minimalistic-assert: 1.0.1 + + web-worker-helper@0.0.3: {} + + webidl-conversions@3.0.1: {} + + webidl-conversions@4.0.2: {} + + webidl-conversions@5.0.0: {} + + webidl-conversions@6.1.0: {} + + webpack-chain@6.5.1: + dependencies: + deepmerge: 1.5.2 + javascript-stringify: 2.1.0 + + webpack-dev-middleware@5.3.4(webpack@5.99.7): + dependencies: + colorette: 2.0.20 + memfs: 3.5.3 + mime-types: 2.1.35 + range-parser: 1.2.1 + schema-utils: 4.3.2 + webpack: 5.99.7 + + webpack-dev-server@4.15.2(webpack@5.99.7): + dependencies: + '@types/bonjour': 3.5.13 + '@types/connect-history-api-fallback': 1.5.4 + '@types/express': 4.17.21 + '@types/serve-index': 1.9.4 + '@types/serve-static': 1.15.7 + '@types/sockjs': 0.3.36 + '@types/ws': 8.18.1 + ansi-html-community: 0.0.8 + bonjour-service: 1.3.0 + chokidar: 3.6.0 + colorette: 2.0.20 + compression: 1.8.0 + connect-history-api-fallback: 2.0.0 + default-gateway: 6.0.3 + express: 4.21.2 + graceful-fs: 4.2.11 + html-entities: 2.6.0 + http-proxy-middleware: 2.0.9(@types/express@4.17.21) + ipaddr.js: 2.2.0 + launch-editor: 2.10.0 + open: 8.4.2 + p-retry: 4.6.2 + rimraf: 3.0.2 + schema-utils: 4.3.2 + selfsigned: 2.4.1 + serve-index: 1.9.1 + sockjs: 0.3.24 + spdy: 4.0.2 + webpack-dev-middleware: 5.3.4(webpack@5.99.7) + ws: 8.18.1 + optionalDependencies: + webpack: 5.99.7 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + + webpack-manifest-plugin@4.1.1(webpack@5.99.7): + dependencies: + tapable: 2.2.1 + webpack: 5.99.7 + webpack-sources: 2.3.1 + + webpack-sources@1.4.3: + dependencies: + source-list-map: 2.0.1 + source-map: 0.6.1 + + webpack-sources@2.3.1: + dependencies: + source-list-map: 2.0.1 + source-map: 0.6.1 + + webpack-sources@3.2.3: {} + + webpack@5.99.7: + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.7 + '@types/json-schema': 7.0.15 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/wasm-edit': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + acorn: 8.14.1 + browserslist: 4.24.4 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.18.1 + es-module-lexer: 1.7.0 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 4.3.2 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.14(webpack@5.99.7) + watchpack: 2.4.2 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + + websocket-driver@0.7.4: + dependencies: + http-parser-js: 0.5.10 + safe-buffer: 5.2.1 + websocket-extensions: 0.1.4 + + websocket-extensions@0.1.4: {} + + whatwg-encoding@1.0.5: + dependencies: + iconv-lite: 0.4.24 + + whatwg-fetch@3.6.20: {} + + whatwg-mimetype@2.3.0: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + whatwg-url@7.1.0: + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + + whatwg-url@8.7.0: + dependencies: + lodash: 4.17.21 + tr46: 2.1.0 + webidl-conversions: 6.1.0 + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.0 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.19 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-module@2.0.1: {} + + which-typed-array@1.1.19: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@1.3.1: + dependencies: + isexe: 2.0.0 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + window-size@0.1.0: {} + + wmf@1.0.2: {} + + word-wrap@1.2.5: {} + + word@0.3.0: {} + + wordwrap@0.0.2: {} + + workbox-background-sync@6.6.0: + dependencies: + idb: 7.1.1 + workbox-core: 6.6.0 + + workbox-broadcast-update@6.6.0: + dependencies: + workbox-core: 6.6.0 + + workbox-build@6.6.0(@types/babel__core@7.20.5): + dependencies: + '@apideck/better-ajv-errors': 0.3.6(ajv@8.17.1) + '@babel/core': 7.26.10 + '@babel/preset-env': 7.26.9(@babel/core@7.26.10) + '@babel/runtime': 7.27.0 + '@rollup/plugin-babel': 5.3.1(@babel/core@7.26.10)(@types/babel__core@7.20.5)(rollup@2.79.2) + '@rollup/plugin-node-resolve': 11.2.1(rollup@2.79.2) + '@rollup/plugin-replace': 2.4.2(rollup@2.79.2) + '@surma/rollup-plugin-off-main-thread': 2.2.3 + ajv: 8.17.1 + common-tags: 1.8.2 + fast-json-stable-stringify: 2.1.0 + fs-extra: 9.1.0 + glob: 7.2.3 + lodash: 4.17.21 + pretty-bytes: 5.6.0 + rollup: 2.79.2 + rollup-plugin-terser: 7.0.2(rollup@2.79.2) + source-map: 0.8.0-beta.0 + stringify-object: 3.3.0 + strip-comments: 2.0.1 + tempy: 0.6.0 + upath: 1.2.0 + workbox-background-sync: 6.6.0 + workbox-broadcast-update: 6.6.0 + workbox-cacheable-response: 6.6.0 + workbox-core: 6.6.0 + workbox-expiration: 6.6.0 + workbox-google-analytics: 6.6.0 + workbox-navigation-preload: 6.6.0 + workbox-precaching: 6.6.0 + workbox-range-requests: 6.6.0 + workbox-recipes: 6.6.0 + workbox-routing: 6.6.0 + workbox-strategies: 6.6.0 + workbox-streams: 6.6.0 + workbox-sw: 6.6.0 + workbox-window: 6.6.0 + transitivePeerDependencies: + - '@types/babel__core' + - supports-color + + workbox-cacheable-response@6.6.0: + dependencies: + workbox-core: 6.6.0 + + workbox-core@6.6.0: {} + + workbox-expiration@6.6.0: + dependencies: + idb: 7.1.1 + workbox-core: 6.6.0 + + workbox-google-analytics@6.6.0: + dependencies: + workbox-background-sync: 6.6.0 + workbox-core: 6.6.0 + workbox-routing: 6.6.0 + workbox-strategies: 6.6.0 + + workbox-navigation-preload@6.6.0: + dependencies: + workbox-core: 6.6.0 + + workbox-precaching@6.6.0: + dependencies: + workbox-core: 6.6.0 + workbox-routing: 6.6.0 + workbox-strategies: 6.6.0 + + workbox-range-requests@6.6.0: + dependencies: + workbox-core: 6.6.0 + + workbox-recipes@6.6.0: + dependencies: + workbox-cacheable-response: 6.6.0 + workbox-core: 6.6.0 + workbox-expiration: 6.6.0 + workbox-precaching: 6.6.0 + workbox-routing: 6.6.0 + workbox-strategies: 6.6.0 + + workbox-routing@6.6.0: + dependencies: + workbox-core: 6.6.0 + + workbox-strategies@6.6.0: + dependencies: + workbox-core: 6.6.0 + + workbox-streams@6.6.0: + dependencies: + workbox-core: 6.6.0 + workbox-routing: 6.6.0 + + workbox-sw@6.6.0: {} + + workbox-webpack-plugin@6.6.0(@types/babel__core@7.20.5)(webpack@5.99.7): + dependencies: + fast-json-stable-stringify: 2.1.0 + pretty-bytes: 5.6.0 + upath: 1.2.0 + webpack: 5.99.7 + webpack-sources: 1.4.3 + workbox-build: 6.6.0(@types/babel__core@7.20.5) + transitivePeerDependencies: + - '@types/babel__core' + - supports-color + + workbox-window@6.6.0: + dependencies: + '@types/trusted-types': 2.0.7 + workbox-core: 6.6.0 + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + wrappy@1.0.2: {} + + write-file-atomic@3.0.3: + dependencies: + imurmurhash: 0.1.4 + is-typedarray: 1.0.0 + signal-exit: 3.0.7 + typedarray-to-buffer: 3.1.5 + + ws@7.5.10: {} + + ws@8.18.1: {} + + xlsx@0.17.5: + dependencies: + adler-32: 1.2.0 + cfb: 1.2.2 + codepage: 1.15.0 + crc-32: 1.2.2 + ssf: 0.11.2 + wmf: 1.0.2 + word: 0.3.0 + + xml-name-validator@3.0.0: {} + + xmlchars@2.2.0: {} + + xtend@4.0.2: {} + + y18n@4.0.3: {} + + y18n@5.0.8: {} + + yallist@2.1.2: {} + + yallist@3.1.1: {} + + yaml@1.10.2: {} + + yaml@2.7.1: {} + + yargs-parser@18.1.3: + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + + yargs-parser@20.2.9: {} + + yargs-parser@21.1.1: {} + + yargs@15.4.1: + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 18.1.3 + + yargs@16.2.0: + dependencies: + cliui: 7.0.4 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yargs@3.10.0: + dependencies: + camelcase: 1.2.1 + cliui: 2.1.0 + decamelize: 1.2.0 + window-size: 0.1.0 + + yn@3.1.1: {} + + yocto-queue@0.1.0: {} + + yorkie@2.0.0: + dependencies: + execa: 0.8.0 + is-ci: 1.2.1 + normalize-path: 1.0.0 + strip-indent: 2.0.0 + + zscroller@0.4.8: + dependencies: + babel-runtime: 6.26.0 diff --git a/frontend/public/assets/badge/default.svg b/frontend/public/assets/badge/default.svg new file mode 100644 index 00000000..af2947e5 --- /dev/null +++ b/frontend/public/assets/badge/default.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/badge/error.svg b/frontend/public/assets/badge/error.svg new file mode 100644 index 00000000..1b5209e8 --- /dev/null +++ b/frontend/public/assets/badge/error.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/badge/processing.svg b/frontend/public/assets/badge/processing.svg new file mode 100644 index 00000000..9634b0ef --- /dev/null +++ b/frontend/public/assets/badge/processing.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/badge/success.svg b/frontend/public/assets/badge/success.svg new file mode 100644 index 00000000..43e05594 --- /dev/null +++ b/frontend/public/assets/badge/success.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/badge/warning.svg b/frontend/public/assets/badge/warning.svg new file mode 100644 index 00000000..4e29e391 --- /dev/null +++ b/frontend/public/assets/badge/warning.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/cluster/abandoned.svg b/frontend/public/assets/cluster/abandoned.svg new file mode 100644 index 00000000..8720fc33 --- /dev/null +++ b/frontend/public/assets/cluster/abandoned.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/cluster/cluster.svg b/frontend/public/assets/cluster/cluster.svg new file mode 100644 index 00000000..400a9f58 --- /dev/null +++ b/frontend/public/assets/cluster/cluster.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/cluster/creating.svg b/frontend/public/assets/cluster/creating.svg new file mode 100644 index 00000000..5b692c96 --- /dev/null +++ b/frontend/public/assets/cluster/creating.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/cluster/deleted.svg b/frontend/public/assets/cluster/deleted.svg new file mode 100644 index 00000000..8fd2d0c2 --- /dev/null +++ b/frontend/public/assets/cluster/deleted.svg @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/cluster/deleting.svg b/frontend/public/assets/cluster/deleting.svg new file mode 100644 index 00000000..4435245c --- /dev/null +++ b/frontend/public/assets/cluster/deleting.svg @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/cluster/error.svg b/frontend/public/assets/cluster/error.svg new file mode 100644 index 00000000..8720fc33 --- /dev/null +++ b/frontend/public/assets/cluster/error.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/cluster/failover.svg b/frontend/public/assets/cluster/failover.svg new file mode 100644 index 00000000..f58ca934 --- /dev/null +++ b/frontend/public/assets/cluster/failover.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/cluster/movingout.svg b/frontend/public/assets/cluster/movingout.svg new file mode 100644 index 00000000..f58ca934 --- /dev/null +++ b/frontend/public/assets/cluster/movingout.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/cluster/operating.svg b/frontend/public/assets/cluster/operating.svg new file mode 100644 index 00000000..f58ca934 --- /dev/null +++ b/frontend/public/assets/cluster/operating.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/cluster/restarting.svg b/frontend/public/assets/cluster/restarting.svg new file mode 100644 index 00000000..4435245c --- /dev/null +++ b/frontend/public/assets/cluster/restarting.svg @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/cluster/running.svg b/frontend/public/assets/cluster/running.svg new file mode 100644 index 00000000..bf430b63 --- /dev/null +++ b/frontend/public/assets/cluster/running.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/cluster/starting.svg b/frontend/public/assets/cluster/starting.svg new file mode 100644 index 00000000..4435245c --- /dev/null +++ b/frontend/public/assets/cluster/starting.svg @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/cluster/stopped.svg b/frontend/public/assets/cluster/stopped.svg new file mode 100644 index 00000000..8fd2d0c2 --- /dev/null +++ b/frontend/public/assets/cluster/stopped.svg @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/cluster/stopping.svg b/frontend/public/assets/cluster/stopping.svg new file mode 100644 index 00000000..4435245c --- /dev/null +++ b/frontend/public/assets/cluster/stopping.svg @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/cluster/switchover.svg b/frontend/public/assets/cluster/switchover.svg new file mode 100644 index 00000000..f58ca934 --- /dev/null +++ b/frontend/public/assets/cluster/switchover.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/cluster/takingover.svg b/frontend/public/assets/cluster/takingover.svg new file mode 100644 index 00000000..5b692c96 --- /dev/null +++ b/frontend/public/assets/cluster/takingover.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/cluster/unavailable.svg b/frontend/public/assets/cluster/unavailable.svg new file mode 100644 index 00000000..8720fc33 --- /dev/null +++ b/frontend/public/assets/cluster/unavailable.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/cluster/upgrading.svg b/frontend/public/assets/cluster/upgrading.svg new file mode 100644 index 00000000..f58ca934 --- /dev/null +++ b/frontend/public/assets/cluster/upgrading.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/common/403.svg b/frontend/public/assets/common/403.svg new file mode 100644 index 00000000..cc237aea --- /dev/null +++ b/frontend/public/assets/common/403.svg @@ -0,0 +1,521 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/common/404.svg b/frontend/public/assets/common/404.svg new file mode 100644 index 00000000..2e752afd --- /dev/null +++ b/frontend/public/assets/common/404.svg @@ -0,0 +1,327 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/common/500.svg b/frontend/public/assets/common/500.svg new file mode 100644 index 00000000..62d4dc80 --- /dev/null +++ b/frontend/public/assets/common/500.svg @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/common/crash.svg b/frontend/public/assets/common/crash.svg new file mode 100644 index 00000000..aa38bfdf --- /dev/null +++ b/frontend/public/assets/common/crash.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/common/empty.svg b/frontend/public/assets/common/empty.svg new file mode 100644 index 00000000..ef077f1a --- /dev/null +++ b/frontend/public/assets/common/empty.svg @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/common/guide.svg b/frontend/public/assets/common/guide.svg new file mode 100644 index 00000000..de05b96e --- /dev/null +++ b/frontend/public/assets/common/guide.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/common/no_auth.svg b/frontend/public/assets/common/no_auth.svg new file mode 100644 index 00000000..9cdb7ea4 --- /dev/null +++ b/frontend/public/assets/common/no_auth.svg @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/icon/client.svg b/frontend/public/assets/icon/client.svg new file mode 100644 index 00000000..7bf6930c --- /dev/null +++ b/frontend/public/assets/icon/client.svg @@ -0,0 +1,29 @@ + + + + + General/box-icon/24px备份 2 + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/icon/close.svg b/frontend/public/assets/icon/close.svg new file mode 100644 index 00000000..2d01fa2a --- /dev/null +++ b/frontend/public/assets/icon/close.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/icon/ellipsis.svg b/frontend/public/assets/icon/ellipsis.svg new file mode 100644 index 00000000..8f34e549 --- /dev/null +++ b/frontend/public/assets/icon/ellipsis.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/icon/fit_canvas.svg b/frontend/public/assets/icon/fit_canvas.svg new file mode 100644 index 00000000..2d495304 --- /dev/null +++ b/frontend/public/assets/icon/fit_canvas.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/icon/more.svg b/frontend/public/assets/icon/more.svg new file mode 100644 index 00000000..8c4f7d18 --- /dev/null +++ b/frontend/public/assets/icon/more.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/icon/obproxy.svg b/frontend/public/assets/icon/obproxy.svg new file mode 100644 index 00000000..98e59b06 --- /dev/null +++ b/frontend/public/assets/icon/obproxy.svg @@ -0,0 +1,30 @@ + + + + + OBProxy + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/icon/reset.svg b/frontend/public/assets/icon/reset.svg new file mode 100644 index 00000000..400b0bdb --- /dev/null +++ b/frontend/public/assets/icon/reset.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/icon/settings.svg b/frontend/public/assets/icon/settings.svg new file mode 100644 index 00000000..8fa522ab --- /dev/null +++ b/frontend/public/assets/icon/settings.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/icon/success.svg b/frontend/public/assets/icon/success.svg new file mode 100644 index 00000000..07ec32b3 --- /dev/null +++ b/frontend/public/assets/icon/success.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/icon/warning.svg b/frontend/public/assets/icon/warning.svg new file mode 100644 index 00000000..b199fc48 --- /dev/null +++ b/frontend/public/assets/icon/warning.svg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/login/background_img.svg b/frontend/public/assets/login/background_img.svg new file mode 100644 index 00000000..2bda4ab8 --- /dev/null +++ b/frontend/public/assets/login/background_img.svg @@ -0,0 +1,46 @@ + + + + + 编组 7 + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/login/background_img_dark.svg b/frontend/public/assets/login/background_img_dark.svg new file mode 100644 index 00000000..77762599 --- /dev/null +++ b/frontend/public/assets/login/background_img_dark.svg @@ -0,0 +1,42 @@ + + + background_img + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/logo/oceanbase_logo.svg b/frontend/public/assets/logo/oceanbase_logo.svg new file mode 100644 index 00000000..9656365a --- /dev/null +++ b/frontend/public/assets/logo/oceanbase_logo.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/logo/ocp_express_favicon.svg b/frontend/public/assets/logo/ocp_express_favicon.svg new file mode 100644 index 00000000..3582318b --- /dev/null +++ b/frontend/public/assets/logo/ocp_express_favicon.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/logo/ocp_express_icon.svg b/frontend/public/assets/logo/ocp_express_icon.svg new file mode 100644 index 00000000..5a9534f1 --- /dev/null +++ b/frontend/public/assets/logo/ocp_express_icon.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/logo/ocp_express_logo_en.svg b/frontend/public/assets/logo/ocp_express_logo_en.svg new file mode 100644 index 00000000..fcd72ca7 --- /dev/null +++ b/frontend/public/assets/logo/ocp_express_logo_en.svg @@ -0,0 +1,55 @@ + + + + + 01-General Component 通用组件/01-General 通用/02-Icon 图标/05-Product 产品/Logo/登录/英文/OCP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/logo/ocp_express_logo_en_dark.svg b/frontend/public/assets/logo/ocp_express_logo_en_dark.svg new file mode 100644 index 00000000..f1607e7b --- /dev/null +++ b/frontend/public/assets/logo/ocp_express_logo_en_dark.svg @@ -0,0 +1,35 @@ + + + ocp_express_logo_en + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/logo/ocp_express_logo_zh.svg b/frontend/public/assets/logo/ocp_express_logo_zh.svg new file mode 100644 index 00000000..7f3139e7 --- /dev/null +++ b/frontend/public/assets/logo/ocp_express_logo_zh.svg @@ -0,0 +1,53 @@ + + + + + 编组 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/logo/ocp_express_logo_zh_dark.svg b/frontend/public/assets/logo/ocp_express_logo_zh_dark.svg new file mode 100644 index 00000000..d1c5cbf4 --- /dev/null +++ b/frontend/public/assets/logo/ocp_express_logo_zh_dark.svg @@ -0,0 +1,33 @@ + + + ocp_express_logo_zh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/logo/ocp_express_simple_logo_en.svg b/frontend/public/assets/logo/ocp_express_simple_logo_en.svg new file mode 100644 index 00000000..0f6e8e5e --- /dev/null +++ b/frontend/public/assets/logo/ocp_express_simple_logo_en.svg @@ -0,0 +1,54 @@ + + + + + 编组 5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/logo/ocp_express_simple_logo_en_dark.svg b/frontend/public/assets/logo/ocp_express_simple_logo_en_dark.svg new file mode 100644 index 00000000..5b140959 --- /dev/null +++ b/frontend/public/assets/logo/ocp_express_simple_logo_en_dark.svg @@ -0,0 +1,36 @@ + + + ocp_express_simple_logo_en + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/logo/ocp_express_simple_logo_zh.svg b/frontend/public/assets/logo/ocp_express_simple_logo_zh.svg new file mode 100644 index 00000000..d38de45b --- /dev/null +++ b/frontend/public/assets/logo/ocp_express_simple_logo_zh.svg @@ -0,0 +1,72 @@ + + + + + 编组 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/logo/ocp_express_simple_logo_zh_dark.svg b/frontend/public/assets/logo/ocp_express_simple_logo_zh_dark.svg new file mode 100644 index 00000000..51ab7241 --- /dev/null +++ b/frontend/public/assets/logo/ocp_express_simple_logo_zh_dark.svg @@ -0,0 +1,72 @@ + + + + + 编组 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/overview/obproxy.svg b/frontend/public/assets/overview/obproxy.svg new file mode 100644 index 00000000..01c45f76 --- /dev/null +++ b/frontend/public/assets/overview/obproxy.svg @@ -0,0 +1,44 @@ + + + + + icon/集群-basic备份 + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/overview/tenant.svg b/frontend/public/assets/overview/tenant.svg new file mode 100644 index 00000000..b2d2f8e0 --- /dev/null +++ b/frontend/public/assets/overview/tenant.svg @@ -0,0 +1,93 @@ + + + + + icon/租户-basic备份 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/server/creating.svg b/frontend/public/assets/server/creating.svg new file mode 100644 index 00000000..71e0e60a --- /dev/null +++ b/frontend/public/assets/server/creating.svg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/server/deleted.svg b/frontend/public/assets/server/deleted.svg new file mode 100644 index 00000000..1141fd52 --- /dev/null +++ b/frontend/public/assets/server/deleted.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/server/deleting.svg b/frontend/public/assets/server/deleting.svg new file mode 100644 index 00000000..f8052d97 --- /dev/null +++ b/frontend/public/assets/server/deleting.svg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/server/disabled.svg b/frontend/public/assets/server/disabled.svg new file mode 100644 index 00000000..1141fd52 --- /dev/null +++ b/frontend/public/assets/server/disabled.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/server/error.svg b/frontend/public/assets/server/error.svg new file mode 100644 index 00000000..7094d618 --- /dev/null +++ b/frontend/public/assets/server/error.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/server/process_stopped.svg b/frontend/public/assets/server/process_stopped.svg new file mode 100644 index 00000000..1141fd52 --- /dev/null +++ b/frontend/public/assets/server/process_stopped.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/server/process_stopping.svg b/frontend/public/assets/server/process_stopping.svg new file mode 100644 index 00000000..f8052d97 --- /dev/null +++ b/frontend/public/assets/server/process_stopping.svg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/server/restarting.svg b/frontend/public/assets/server/restarting.svg new file mode 100644 index 00000000..f8052d97 --- /dev/null +++ b/frontend/public/assets/server/restarting.svg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/server/running.svg b/frontend/public/assets/server/running.svg new file mode 100644 index 00000000..2f7f183f --- /dev/null +++ b/frontend/public/assets/server/running.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/server/server.svg b/frontend/public/assets/server/server.svg new file mode 100644 index 00000000..bd8d6787 --- /dev/null +++ b/frontend/public/assets/server/server.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/server/service_stopped.svg b/frontend/public/assets/server/service_stopped.svg new file mode 100644 index 00000000..1141fd52 --- /dev/null +++ b/frontend/public/assets/server/service_stopped.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/server/service_stopping.svg b/frontend/public/assets/server/service_stopping.svg new file mode 100644 index 00000000..f8052d97 --- /dev/null +++ b/frontend/public/assets/server/service_stopping.svg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/server/starting.svg b/frontend/public/assets/server/starting.svg new file mode 100644 index 00000000..f8052d97 --- /dev/null +++ b/frontend/public/assets/server/starting.svg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/server/stopped.svg b/frontend/public/assets/server/stopped.svg new file mode 100644 index 00000000..1141fd52 --- /dev/null +++ b/frontend/public/assets/server/stopped.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/server/stopping.svg b/frontend/public/assets/server/stopping.svg new file mode 100644 index 00000000..f8052d97 --- /dev/null +++ b/frontend/public/assets/server/stopping.svg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/server/unavailable.svg b/frontend/public/assets/server/unavailable.svg new file mode 100644 index 00000000..7094d618 --- /dev/null +++ b/frontend/public/assets/server/unavailable.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/server/warning.svg b/frontend/public/assets/server/warning.svg new file mode 100644 index 00000000..00716392 --- /dev/null +++ b/frontend/public/assets/server/warning.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/task/subtask_failed.svg b/frontend/public/assets/task/subtask_failed.svg new file mode 100644 index 00000000..14b5eafa --- /dev/null +++ b/frontend/public/assets/task/subtask_failed.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/task/subtask_pending.svg b/frontend/public/assets/task/subtask_pending.svg new file mode 100644 index 00000000..f672fa93 --- /dev/null +++ b/frontend/public/assets/task/subtask_pending.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/task/subtask_ready.svg b/frontend/public/assets/task/subtask_ready.svg new file mode 100644 index 00000000..f672fa93 --- /dev/null +++ b/frontend/public/assets/task/subtask_ready.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/task/subtask_running.svg b/frontend/public/assets/task/subtask_running.svg new file mode 100644 index 00000000..ce473d6e --- /dev/null +++ b/frontend/public/assets/task/subtask_running.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/task/subtask_successful.svg b/frontend/public/assets/task/subtask_successful.svg new file mode 100644 index 00000000..01a15ef0 --- /dev/null +++ b/frontend/public/assets/task/subtask_successful.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/tenant/deadlock.svg b/frontend/public/assets/tenant/deadlock.svg new file mode 100644 index 00000000..adab3fe6 --- /dev/null +++ b/frontend/public/assets/tenant/deadlock.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/tenant/no_deadlock.svg b/frontend/public/assets/tenant/no_deadlock.svg new file mode 100644 index 00000000..237480b6 --- /dev/null +++ b/frontend/public/assets/tenant/no_deadlock.svg @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/tenant/no_deadlock_data.svg b/frontend/public/assets/tenant/no_deadlock_data.svg new file mode 100644 index 00000000..34b38fa3 --- /dev/null +++ b/frontend/public/assets/tenant/no_deadlock_data.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/tenant/polyline.svg b/frontend/public/assets/tenant/polyline.svg new file mode 100644 index 00000000..abddedd1 --- /dev/null +++ b/frontend/public/assets/tenant/polyline.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/tenant/tenant.svg b/frontend/public/assets/tenant/tenant.svg new file mode 100644 index 00000000..11ba6b6d --- /dev/null +++ b/frontend/public/assets/tenant/tenant.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/unit/cpu.svg b/frontend/public/assets/unit/cpu.svg new file mode 100644 index 00000000..268825f7 --- /dev/null +++ b/frontend/public/assets/unit/cpu.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/unit/disk.svg b/frontend/public/assets/unit/disk.svg new file mode 100644 index 00000000..87fd436e --- /dev/null +++ b/frontend/public/assets/unit/disk.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/unit/memory.svg b/frontend/public/assets/unit/memory.svg new file mode 100644 index 00000000..c522c0ca --- /dev/null +++ b/frontend/public/assets/unit/memory.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/unit/region.svg b/frontend/public/assets/unit/region.svg new file mode 100644 index 00000000..2f0946b7 --- /dev/null +++ b/frontend/public/assets/unit/region.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/unit/replica.svg b/frontend/public/assets/unit/replica.svg new file mode 100644 index 00000000..b9adeceb --- /dev/null +++ b/frontend/public/assets/unit/replica.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/unit/server.svg b/frontend/public/assets/unit/server.svg new file mode 100644 index 00000000..529ce895 --- /dev/null +++ b/frontend/public/assets/unit/server.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/unit/tenant.svg b/frontend/public/assets/unit/tenant.svg new file mode 100644 index 00000000..a180077b --- /dev/null +++ b/frontend/public/assets/unit/tenant.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/unit/unit.svg b/frontend/public/assets/unit/unit.svg new file mode 100644 index 00000000..8131954f --- /dev/null +++ b/frontend/public/assets/unit/unit.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/unit/zone.svg b/frontend/public/assets/unit/zone.svg new file mode 100644 index 00000000..ad6be573 --- /dev/null +++ b/frontend/public/assets/unit/zone.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/zone/creating.svg b/frontend/public/assets/zone/creating.svg new file mode 100644 index 00000000..50f04355 --- /dev/null +++ b/frontend/public/assets/zone/creating.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/zone/deleted.svg b/frontend/public/assets/zone/deleted.svg new file mode 100644 index 00000000..812bb4f1 --- /dev/null +++ b/frontend/public/assets/zone/deleted.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/zone/deleting.svg b/frontend/public/assets/zone/deleting.svg new file mode 100644 index 00000000..ad729194 --- /dev/null +++ b/frontend/public/assets/zone/deleting.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/zone/disabled.svg b/frontend/public/assets/zone/disabled.svg new file mode 100644 index 00000000..812bb4f1 --- /dev/null +++ b/frontend/public/assets/zone/disabled.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/zone/error.svg b/frontend/public/assets/zone/error.svg new file mode 100644 index 00000000..42bc3b7b --- /dev/null +++ b/frontend/public/assets/zone/error.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/zone/operating.svg b/frontend/public/assets/zone/operating.svg new file mode 100644 index 00000000..2746f0de --- /dev/null +++ b/frontend/public/assets/zone/operating.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/zone/restarting.svg b/frontend/public/assets/zone/restarting.svg new file mode 100644 index 00000000..ad729194 --- /dev/null +++ b/frontend/public/assets/zone/restarting.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/zone/running.svg b/frontend/public/assets/zone/running.svg new file mode 100644 index 00000000..45e57a7b --- /dev/null +++ b/frontend/public/assets/zone/running.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/zone/service_stopped.svg b/frontend/public/assets/zone/service_stopped.svg new file mode 100644 index 00000000..812bb4f1 --- /dev/null +++ b/frontend/public/assets/zone/service_stopped.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/zone/starting.svg b/frontend/public/assets/zone/starting.svg new file mode 100644 index 00000000..ad729194 --- /dev/null +++ b/frontend/public/assets/zone/starting.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/zone/stopped.svg b/frontend/public/assets/zone/stopped.svg new file mode 100644 index 00000000..812bb4f1 --- /dev/null +++ b/frontend/public/assets/zone/stopped.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/zone/stopping.svg b/frontend/public/assets/zone/stopping.svg new file mode 100644 index 00000000..ad729194 --- /dev/null +++ b/frontend/public/assets/zone/stopping.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/assets/zone/unavailable.svg b/frontend/public/assets/zone/unavailable.svg new file mode 100644 index 00000000..42bc3b7b --- /dev/null +++ b/frontend/public/assets/zone/unavailable.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/public/js/iconfont.js b/frontend/public/js/iconfont.js new file mode 100644 index 00000000..37cb3a0c --- /dev/null +++ b/frontend/public/js/iconfont.js @@ -0,0 +1 @@ +window._iconfont_svg_string_3786261='',function(t){var a=(a=document.getElementsByTagName("script"))[a.length-1],l=a.getAttribute("data-injectcss"),a=a.getAttribute("data-disable-injectsvg");if(!a){var i,o,h,p,d,e=function(a,l){l.parentNode.insertBefore(a,l)};if(l&&!t.__iconfont__svg__cssinject__){t.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}i=function(){var a,l=document.createElement("div");l.innerHTML=t._iconfont_svg_string_3786261,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(a=document.body).firstChild?e(l,a.firstChild):a.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(i,0):(o=function(){document.removeEventListener("DOMContentLoaded",o,!1),i()},document.addEventListener("DOMContentLoaded",o,!1)):document.attachEvent&&(h=i,p=t.document,d=!1,y(),p.onreadystatechange=function(){"complete"==p.readyState&&(p.onreadystatechange=null,s())})}function s(){d||(d=!0,h())}function y(){try{p.documentElement.doScroll("left")}catch(a){return void setTimeout(y,50)}s()}}(window); \ No newline at end of file diff --git a/frontend/public/lottie/backup.json b/frontend/public/lottie/backup.json new file mode 100644 index 00000000..5503d443 --- /dev/null +++ b/frontend/public/lottie/backup.json @@ -0,0 +1 @@ +{"v":"5.9.6","fr":60,"ip":0,"op":40,"w":36,"h":36,"nm":"backup_che","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"▽ backup_che","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,18,0],"ix":2,"l":2},"a":{"a":0,"k":[18,18,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"蓝色","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":10,"s":[100]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[90]},{"t":10,"s":[0]}],"ix":10},"p":{"a":0,"k":[13,23,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,4.333]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,6.667]},"t":0,"s":[60,60,100]},{"t":10,"s":[100,100,100]}],"ix":6,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('缩放 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('缩放 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('缩放 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"}},"ao":0,"ef":[{"ty":5,"nm":"缩放 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Bounce","np":3,"mn":"ADBE Slider Control","ix":2,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Friction","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.55,0],[0,0],[0,-0.55],[0,0],[0.55,0],[0,0],[0,0.55],[0,0]],"o":[[0,0],[0.55,0],[0,0],[0,0.55],[0,0],[-0.55,0],[0,0],[0,-0.55]],"v":[[-3.5,-4.5],[3.5,-4.5],[4.5,-3.5],[4.5,3.5],[3.5,4.5],[-3.5,4.5],[-4.5,3.5],[-4.5,-3.5]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.415686279535,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"蓝色","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"绿色","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":8,"s":[0]},{"t":24,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[23,13,0],"ix":2,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('位置 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('位置 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('位置 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,17.667]},"o":{"x":[1,1,1],"y":[0,0,0]},"t":8,"s":[60,60,100]},{"t":24,"s":[100,100,100]}],"ix":6,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('缩放 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('缩放 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('缩放 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"}},"ao":0,"ef":[{"ty":5,"nm":"位置 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Bounce","np":3,"mn":"ADBE Slider Control","ix":2,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Friction","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":4,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Bounce","np":3,"mn":"ADBE Slider Control","ix":5,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Friction","np":3,"mn":"ADBE Slider Control","ix":6,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":7,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Bounce","np":3,"mn":"ADBE Slider Control","ix":8,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Friction","np":3,"mn":"ADBE Slider Control","ix":9,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":10,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Bounce","np":3,"mn":"ADBE Slider Control","ix":11,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Friction","np":3,"mn":"ADBE Slider Control","ix":12,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-0.55],[0,0],[0.55,0],[0,0],[0,0],[0,0],[0.33,0.32],[0.48,0.04],[0,0],[0,0],[0,0],[-0.55,0]],"o":[[0.55,0],[0,0],[0,0.55],[0,0],[0,0],[0,0],[-0.04,-0.48],[-0.32,-0.33],[0,0],[0,0],[0,0],[0,-0.55],[0,0]],"v":[[3.5,-4.5],[4.5,-3.5],[4.5,3.5],[3.5,4.5],[0.5,4.5],[0.5,1.5],[0.49,1.32],[-0.09,0.09],[-1.32,-0.49],[-1.5,-0.5],[-4.5,-0.5],[-4.5,-3.5],[-3.5,-4.5]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.039215687662,0.75686275959,0.521568655968,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"绿色","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"矩形","parent":1,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,18,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[18,18],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/frontend/public/lottie/diagnosis.json b/frontend/public/lottie/diagnosis.json new file mode 100644 index 00000000..090fa819 --- /dev/null +++ b/frontend/public/lottie/diagnosis.json @@ -0,0 +1 @@ +{"v":"5.9.6","fr":60,"ip":0,"op":40,"w":36,"h":36,"nm":"diagnose_che","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"▽ diagnose_che","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,18,0],"ix":2,"l":2},"a":{"a":0,"k":[18,18,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"竖","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[17,22,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[1,0.833,1]},"o":{"x":[1,1,1],"y":[0,0,0]},"t":0,"s":[100,0,100]},{"t":24,"s":[100,100,100]}],"ix":6,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('缩放 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('缩放 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('缩放 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"}},"ao":0,"ef":[{"ty":5,"nm":"缩放 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Bounce","np":3,"mn":"ADBE Slider Control","ix":2,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Friction","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.28,0],[-0.04,-0.23],[0,0],[0,0],[0.28,0],[0.04,0.23],[0,0],[0,0]],"o":[[0.25,0],[0,0],[0,0],[0,0.28],[-0.25,0],[0,0],[0,0],[0,-0.28]],"v":[[0,-2],[0.49,-1.59],[0.5,-1.5],[0.5,1.5],[0,2],[-0.49,1.59],[-0.5,1.5],[-0.5,-1.5]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"竖","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"横","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[17,22,0],"ix":2,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('位置 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('位置 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('位置 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,-15.667]},"o":{"x":[1,1,1],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":24,"s":[100,100,100]}],"ix":6,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('缩放 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('缩放 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('缩放 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"}},"ao":0,"ef":[{"ty":5,"nm":"缩放 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Bounce","np":3,"mn":"ADBE Slider Control","ix":2,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Friction","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":4,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Bounce","np":3,"mn":"ADBE Slider Control","ix":5,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Friction","np":3,"mn":"ADBE Slider Control","ix":6,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-0.28],[0.23,-0.04],[0,0],[0,0],[0,0.28],[-0.23,0.04],[0,0]],"o":[[0.28,0],[0,0.25],[0,0],[0,0],[-0.28,0],[0,-0.25],[0,0],[0,0]],"v":[[1.5,-0.5],[2,0],[1.59,0.49],[1.5,0.5],[-1.5,0.5],[-2,0],[-1.59,-0.49],[-1.5,-0.5]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"横","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"绿色","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[100]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":0,"s":[-90]},{"t":24,"s":[0]}],"ix":10,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('旋转 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('旋转 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('旋转 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"},"p":{"a":0,"k":[4,13,0],"ix":2,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('位置 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('位置 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('位置 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"},"a":{"a":0,"k":[-13,3,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,11.667,11.667]},"t":0,"s":[30,100,100]},{"t":24,"s":[100,100,100]}],"ix":6,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('缩放 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('缩放 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('缩放 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"}},"ao":0,"ef":[{"ty":5,"nm":"缩放 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Bounce","np":3,"mn":"ADBE Slider Control","ix":2,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Friction","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":4,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Bounce","np":3,"mn":"ADBE Slider Control","ix":5,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Friction","np":3,"mn":"ADBE Slider Control","ix":6,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"旋转 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":7,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"旋转 - Bounce","np":3,"mn":"ADBE Slider Control","ix":8,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"旋转 - Friction","np":3,"mn":"ADBE Slider Control","ix":9,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.55,0],[0,0],[0,-0.55],[0,0],[0,0],[0,0]],"o":[[0,0],[0.55,0],[0,0],[0,0],[0,0],[0,-0.55]],"v":[[-5.5,-1.5],[5.5,-1.5],[6.5,-0.5],[6.5,1.5],[-6.5,1.5],[-6.5,-0.5]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.039215687662,0.75686275959,0.521568655968,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"绿色","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"蓝色","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[17,31,0],"ix":2,"l":2},"a":{"a":0,"k":[0,8,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0.55,0],[0,0],[0,0.55]],"o":[[0,0],[0,0],[0,0.55],[0,0],[-0.55,0],[0,0]],"v":[[-6.5,-4],[6.5,-4],[6.5,3],[5.5,4],[-5.5,4],[-6.5,3]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.415686279535,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"蓝色","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"矩形","parent":1,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,18,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[18,18],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/frontend/public/lottie/log.json b/frontend/public/lottie/log.json new file mode 100644 index 00000000..ffda0a4f --- /dev/null +++ b/frontend/public/lottie/log.json @@ -0,0 +1 @@ +{"v":"5.9.6","fr":60,"ip":0,"op":40,"w":36,"h":36,"nm":"log_che","ddd":1,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"▽ log_che","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,18,0],"ix":2,"l":2},"a":{"a":0,"k":[18,18,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"绿色","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[23.516,25.516,0],"ix":2,"l":2},"a":{"a":0,"k":[-0.484,-0.484,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,-15.667]},"o":{"x":[0.79,0.79,0.79],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":24,"s":[100,100,100]}],"ix":6,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('缩放 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('缩放 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('缩放 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"}},"ao":0,"ef":[{"ty":5,"nm":"缩放 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Bounce","np":3,"mn":"ADBE Slider Control","ix":2,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Friction","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,-3],[3,-3],[-3,3]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"rd","nm":"圆角 1","r":{"a":0,"k":1,"ix":1},"ix":2,"mn":"ADBE Vector Filter - RC","hd":false},{"ty":"fl","c":{"a":0,"k":[0.039215687662,0.75686275959,0.521568655968,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"绿色","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"遮罩","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":1,"y":0},"t":0,"s":[30,32,0],"to":[-2.333,-2.333,0],"ti":[2.333,2.333,0]},{"t":24,"s":[16,18,0]}],"ix":2,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('位置 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('位置 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('位置 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"},"a":{"a":0,"k":[-12,-14,0],"ix":1,"l":2},"s":{"a":0,"k":[100,85.43,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":5,"nm":"位置 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Bounce","np":3,"mn":"ADBE Slider Control","ix":2,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Friction","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[12,14],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":1,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.415686279535,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"蓝色","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":1,"ind":4,"ty":4,"nm":"蓝色","tt":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"rx":{"a":0,"k":0,"ix":8},"ry":{"a":0,"k":0,"ix":9},"rz":{"a":0,"k":0,"ix":10},"or":{"a":0,"k":[0,0,0],"ix":7},"p":{"a":0,"k":[6,4,0],"ix":2},"a":{"a":0,"k":[-12,-14,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[1,1,1],"y":[0,0,0]},"t":0,"s":[0,0,0]},{"t":16,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[12,14],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":1,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.415686279535,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"蓝色","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"矩形","parent":1,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,18,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[18,18],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/frontend/public/lottie/monitor.json b/frontend/public/lottie/monitor.json new file mode 100644 index 00000000..8eaab22a --- /dev/null +++ b/frontend/public/lottie/monitor.json @@ -0,0 +1 @@ +{"v":"5.9.6","fr":60,"ip":0,"op":40,"w":36,"h":36,"nm":"monitor_che","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"遮罩","td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[18,18,0],"to":[4.167,0,0],"ti":[-4.167,0,0]},{"t":39,"s":[43,18,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[23.53,23.53],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0.444,-0.584],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[108.489,108.489],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"数据线","tt":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[17,17.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0.15,0.01],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.12,-0.01],[0,0],[0,0],[0,0]],"o":[[0,0],[-0.1,0.11],[0,0],[0,0],[0,0],[0,0],[0,0],[0.1,-0.07],[0,0],[0,0],[0,0],[0,0]],"v":[[6.506,-2.556],[2.85,1.1],[2.46,1.25],[2.38,1.24],[-1.39,0.29],[-5.497,3.354],[-5.503,2.127],[-1.8,-0.65],[-1.47,-0.75],[-1.38,-0.74],[2.35,0.2],[6.509,-3.959]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"数据线","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"绿色","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[1],"y":[0]},"t":0,"s":[100]},{"t":8,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,6,0],"ix":2,"l":2},"a":{"a":0,"k":[0,-8.164,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[1,0.833,1]},"o":{"x":[1,1,1],"y":[0,0,0]},"t":0,"s":[100,0,100]},{"t":8,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-0.55],[0,0],[0,0],[0.15,0.01],[0,0],[0,0],[0.1,-0.06],[0,0],[0,0],[0,0],[-0.55,0]],"o":[[0.55,0],[0,0],[0,0],[-0.1,0.1],[0,0],[0,0],[-0.12,-0.03],[0,0],[0,0],[0,0],[0,-0.55],[0,0]],"v":[[5,-4.082],[6,-3.082],[6,-2.082],[1.89,2.028],[1.5,2.168],[1.42,2.158],[-1.99,1.308],[-2.33,1.348],[-2.41,1.388],[-6,4.078],[-6,-3.082],[-5,-4.082]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.039215687662,0.75686275959,0.521568655968,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"绿色","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"蓝色","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[1],"y":[0]},"t":0,"s":[100]},{"t":8,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,30,0],"ix":2,"l":2},"a":{"a":0,"k":[0,10.5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[1,0.833,1]},"o":{"x":[1,1,1],"y":[0,0,0]},"t":0,"s":[100,0,100]},{"t":8,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0.55,0],[0,0],[0,0.55],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0.55],[0,0],[-0.55,0],[0,0],[0,0]],"v":[[-2,-2.25],[2,-1.25],[6,-5.25],[6,4.25],[5,5.25],[-5,5.25],[-6,4.25],[-6,0.75]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"rd","nm":"圆角 1","r":{"a":0,"k":0.5,"ix":1},"ix":2,"mn":"ADBE Vector Filter - RC","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.415686279535,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"蓝色","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"矩形","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,18,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[18,18],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/frontend/public/lottie/overview.json b/frontend/public/lottie/overview.json new file mode 100644 index 00000000..a6ed6c6f --- /dev/null +++ b/frontend/public/lottie/overview.json @@ -0,0 +1 @@ +{"v":"5.9.6","fr":60,"ip":0,"op":40,"w":36,"h":36,"nm":"overview_che","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"绿色","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('旋转 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('旋转 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('旋转 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"},"p":{"a":0,"k":[27.5,30,0],"ix":2,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('位置 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('位置 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('位置 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"},"a":{"a":0,"k":[0,12,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[1,0.833,1]},"o":{"x":[0.8,0.8,0.8],"y":[0,0,0]},"t":0,"s":[100,10,100]},{"t":24,"s":[100,100,100]}],"ix":6,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('缩放 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('缩放 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('缩放 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"}},"ao":0,"ef":[{"ty":5,"nm":"缩放 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Bounce","np":3,"mn":"ADBE Slider Control","ix":2,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Friction","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":4,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Bounce","np":3,"mn":"ADBE Slider Control","ix":5,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Friction","np":3,"mn":"ADBE Slider Control","ix":6,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"旋转 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":7,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"旋转 - Bounce","np":3,"mn":"ADBE Slider Control","ix":8,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"旋转 - Friction","np":3,"mn":"ADBE Slider Control","ix":9,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[3.5,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":1,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.039215687662,0.75686275959,0.521568655968,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形备份 12","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"中间","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[99]}],"ix":11},"r":{"a":0,"k":0,"ix":10,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('旋转 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('旋转 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('旋转 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"},"p":{"a":0,"k":[18.5,30,0],"ix":2,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('位置 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('位置 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('位置 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"},"a":{"a":0,"k":[0,9,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[1,0.833,1]},"o":{"x":[0.8,0.8,0.8],"y":[0,0,0]},"t":0,"s":[100,40,100]},{"t":24,"s":[100,100,100]}],"ix":6,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('缩放 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('缩放 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('缩放 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"}},"ao":0,"ef":[{"ty":5,"nm":"缩放 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Bounce","np":3,"mn":"ADBE Slider Control","ix":2,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Friction","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":4,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Bounce","np":3,"mn":"ADBE Slider Control","ix":5,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Friction","np":3,"mn":"ADBE Slider Control","ix":6,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"旋转 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":7,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"旋转 - Bounce","np":3,"mn":"ADBE Slider Control","ix":8,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"旋转 - Friction","np":3,"mn":"ADBE Slider Control","ix":9,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[3.5,9],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":1,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.415686279535,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形备份 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"左侧","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[9.5,30,0],"ix":2,"l":2},"a":{"a":0,"k":[0,6,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":0,"s":[100,210,100]},{"t":24,"s":[100,100,100]}],"ix":6,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('缩放 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('缩放 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('缩放 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"}},"ao":0,"ef":[{"ty":5,"nm":"缩放 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Bounce","np":3,"mn":"ADBE Slider Control","ix":2,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Friction","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":4,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Bounce","np":3,"mn":"ADBE Slider Control","ix":5,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Friction","np":3,"mn":"ADBE Slider Control","ix":6,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[3.5,6],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":1,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.415686279535,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"背景","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,18,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[18,18],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":0,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":0,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0}],"markers":[{"tm":40,"cm":"1","dr":0}]} \ No newline at end of file diff --git a/frontend/public/lottie/property.json b/frontend/public/lottie/property.json new file mode 100644 index 00000000..6599a3dd --- /dev/null +++ b/frontend/public/lottie/property.json @@ -0,0 +1 @@ +{"v":"5.9.6","fr":60,"ip":0,"op":40,"w":36,"h":36,"nm":"canshu_che","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"绿色滑块","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":8,"s":[0]},{"t":24,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":1,"y":0},"t":8,"s":[26,11,0],"to":[-1.833,0,0],"ti":[1.833,0,0]},{"t":24,"s":[15,11,0]}],"ix":2,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('位置 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('位置 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('位置 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":5,"nm":"位置 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Bounce","np":3,"mn":"ADBE Slider Control","ix":2,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Friction","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-0.55],[0,0],[0.55,0],[0,0],[0,0.55],[0,0],[-0.55,0],[0,0]],"o":[[0,0],[0,0.55],[0,0],[-0.55,0],[0,0],[0,-0.55],[0,0],[0.55,0]],"v":[[1.5,-2],[1.5,2],[0.5,3],[-0.5,3],[-1.5,2],[-1.5,-2],[-0.5,-3],[0.5,-3]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.039215687662,0.75686275959,0.521568655968,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"绿色滑块","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"蓝色滑块","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":8,"s":[0]},{"t":24,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":1,"y":0},"t":8,"s":[10,25,0],"to":[1.833,0,0],"ti":[-1.833,0,0]},{"t":24,"s":[21,25,0]}],"ix":2,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('位置 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('位置 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('位置 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":5,"nm":"位置 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Bounce","np":3,"mn":"ADBE Slider Control","ix":2,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Friction","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-0.55],[0,0],[0.55,0],[0,0],[0,0.55],[0,0],[-0.55,0],[0,0]],"o":[[0,0],[0,0.55],[0,0],[-0.55,0],[0,0],[0,-0.55],[0,0],[0.55,0]],"v":[[1.5,-2],[1.5,2],[0.5,3],[-0.5,3],[-1.5,2],[-1.5,-2],[-0.5,-3],[0.5,-3]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.415686279535,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"蓝色滑块","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"遮蓝色","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":8,"s":[0]},{"t":24,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":1,"y":0},"t":8,"s":[14,24.661,0],"to":[2,0,0],"ti":[-2,0,0]},{"t":24,"s":[26,24.661,0]}],"ix":2,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('位置 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('位置 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('位置 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"},"a":{"a":0,"k":[-5.991,-7.339,0],"ix":1,"l":2},"s":{"a":0,"k":[46.154,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":5,"nm":"位置 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Bounce","np":3,"mn":"ADBE Slider Control","ix":2,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Friction","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4.834,10.177],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-8.167,-7.339],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[90.044,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"蓝色","tt":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":6,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[32,25,0],"ix":2,"l":2},"a":{"a":0,"k":[14,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":0,"s":[0,100,100]},{"t":6,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.55,0],[0,0],[0,-0.55],[0,0],[0.55,0],[0,0],[0,0.55],[0,0]],"o":[[0,0],[0.55,0],[0,0],[0,0.55],[0,0],[-0.55,0],[0,0],[0,-0.55]],"v":[[-6,-1.5],[6,-1.5],[7,-0.5],[7,0.5],[6,1.5],[-6,1.5],[-7,0.5],[-7,-0.5]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.415686279535,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"蓝色","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"遮绿色","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":8,"s":[0]},{"t":24,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":1,"y":0},"t":8,"s":[24,10.661,0],"to":[-2,0,0],"ti":[2,0,0]},{"t":24,"s":[12,10.661,0]}],"ix":2,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('位置 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('位置 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('位置 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"},"a":{"a":0,"k":[-5.991,-7.339,0],"ix":1,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('锚点 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('锚点 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('锚点 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"},"s":{"a":0,"k":[46.154,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":5,"nm":"位置 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Bounce","np":3,"mn":"ADBE Slider Control","ix":2,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"位置 - Friction","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"锚点 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":4,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"锚点 - Bounce","np":3,"mn":"ADBE Slider Control","ix":5,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"锚点 - Friction","np":3,"mn":"ADBE Slider Control","ix":6,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[4.834,10.177],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-8.167,-7.339],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[90.044,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"绿色","tt":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":6,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[4,11,0],"ix":2,"l":2},"a":{"a":0,"k":[-14,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":0,"s":[0,100,100]},{"t":6,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.55,0],[0,0],[0,-0.55],[0,0],[0.55,0],[0,0],[0,0.55],[0,0]],"o":[[0,0],[0.55,0],[0,0],[0,0.55],[0,0],[-0.55,0],[0,0],[0,-0.55]],"v":[[-6,-1.5],[6,-1.5],[7,-0.5],[7,0.5],[6,1.5],[-6,1.5],[-7,0.5],[-7,-0.5]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.039215687662,0.75686275959,0.521568655968,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"绿色","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/frontend/public/lottie/tenant.json b/frontend/public/lottie/tenant.json new file mode 100644 index 00000000..50d7de3d --- /dev/null +++ b/frontend/public/lottie/tenant.json @@ -0,0 +1 @@ +{"v":"5.9.6","fr":60,"ip":0,"op":40,"w":36,"h":36,"nm":"tenant_che","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"中心","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,18,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,-15.667]},"o":{"x":[1,1,1],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":24,"s":[100,100,100]}],"ix":6,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('缩放 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('缩放 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('缩放 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"}},"ao":0,"ef":[{"ty":5,"nm":"缩放 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Bounce","np":3,"mn":"ADBE Slider Control","ix":2,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Friction","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":4,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Bounce","np":3,"mn":"ADBE Slider Control","ix":5,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Friction","np":3,"mn":"ADBE Slider Control","ix":6,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":7,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Bounce","np":3,"mn":"ADBE Slider Control","ix":8,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"缩放 - Friction","np":3,"mn":"ADBE Slider Control","ix":9,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0.002,-3.381],[2.932,-1.691],[2.932,1.689],[0.002,3.379],[-2.928,1.689],[-2.928,-1.691]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.415686279535,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"中心","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"遮绿色","td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":180,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":1,"y":0},"t":0,"s":[-0.954,16.148,0],"to":[5.667,0,0],"ti":[-5.667,0,0]},{"t":24,"s":[33.046,16.148,0]}],"ix":2,"l":2},"a":{"a":0,"k":[17.296,-3,0],"ix":1,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('锚点 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('锚点 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('锚点 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"},"s":{"a":0,"k":[108.589,454.572,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":5,"nm":"锚点 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"锚点 - Bounce","np":3,"mn":"ADBE Slider Control","ix":2,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"锚点 - Friction","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[33.796,5.217],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0.398,-0.392],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"绿色","tt":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[17.998,7.646,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.31,-0.17],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0.31,-0.17]],"v":[[0.502,-2.538],[6.432,0.891],[6.512,0.941],[3.512,2.671],[0.002,0.641],[-3.508,2.671],[-6.508,0.941],[-6.428,0.891],[-6.428,0.891],[-0.498,-2.538]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.039215687662,0.75686275959,0.521568655968,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"绿色","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"遮蓝色","td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":180,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":1,"y":0},"t":0,"s":[-0.954,35.148,0],"to":[-5.667,0.167,0],"ti":[5.667,-0.167,0]},{"t":24,"s":[-34.954,36.148,0]}],"ix":2,"l":2},"a":{"a":0,"k":[17.296,-3,0],"ix":1,"l":2,"x":"var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('锚点 - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('锚点 - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('锚点 - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}"},"s":{"a":0,"k":[108.589,636.676,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":5,"nm":"锚点 - Overshoot","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"锚点 - Bounce","np":3,"mn":"ADBE Slider Control","ix":2,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"锚点 - Friction","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"滑块","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"ix":1,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[33.796,5.217],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0.398,-0.392],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"下","tt":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[17.999,22.519,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0.31,-0.17],[0,0],[0.31,0.18],[0,0],[0,0.36]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0.36],[0,0],[-0.31,0.18],[0,0],[-0.31,-0.17],[0,0]],"v":[[-6.929,-5.586],[-3.929,-3.856],[-3.929,0.004],[0.001,2.274],[3.931,0.004],[3.931,-3.856],[6.931,-5.586],[6.931,1.164],[6.431,2.024],[0.501,5.454],[-0.499,5.454],[-6.429,2.024],[-6.929,1.164]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.415686279535,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[200,200],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"下","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/frontend/src/app.ts b/frontend/src/app.ts new file mode 100644 index 00000000..6482505d --- /dev/null +++ b/frontend/src/app.ts @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { formatMessage } from '@/util/intl'; +import { message } from '@oceanbase/design'; + +export const dva = { + config: { + // 在 onError 函数当中做的处理,需要同步到 UseRequestProvider(全局搜索)当中进行相同处理。使用 useRequest 抛的错暂时不能被 onError 函数捕获到。 + onError(err: ErrorEvent, dispatch) { + // 用来捕获全局错误,避免页面崩溃 + if (err.preventDefault) { + err.preventDefault(); + } + message.error( + formatMessage( + { + id: 'ocp-express.src.app.DvaErrorErrmessage', + defaultMessage: 'dva error:{errMessage}', + }, + { errMessage: err.message } + ), + 3 + ); + // 3010 为新版接口找不到密码箱连接的错误码 + if (err.message === '3010') { + dispatch({ + type: 'global/update', + payload: { + showCredentialModal: true, + credentialErrorData: err?.data || {}, + }, + }); + } else if (err.message === '301000') { + // 301000 为旧版接口找不到密码箱连接的错误码 + dispatch({ + type: 'global/update', + payload: { + showCredentialModal: true, + }, + }); + } + }, + }, +}; diff --git a/frontend/src/asset/diagnosis.svg b/frontend/src/asset/diagnosis.svg new file mode 100644 index 00000000..69608cd0 --- /dev/null +++ b/frontend/src/asset/diagnosis.svg @@ -0,0 +1,31 @@ + + + + + diagnose_un + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/asset/drag_icon.svg b/frontend/src/asset/drag_icon.svg new file mode 100644 index 00000000..b2538c94 --- /dev/null +++ b/frontend/src/asset/drag_icon.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/asset/drilldown.svg b/frontend/src/asset/drilldown.svg new file mode 100644 index 00000000..f2de35e0 --- /dev/null +++ b/frontend/src/asset/drilldown.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/asset/fail.svg b/frontend/src/asset/fail.svg new file mode 100644 index 00000000..2815f8fb --- /dev/null +++ b/frontend/src/asset/fail.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/asset/monitor.svg b/frontend/src/asset/monitor.svg new file mode 100644 index 00000000..2d4c1889 --- /dev/null +++ b/frontend/src/asset/monitor.svg @@ -0,0 +1,37 @@ + + + + + monitor_un + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/asset/sqlDigest.svg b/frontend/src/asset/sqlDigest.svg new file mode 100644 index 00000000..5547f275 --- /dev/null +++ b/frontend/src/asset/sqlDigest.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/asset/success.svg b/frontend/src/asset/success.svg new file mode 100644 index 00000000..388d7069 --- /dev/null +++ b/frontend/src/asset/success.svg @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/component/Access.tsx b/frontend/src/component/Access.tsx new file mode 100644 index 00000000..f97719e9 --- /dev/null +++ b/frontend/src/component/Access.tsx @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { formatMessage } from '@/util/intl'; +import React from 'react'; +import { Button, Checkbox, Menu, Switch, Tooltip } from '@oceanbase/design'; +import { isObject } from 'lodash'; +import type { TooltipProps } from '@oceanbase/design/es/tooltip'; + +export interface AccessProps { + /* 是否可访问 */ + accessible: boolean; + /* 所见即所得模式下,无权限时的展示内容,与 tooltip 属性是互斥的 (优先级: tooltip > fallback),不能同时设置 */ + fallback?: React.ReactNode; + /* 默认是所见即所得模式,如果想展示为 disabled + Tooltip 模式,则需要设置 tooltip 属性 */ + tooltip?: + | boolean + | (Omit & { + // 将 title 改为可选属性 + title?: React.ReactNode; + }); + children: React.ReactElement; +} + +export default ({ + accessible = true, + fallback, + tooltip = false, + children, + ...restProps +}: AccessProps) => { + const childrenProps = children.props || {}; + const disabled = !accessible || childrenProps.disabled; + const tooltipProps = isObject(tooltip) ? tooltip || {} : {}; + const { title, ...restTooltipProps } = tooltipProps; + const element = React.cloneElement(children, { + style: { + ...(disabled && + (children.type === Button || children.type === Checkbox || children.type === Switch) + ? { pointerEvents: 'none' } + : {}), + ...childrenProps.style, + }, + + ...(children.type === Menu.Item || children.type === Menu.SubMenu + ? { eventKey: children.key } + : {}), + ...(tooltip + ? { + // 根据 accessible 设置 disabled + disabled, + } + : {}), + }); + return tooltip ? ( + // disabled + Tooltip 模式 + + + {element} + + + ) : accessible ? ( + + {element} + + ) : ( + <>{fallback || null} + ); +}; diff --git a/frontend/src/component/AddUnitSpecModal.tsx b/frontend/src/component/AddUnitSpecModal.tsx new file mode 100644 index 00000000..37ed832a --- /dev/null +++ b/frontend/src/component/AddUnitSpecModal.tsx @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { formatMessage } from '@/util/intl'; +import { connect } from 'umi'; +import { Form, InputNumber, Modal } from '@oceanbase/design'; +import { isNullValue } from '@oceanbase/util'; +import MyInput from '@/component/MyInput'; +import type { ValueType } from '@/component/RangeInput'; +import { MODAL_FORM_ITEM_LAYOUT, NAME_RULE } from '@/constant'; + +const FormItem = Form.Item; + +export interface AddUnitSpecModalProps { + visible: boolean; + dispatch: any; + onSuccess: () => void; + /** unitSpec 为空时,为新增 unit 规格; unitSpec 不为空时,为编辑 unit 规格 */ + unitSpec?: API.UnitSpec; + loading: boolean; +} + +const AddUnitSpecModal: React.FC = ({ + dispatch, + unitSpec, + onSuccess, + loading, + ...restProps +}) => { + const isEdit = !!unitSpec; + const [form] = Form.useForm(); + + const { validateFields } = form; + + const validateCPU = (rule, value: ValueType, callback) => { + if (!isNullValue(value) && (value as number) % 0.5 !== 0) { + callback( + formatMessage({ + id: 'ocp-express.src.component.AddUnitSpecModal.MustBeAnIntegerMultipleOf', + defaultMessage: '需要是 0.5 的整数倍', + }) + ); + } + callback(); + }; + + const handleSubmit = () => { + validateFields().then(values => { + const { name = '', maxCpuCoreCount, maxMemorySize } = values; + + if (isEdit) { + dispatch({ + type: 'tenant/modifyUnitSpec', + name: unitSpec?.name, + payload: { + specId: unitSpec?.id, + maxCpuCoreCount, + maxMemorySize, + }, + + onSuccess: () => { + if (onSuccess) { + onSuccess(); + } + }, + }); + } else { + dispatch({ + type: 'tenant/addUnitSpec', + payload: { + name, + maxCpuCoreCount, + maxMemorySize, + }, + + onSuccess: () => { + if (onSuccess) { + onSuccess(); + } + }, + }); + } + }); + }; + + return ( + +
+ + {isEdit ? unitSpec?.name : } + + = 0.5 核,请输入 0.5 的整数倍。', + })} + > + + + = 1 GB,请输入 1 的整数倍。', + })} + > + + +
+
+ ); +}; + +function mapStateToProps({ loading }) { + return { + loading: loading.effects['tenant/modifyUnitSpec'] || loading.effects['tenant/addUnitSpec'], + }; +} + +export default connect(mapStateToProps)(AddUnitSpecModal); diff --git a/frontend/src/component/AobException/index.less b/frontend/src/component/AobException/index.less new file mode 100644 index 00000000..c257538d --- /dev/null +++ b/frontend/src/component/AobException/index.less @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.container { + display: flex; + align-items: center; + height: 80%; + min-height: 500px; + + .imgWrapper { + flex: 0 0 62.5%; + width: 62.5%; + padding-right: 152px; + zoom: 1; + + &::before, + &::after { + display: table; + content: ' '; + } + + &::after { + clear: both; + height: 0; + font-size: 0; + visibility: hidden; + } + } + + .img { + float: right; + width: 100%; + max-width: 430px; + height: 360px; + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: contain; + } + + .content { + flex: auto; + + h1 { + margin-bottom: 24px; + color: #434e59; + font-weight: 600; + font-size: 72px; + line-height: 72px; + } + + .desc { + margin-bottom: 16px; + color: rgba(0, 0, 0, 0.45); + font-size: 20px; + line-height: 28px; + } + + .actions { + button:not(:last-child) { + margin-right: 8px; + } + } + } +} diff --git a/frontend/src/component/AobException/index.style.ts b/frontend/src/component/AobException/index.style.ts new file mode 100644 index 00000000..ca543c93 --- /dev/null +++ b/frontend/src/component/AobException/index.style.ts @@ -0,0 +1,51 @@ +import { createStyles } from 'antd-style'; + +const useStyles = createStyles(() => { + return { + container: { + display: 'flex', + alignItems: 'center', + height: '80%', + minHeight: '500px', + }, + imgWrapper: { + flex: '0 0 62.5%', + width: '62.5%', + paddingRight: '152px', + zoom: '1', + '&::before, &::after': { display: 'table', content: "' '" }, + '&::after': { clear: 'both', height: '0', fontSize: '0', visibility: 'hidden' }, + }, + img: { + float: 'right', + width: '100%', + maxWidth: '430px', + height: '360px', + backgroundRepeat: 'no-repeat', + backgroundPosition: '50% 50%', + backgroundSize: 'contain', + }, + content: { + flex: 'auto', + h1: { + marginBottom: '24px', + color: '#434e59', + fontWeight: '600', + fontSize: '72px', + lineHeight: '72px', + }, + actions: { + 'button:not(:last-child)': { + marginRight: '8px', + } + } + }, + desc: { + marginBottom: '16px', + color: 'rgba(0, 0, 0, 0.45)', + fontSize: '20px', + lineHeight: '28px', + }, + }; +}); +export default useStyles; diff --git a/frontend/src/component/AobException/index.tsx b/frontend/src/component/AobException/index.tsx new file mode 100644 index 00000000..eeeb8c8e --- /dev/null +++ b/frontend/src/component/AobException/index.tsx @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { formatMessage } from '@/util/intl'; +import React, { createElement } from 'react'; +import { Button } from '@oceanbase/design'; +import useStyles from './index.style'; + +interface AobExceptionProps { + title?: React.ReactNode; + desc?: React.ReactNode; + img?: string; + actions?: React.ReactNode; + style?: React.CSSProperties; + className?: string; + linkElement?: string; + backText?: string; + redirect?: string; + onBack?: () => void; +} + +const AobException: React.FC = ({ + className, + backText = formatMessage({ + id: 'ocp-express.component.AobException.ReturnToHomePage', + defaultMessage: '返回首页', + }), + title, + desc, + img, + linkElement = 'a', + actions, + redirect = '/', + onBack, + ...rest +}) => { + const { styles } = useStyles(); + return ( +
+
+
+
+
+

{title}

+
{desc}
+
+ {actions || + (onBack ? ( + + ) : ( + createElement( + linkElement, + { + to: redirect, + href: redirect, + }, + + ) + ))} +
+
+
+ ); +}; + +export default AobException; diff --git a/frontend/src/component/BatchOperationBar/index.less b/frontend/src/component/BatchOperationBar/index.less new file mode 100644 index 00000000..a9bc9c21 --- /dev/null +++ b/frontend/src/component/BatchOperationBar/index.less @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import '~@oceanbase/design/es/theme/index.less'; + +.container { + display: flex; + align-items: center; + justify-content: space-between; + padding: ~'@{sizeSM}px' ~'@{sizeLG}px'; + overflow: hidden; + background-color: @colorPrimaryBg; + border-radius: ~'@{borderRadius}px'; +} +.small { + padding: ~'@{sizeSM}px' ~'@{sizeMD}px'; +} +.large { + padding: ~'@{sizeMD}px' ~'@{sizeLG}px'; +} +.title { + margin-right: ~'@{sizeXS}px'; +} +.small .title { + margin-right: ~'@{sizeMD}px'; +} +.cancel { + margin-left: ~'@{sizeXS}px'; + color: @colorPrimary; + cursor: pointer; +} +.actionItem { + margin-left: ~'@{sizeXS}px'; +} +.left { + display: flex; + align-items: center; + justify-content: flex-start; +} +.right { + display: flex; + align-items: center; + justify-content: flex-end; +} diff --git a/frontend/src/component/BatchOperationBar/index.style.ts b/frontend/src/component/BatchOperationBar/index.style.ts new file mode 100644 index 00000000..a3e6b082 --- /dev/null +++ b/frontend/src/component/BatchOperationBar/index.style.ts @@ -0,0 +1,45 @@ +import { createStyles } from "antd-style"; + +const useStyles = createStyles(({ token }) => { + return { + container: { + display: "flex", + alignItems: "center", + justifyContent: "space-between", + padding: "`~'@{sizeSM}px' ~'@{sizeLG}px'`", + overflow: "hidden", + backgroundColor: token.colorPrimaryBg, + borderRadius: "`~'@{borderRadius}px'`", + }, + small: { + padding: "`~'@{sizeSM}px' ~'@{sizeMD}px'`", + marginRight: "`~'@{sizeMD}px'`", + }, + large: { + padding: "`~'@{sizeMD}px' ~'@{sizeLG}px'`", + }, + title: { + marginRight: "`~'@{sizeMD}px'`", + }, + cancel: { + marginLeft: "`~'@{sizeXS}px'`", + color: token.colorPrimary, + cursor: "pointer", + }, + actionItem: { + marginLeft: "`~'@{sizeXS}px'`", + }, + left: { + display: "flex", + alignItems: "center", + justifyContent: "flex-start", + }, + right: { + display: "flex", + alignItems: "center", + justifyContent: "flex-end", + }, + }; +}); + +export default useStyles; diff --git a/frontend/src/component/BatchOperationBar/index.tsx b/frontend/src/component/BatchOperationBar/index.tsx new file mode 100644 index 00000000..4c7460d8 --- /dev/null +++ b/frontend/src/component/BatchOperationBar/index.tsx @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { formatMessage } from '@/util/intl'; +import React from 'react'; +import classNames from 'classnames'; +import useStyles from './index.style'; + +export interface BatchOperationBarProps { + className?: string; + style?: React.CSSProperties; + size?: 'small' | 'default' | 'large'; + description?: React.ReactNode; + selectedCount?: number; + visible?: boolean; + actions?: React.ReactNode[]; + onCancel?: () => void; + selectedText?: string; + cancelText?: string; +} + +const BatchOperationBar: React.FC = ({ + description, + className, + style, + actions = [], + selectedCount = 0, + visible, + onCancel, + size = 'default', +}) => { + const { styles } = useStyles(); + const realVisible = visible === undefined ? selectedCount > 0 : visible; + return ( +
+
+
+ {formatMessage( + { + id: 'ocp-express.component.BatchOperationBar.SelectedcountSelected', + defaultMessage: '已选 {selectedCount} 项', + }, + { selectedCount }, + )} + {onCancel && ( + + {formatMessage({ + id: 'ocp-express.component.BatchOperationBar.Deselect', + defaultMessage: '取消选择', + })} + + )} +
+ {description &&
{description}
} +
+
+ {actions.map((action, index) => { + return ( +
+ {action} +
+ ); + })} +
+
+ ); +}; + +export default BatchOperationBar; diff --git a/frontend/src/component/BeutifySQL.tsx b/frontend/src/component/BeutifySQL.tsx new file mode 100644 index 00000000..257275b9 --- /dev/null +++ b/frontend/src/component/BeutifySQL.tsx @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { useState, useRef, useEffect, useImperativeHandle } from 'react'; +import { Highlight } from '@oceanbase/ui'; +import { useUpdate } from 'ahooks'; +import { reduce } from 'lodash'; +import { formatSql } from '@/util'; +import { getSqlOperatorList, transRegcharacter } from '@/util/sqlDiagnosis'; + +type sqlOperator = '=' | '<>' | '>' | '<' | '>=' | '<=' | 'BETWEEN' | 'LIKE'; +type sqlOpreaterItem = { + field: string; + operator: sqlOperator; + // maxValue 和 minValue 只有 BETWEEN 情况下才会使用 + minValue: string; + maxValue: string; + value: string; +}; + +type sqlContentErrorType = 'NO_INPUT' | 'ILLEGAL_SPACE' | 'MISS_QUOTATION'; + +export type sqlContentErrorItem = { + type: sqlContentErrorType; +} & sqlOpreaterItem; + +const OCP_LIMIT_KEY = '__OCP_SQL_DIAGNOSIS_LIMIT_INPUT'; + +const getMarkerSqlText = (sqlText: string) => { + const result = getSqlOperatorList(sqlText); + let realSqlText = sqlText; + + result.forEach(({ field, operator, value, maxValue, minValue }, index) => { + const realField = transRegcharacter(field); + const realOperator = transRegcharacter(operator); + const realMinValue = transRegcharacter(minValue); + const realMaxValue = transRegcharacter(maxValue); + const realValue = transRegcharacter(value); + + const regStr = + operator === 'BETWEEN' + ? `(${realField}\\s?${realOperator}\\s?)${realMinValue}(\\n\s+and\\s)${realMaxValue}` + : `(${realField}\\s?${realOperator}\\s?)${realValue}`; + + const reg = new RegExp(regStr, 'i'); + if (operator === 'BETWEEN') { + realSqlText = realSqlText.replace( + reg, + `$1minValue${OCP_LIMIT_KEY}${index}$2maxValue${OCP_LIMIT_KEY}${index}` + ); + } else { + realSqlText = realSqlText.replace(reg, `$1value${OCP_LIMIT_KEY}${index}`); + } + }); + + return realSqlText; +}; + +const getSqlContentErrorList: ( + sqlOperatorList: sqlOpreaterItem[] +) => sqlContentErrorItem[] = sqlOperatorList => { + const errorList = []; + + const getContentErrorType: (s: string) => null | sqlContentErrorType = s => { + // 去除两边的空格 + const content = s?.trim() || ''; + + if (/^\'.*\'$/.test(content) || /^\".*\"$/.test(content)) { + // 包裹了单引号或双引号的内容 + return null; + } else if (content === '?') { + return null; + } else if (content === '') { + return 'NO_INPUT'; + } else if (content.includes(' ')) { + return 'ILLEGAL_SPACE'; + } else if (!/^\d+$/.test(content)) { + // 未包裹双引号且存在除数字以外的字符 + return 'MISS_QUOTATION'; + } + + return null; + }; + + sqlOperatorList.map(({ field, operator, value, minValue, maxValue }) => { + let errorType = null; + if (operator === 'BETWEEN') { + errorType = getContentErrorType(minValue) || getContentErrorType(maxValue); + } else { + errorType = getContentErrorType(value); + } + + if (errorType) { + errorList.push({ + field, + value, + operator, + minValue, + maxValue, + type: errorType, + }); + } + }); + + return errorList; +}; + +const errorColor = 'rgba(232, 104, 74, 0.15)'; +const successColor = 'rgba(90, 216, 216, 0.15)'; + +interface BeutifySQLProps { + sqlText: string; + onChange?: (list: sqlOpreaterItem[]) => void; + edit?: boolean; +} + +export interface BeutifySQLRef { + validateFields: ( + cb?: (sqlContentErrorList: sqlContentErrorItem[], sqlOperatorList: sqlOpreaterItem[]) => void + ) => void; + setSqlOperatorList: (list: sqlOpreaterItem[]) => void; +} + +const BeutifySQL: React.FC = React.forwardRef( + ( + { sqlText, onChange, edit = true }, + + ref + ) => { + const [highlightSqltext, setHighlightSqltext] = useState(''); + const [sqlOperatorList, setSqlOperatorList] = useState([]); + const update = useUpdate(); + + const refCode = useRef(); + + // 向组件外部暴露 validateFields 属性函数,可通过 ref 引用 + useImperativeHandle(ref, () => ({ + validateFields: cb => { + const mySqlContentErrorList = getSqlContentErrorList(sqlOperatorList); + if (mySqlContentErrorList.length > 0) { + mySqlContentErrorList.forEach(({ field, operator }) => { + const e = document.getElementById(field + operator); + if (e?.parentNode?.style) { + e.parentNode.style.backgroundColor = errorColor; + } + }); + } + if (cb) { + cb(mySqlContentErrorList, sqlOperatorList); + } + }, + setSqlOperatorList: list => { + setSqlOperatorList(list); + }, + })); + + useEffect(() => { + if (sqlText) { + const realOperaterList = getSqlOperatorList(sqlText); + setSqlOperatorList(realOperaterList); + + const realSqlText = getMarkerSqlText(sqlText); + setHighlightSqltext(realSqlText); + } + }, [sqlText]); + + useEffect(() => { + if (refCode.current) { + const codeEle = refCode.current?.querySelector('code'); + if (codeEle) { + // 说明已经替换过 Input 组件 + if (codeEle.querySelectorAll('input').length > 0) { + return; + } + + let realHTML = ''; + codeEle?.innerHTML.split('\n').map(rowHtml => { + realHTML += `
${rowHtml}
`; + }); + + // ['valueOCP_LIMIT_KEY0', 'valueOCP_LIMIT_KEY1', 'valueOCP_LIMIT_KEY2', 'valueOCP_LIMIT_KEY3', 'valueOCP_LIMIT_KEY4', 'valueOCP_LIMIT_KEY5', 'valueOCP_LIMIT_KEY6', 'valueOCP_LIMIT_KEY7'] + const inputReg = new RegExp(`\\S+${OCP_LIMIT_KEY}[^\\s;<]+`, 'gi'); + const syntaxList = realHTML.match(inputReg); + syntaxList?.forEach(str => { + const [valueField, valueIndex] = str.split(OCP_LIMIT_KEY); + const value = sqlOperatorList[valueIndex][valueField]; + const field = sqlOperatorList[valueIndex].field; + const operator = sqlOperatorList[valueIndex].operator; + realHTML = realHTML.replace( + str, + `` + ); + }); + + codeEle.innerHTML = realHTML; + + const onInputUpdate = event => { + const l = reduce( + event.target.value || '', + (m, c) => m + (c.charCodeAt(0) < 128 ? 0.55 : 1), + 0 + ); + event.target.style.width = l + 0.5 + 'em'; + if (event?.target?.parentNode?.style?.backgroundColor === errorColor) { + event.target.parentNode.style.backgroundColor = successColor; + } + + const { field = 'value', index } = event.target.dataset; + sqlOperatorList[index][field] = event.target.value; + + if (onChange) { + onChange(sqlOperatorList); + } + + update(); + }; + + codeEle.querySelectorAll('input').forEach(el => { + if (el.parentNode) { + el.parentNode.style.backgroundColor = successColor; + } + + el.addEventListener('input', onInputUpdate); + }); + } + } + }, [refCode.current]); + + return ( +
+ + {formatSql(highlightSqltext)} + +
+ ); + } +); + +export default BeutifySQL; diff --git a/frontend/src/component/BinlogAssociationMsg.tsx b/frontend/src/component/BinlogAssociationMsg.tsx new file mode 100644 index 00000000..22b10b44 --- /dev/null +++ b/frontend/src/component/BinlogAssociationMsg.tsx @@ -0,0 +1,68 @@ +import React, { useState } from 'react'; +import { flatten } from 'lodash'; +import { Alert, Typography } from '@oceanbase/design'; +import { joinComponent } from '@oceanbase/util'; + +const { Paragraph } = Typography; + +export interface BinlogAssociationMsgProps { + clusterType: string; + type: string; + binlogService: API.TenantBinlogService[] | []; +} + +const BinlogAssociationMsg: React.FC = ({ + clusterType, + type, + binlogService = [], +}) => { + const [expanded, setExpanded] = useState(false); + + const instanceList = flatten((binlogService || []).map(item => item?.nodes)) || []; + + const instanceNames = instanceList.map(item => item.instanceName) || []; + + const TEXT = ( + <> + setExpanded(info.expanded), + tooltip: { + placement: 'top', + }, + }} + > + 当前 {clusterType} 与 Binlog 实例: + {joinComponent(instanceNames, item => ( + {item} + ))} + + 关联,本操作会造成 Binlog 服务与下游业务中断, 请谨慎评估业务影响后再进行操作。 + + ); + + return ( + <> + {instanceNames?.length > 0 ? ( + <> + {type === 'text' ? ( + TEXT + ) : ( + + )} + + ) : null} + + ); +}; + +export default BinlogAssociationMsg; diff --git a/frontend/src/component/Chart/index.tsx b/frontend/src/component/Chart/index.tsx new file mode 100644 index 00000000..1cd49d68 --- /dev/null +++ b/frontend/src/component/Chart/index.tsx @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { isObject } from 'lodash'; +import { sortByMoment } from '@oceanbase/util'; +import * as Charts from '@oceanbase/charts'; +import * as OBCharts from '@oceanbase/charts'; + +export type ChartType = + | 'Bar' + | 'Column' + | 'Area' + | 'GroupBar' + | 'RangeBar' + | 'GroupedColumn' + | 'Gauge' + | 'Line' + | 'Pie' + | 'Radar' + | 'Ring' + | 'StackedBar' + | 'StackColumn' + | 'StackArea' + | 'TinyArea' + | 'TinyColumn' + | 'TinyLine' + | 'Progress' + | 'RingProgress' + | 'DualAxes'; + +export interface TooltipScrollProps { + maxHeight: string; +} + +export type TooltipScroll = boolean | TooltipScrollProps; + +export interface ChartProps { + type?: ChartType; + autoFit?: boolean; + data?: any[]; + percent?: number; + title?: React.ReactNode; + description?: React.ReactNode; + height?: number; + xField?: string; + yField?: string; + colorField?: string; + seriesField?: string; + animation?: boolean; + meta?: Record< + string, + { + alias?: string; + formatter?: (value: any) => any; + } + >; + xAxis?: any; + yAxis?: any; + legend?: any; + tooltip?: any; + interactions?: { + type: string; + }[]; + // 图表的 tooltip 是否可进入且可滚动,常用于 tooltip 数过多、需要滚动查看的场景 + tooltipScroll?: TooltipScroll; + style?: React.CSSProperties; + className?: string; +} + +const Chart: React.FC = ({ + type = 'Line', + data, + xField, + xAxis, + yAxis, + tooltip, + tooltipScroll, + ...restProps +}) => { + let newData = data; + + if (type === 'Line' && (xAxis?.type === 'time' || xAxis?.type === 'timeCat')) { + newData = data?.sort((a, b) => sortByMoment(a, b, xField)); + } else if (type === 'DualAxes' && (xAxis?.type === 'time' || xAxis?.type === 'timeCat')) { + newData = [ + (data && data[0] && data[0].sort((a, b) => sortByMoment(a, b, xField))) || [], + (data && data[1] && data[1].sort((a, b) => sortByMoment(a, b, xField))) || [], + ]; + } + const config = { + data: newData, + padding: 'auto', + autoFit: true, + xField, + xAxis: { + title: false, + ...(xAxis?.type === 'time' + ? { + nice: false, + } + : {}), + ...xAxis, + }, + yAxis: { + title: false, + ...yAxis, + }, + tooltip: { + ...(tooltipScroll + ? { + follow: true, + shared: true, + enterable: true, + // 允许鼠标滑入 tooltip 会导致框选很难选中区间,因此加大鼠标和 tooltip 之间的间距,以缓解该问题 + offset: 40, + domStyles: { + 'g2-tooltip': { + maxHeight: '164px', + overflow: 'auto', + ...(isObject(tooltipScroll) ? (tooltipScroll as TooltipScrollProps) : {}), + }, + }, + } + : {}), + ...tooltip, + }, + ...restProps, + }; + const ChartComp = OBCharts[type] || Charts[type]; + return ; +}; + +export default Chart; diff --git a/frontend/src/component/CheckboxPopover/index.less b/frontend/src/component/CheckboxPopover/index.less new file mode 100644 index 00000000..7d9b8c46 --- /dev/null +++ b/frontend/src/component/CheckboxPopover/index.less @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.container { + :global { + .ant-popover-inner-content { + padding: 0; + } + } +} diff --git a/frontend/src/component/CheckboxPopover/index.style.ts b/frontend/src/component/CheckboxPopover/index.style.ts new file mode 100644 index 00000000..94fc30b6 --- /dev/null +++ b/frontend/src/component/CheckboxPopover/index.style.ts @@ -0,0 +1,10 @@ +import { createStyles } from 'antd-style'; + +const useStyles = createStyles(() => { + return { + container: { + '.ant-popover-inner-content': { padding: '0' }, + }, + }; +}); +export default useStyles; diff --git a/frontend/src/component/CheckboxPopover/index.tsx b/frontend/src/component/CheckboxPopover/index.tsx new file mode 100644 index 00000000..1f0ae89d --- /dev/null +++ b/frontend/src/component/CheckboxPopover/index.tsx @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { formatMessage } from '@/util/intl'; +import React from 'react'; +import { Typography, Row, Col, Divider, Checkbox, Space, Popover, theme } from '@oceanbase/design'; +import type { PopoverProps } from '@oceanbase/design/es/popover'; +import type { CheckboxOptionType } from '@oceanbase/design/es/checkbox'; +import { groupBy, some, uniq } from 'lodash'; +import { isNullValue } from '@oceanbase/util'; +import { InfoCircleFilled } from '@oceanbase/icons'; +import ContentWithQuestion from '@/component/ContentWithQuestion'; +import useStyles from './index.style'; + +export interface OptionType extends CheckboxOptionType { + description?: string; + span?: number; + group?: string; +} + +export type OptionValue = string | number | boolean; + +export interface CheckboxPopoverProps extends PopoverProps { + options?: OptionType[]; + defaultValue: OptionValue[]; + value: OptionValue[]; + onChange: (value: OptionValue[]) => void; + /* 最多可选中的对象数,为空时不限制选中数 */ + maxSelectCount?: number; + maxSelectCountLabel?: string; + children: React.ReactNode; +} + +const CheckboxPopover = ({ + title, + options, + defaultValue, + value, + onChange, + maxSelectCount, + maxSelectCountLabel, + children, + overlayClassName, + ...restProps +}: CheckboxPopoverProps) => { + const { styles } = useStyles(); + const { token } = theme.useToken(); + + // 分组列表 + const groupList = uniq(options?.map(item => item.group)); + const groupByData = groupBy(options, 'group'); + // 分组选项存在多于 3 个的情况下,设置最大宽度,否则设置最小宽度 + const width = some(Object.keys(groupByData), key => groupByData[key].length > 3) ? 608 : 480; + return ( + + + + + {title} + + {!isNullValue(maxSelectCount) && ( + + + + {maxSelectCountLabel || + formatMessage( + { + id: 'ocp-express.component.CheckboxPopover.YouCanSelectUpTo', + defaultMessage: '最多可选择 {maxSelectCount} 个对象', + }, + { maxSelectCount: maxSelectCount } + )} + + + )} + + { + onChange(defaultValue); + }} + > + {formatMessage({ + id: 'ocp-express.component.CheckboxPopover.Reset', + defaultMessage: '重置', + })} + + + + { + onChange(newValue); + }} + style={{ + width: '100%', + padding: 16, + maxHeight: 400, + overflow: 'auto', + }} + > + {groupList.map((group, index) => { + return ( + <> + {group && ( +

{group}

+ )} + + + {options + ?.filter(item => !group || item.group === group) + ?.map(item => { + return ( + + = (maxSelectCount || 0) + : false + } + > + + + + ); + })} + + + ); + })} +
+ + } + > + {children} +
+ ); +}; + +export default CheckboxPopover; diff --git a/frontend/src/component/ClusterLabel.tsx b/frontend/src/component/ClusterLabel.tsx new file mode 100644 index 00000000..0b6db55b --- /dev/null +++ b/frontend/src/component/ClusterLabel.tsx @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; + +export interface ClusterLabelProps { + cluster?: API.ClusterInfo | API.Cluster | API.BasicClusterInfo; + tenant?: API.TenantInfo | API.Tenant; +} + +const ClusterLabel: React.FC = ({ tenant, cluster }) => { + // 优先级: cluster > tenant + const clusterName = cluster?.name || tenant?.clusterName; + return {clusterName}; +}; + +export default ClusterLabel; diff --git a/frontend/src/component/CollapseSwitcher.tsx b/frontend/src/component/CollapseSwitcher.tsx new file mode 100644 index 00000000..34343e19 --- /dev/null +++ b/frontend/src/component/CollapseSwitcher.tsx @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { formatMessage } from '@/util/intl'; +import React from 'react'; +import { DownOutlined, UpOutlined } from '@oceanbase/icons'; +import { noop } from 'lodash'; + +interface CollapseSwictherProps { + textList?: React.ReactElement[]; + collapsed: boolean; + onCollapse: (collapsed: boolean) => void; +} + +class CollapseSwicther extends React.PureComponent { + public state = {}; + + public render() { + const { + textList = [ + formatMessage({ + id: 'ocp-express.component-legacy.common.CollapseSwitcher.Expand', + defaultMessage: '展开', + }), + formatMessage({ + id: 'ocp-express.component-legacy.common.CollapseSwitcher.PutAway', + defaultMessage: '收起', + }), + ], + collapsed = false, // 默认展开 + onCollapse = noop, + } = this.props; + return ( + { + onCollapse(!collapsed); + }} + > + {collapsed ? textList[0] : textList[1]} + {collapsed ? : } + + ); + } +} + +export default CollapseSwicther; diff --git a/frontend/src/component/ComparisonMetricChart/Item.tsx b/frontend/src/component/ComparisonMetricChart/Item.tsx new file mode 100644 index 00000000..250ef56b --- /dev/null +++ b/frontend/src/component/ComparisonMetricChart/Item.tsx @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import moment from 'moment'; +import { DATE_TIME_FORMAT_DISPLAY, TIME_FORMAT_WITHOUT_SECOND } from '@/constant/datetime'; +import { formatValueForChart } from '@/util'; +import type { ChartProps } from '@/component/Chart'; +import type { TooltipScroll } from '@/component/Chart'; +import Chart from '@/component/Chart'; +import { useComparisonMetrichartDataList } from '@/hook/sqlDiagnosis'; +import { Card } from '@oceanbase/design'; + +export interface MetricGroupWithChartConfig extends API.MetricGroup { + chartConfig?: ChartProps; + drilldownable?: string; + tooltipScroll?: TooltipScroll; + scope?: Global.MonitorScope; + metrics: any[]; + name: string; + description: string; +} + +export interface CommonProps { + // 监控卡片的顺序索引,用于判断是否为第一个卡片 + index?: number; + /* 一级下钻维度,为空时不展示下钻入口,只支持集群、租户和主机 */ + drilldownScope?: 'ob_cluster_id' | 'tenant_name' | 'svr_ip'; + metricClass?: API.MetricClass; + chartConfig?: ChartProps; + scope?: Global.MonitorScope; + app?: Global.MonitorApp; + clusterName?: string; + tenantName?: string; + isRealtime?: boolean; + interval?: number; + baselineStartTime?: string; + baselineEndTime?: string; + startTime?: string; + endTime?: string; + zoneName?: string; + serverIp?: string; + mount_point?: string; + mount_label?: string; + task_type?: string; + process?: string; + device?: string; + cpu?: string; + zoneNameList?: string[]; + serverList?: MonitorServer[]; + tenantList?: API.TenantInfo[]; + className?: string; + style?: React.CSSProperties; +} + +export interface ComparisonMetricChartItemProps extends CommonProps { + metricGroup: MetricGroupWithChartConfig; +} +const Item: React.FC = ({ + metricGroup, + // 默认获取 OB 的监控数据 + app = 'OB', + clusterName, + // 租户 + tenantName, + baselineStartTime, + baselineEndTime, + startTime, + endTime, + zoneNameList, + serverList, +}) => { + const { chartDataList = [] } = useComparisonMetrichartDataList({ + app, + metricGroup, + clusterName, + tenantName, + zoneNameList, + serverList, + interval: 60, + baselineStartTime, + baselineEndTime, + startTime, + endTime, + }); + + const getConfig = (chartData: any[]) => { + return { + height: 300, + type: 'Line', + xField: 'timestamp', + yField: 'value', + seriesField: 'metric', + animation: false, + meta: { + timestamp: { + formatter: (value: moment.MomentInput) => { + return moment(value).format(DATE_TIME_FORMAT_DISPLAY); + }, + }, + value: { + formatter: (value: number) => { + return formatValueForChart(chartData, value, chartData?.[0]?.unit as string); + }, + }, + }, + xAxis: { + type: 'time', + tickCount: 4, + label: { + formatter: (value: moment.MomentInput) => { + return moment(value, DATE_TIME_FORMAT_DISPLAY).format(TIME_FORMAT_WITHOUT_SECOND); + }, + }, + }, + yAxis: { + nice: true, + tickCount: 3, + }, + tooltip: { + fields: ['value', 'timestamp', 'ComparisonTimestamp', 'metric'], + showTitle: false, + formatter: (datum: Global.ChartData) => { + const { ComparisonTimestamp, timestamp } = datum; + let value = formatValueForChart(chartData, datum.value, chartData?.[0]?.unit as string); + value += ` (${moment(ComparisonTimestamp || timestamp).format( + DATE_TIME_FORMAT_DISPLAY + )})`; + return { name: datum.metric, value }; + }, + }, + }; + }; + + const { metrics = [] } = metricGroup || {}; + + return ( + + {metrics.map(metric => { + const chartData = + chartDataList.find(item => { + return item?.[0]?.key === metric.key; + }) || []; + + const config = getConfig(chartData); + + return ( + +
{metric.name}
+ +
+ ); + })} +
+ ); +}; + +export default Item; diff --git a/frontend/src/component/ComparisonMetricChart/index.tsx b/frontend/src/component/ComparisonMetricChart/index.tsx new file mode 100644 index 00000000..3266be82 --- /dev/null +++ b/frontend/src/component/ComparisonMetricChart/index.tsx @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { Card } from '@oceanbase/design'; +import ContentWithQuestion from '@/component/ContentWithQuestion'; +import type { CommonProps, MetricGroupWithChartConfig } from './Item'; +import Item from './Item'; + +export interface ComparisonMetricChartProps extends CommonProps { + metricGroupList: MetricGroupWithChartConfig[]; + cardStyle?: React.CSSProperties; + titleStyle?: React.CSSProperties; +} + +const ComparisonMetricChart: React.FC = ({ + metricGroupList, + titleStyle, + ...restProps +}) => { + return ( +
+ {metricGroupList.map((item, index) => { + const title = ( + + {/* 用第一个指标的单位替代指标组的单位作展示 */} + {`${item?.description}`} +
+ ), + } + } + /> + ); + + return ( + + + + ); + })} +
+ ); +}; + +export default ComparisonMetricChart; diff --git a/frontend/src/component/ContentWithIcon/index.less b/frontend/src/component/ContentWithIcon/index.less new file mode 100644 index 00000000..4a4b4108 --- /dev/null +++ b/frontend/src/component/ContentWithIcon/index.less @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.item { + display: inline-flex; + align-items: center; + + .prefix { + margin-right: 8px; + :global { + .anticon { + vertical-align: middle; + } + } + } + + .affix { + margin-left: 8px; + :global { + .anticon { + vertical-align: middle; + } + } + } + + .pointable { + cursor: pointer; + } +} diff --git a/frontend/src/component/ContentWithIcon/index.style.ts b/frontend/src/component/ContentWithIcon/index.style.ts new file mode 100644 index 00000000..37a125e3 --- /dev/null +++ b/frontend/src/component/ContentWithIcon/index.style.ts @@ -0,0 +1,23 @@ +import { createStyles } from 'antd-style'; + +const useStyles = createStyles(() => { + return { + item: { + display: 'inline-flex', + alignItems: 'center', + }, + prefix: { + marginRight: '8px', + }, + anticon: { + verticalAlign: 'middle', + }, + affix: { + marginLeft: '8px', + }, + pointable: { + cursor: 'pointer', + }, + }; +}); +export default useStyles; diff --git a/frontend/src/component/ContentWithIcon/index.tsx b/frontend/src/component/ContentWithIcon/index.tsx new file mode 100644 index 00000000..af93b23c --- /dev/null +++ b/frontend/src/component/ContentWithIcon/index.tsx @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Badge, Tooltip } from '@oceanbase/design'; +import React, { isValidElement } from 'react'; +import classNames from 'classnames'; +import Icon from '@oceanbase/icons'; +import type { IconComponentProps } from '@oceanbase/icons/lib/components/Icon'; +import type { BadgeProps } from '@oceanbase/design/es/badge'; +import type { TooltipProps } from '@oceanbase/design/es/tooltip'; +import useStyles from './index.style'; + +interface IconConfig extends IconComponentProps { + badge?: BadgeProps; + tooltip?: TooltipProps; + pointable?: boolean; +} + +type IconPosition = 'prefix' | 'affix'; + +export interface ContentWithIconProps { + content?: React.ReactNode; + prefixIcon?: IconConfig | React.ReactNode; + affixIcon?: IconConfig | React.ReactNode; + onClick?: (e: React.SyntheticEvent) => void; + style?: React.CSSProperties; + className?: string; +} + +const ContentWithIcon: React.FC = ({ + content, + prefixIcon, + affixIcon, + className, + ...restProps +}) => { + const { styles } = useStyles(); + return ( + + {prefixIcon && + (isValidElement(prefixIcon) ? ( + {prefixIcon} + ) : ( + getIcon('prefix', prefixIcon) + ))} + + {content} + {affixIcon && + (isValidElement(affixIcon) ? ( + {affixIcon} + ) : ( + getIcon('affix', affixIcon) + ))} + + ); +}; + +function getIcon(position: IconPosition, config: IconConfig) { + const { component, badge, tooltip, pointable = false, ...restProps } = config; + const { styles } = useStyles(); + return ( + config && ( + + {badge ? ( + + + + ) : ( + + + + )} + + ) + ); +} + +export default ContentWithIcon; diff --git a/frontend/src/component/ContentWithInfo/index.less b/frontend/src/component/ContentWithInfo/index.less new file mode 100644 index 00000000..7055a27b --- /dev/null +++ b/frontend/src/component/ContentWithInfo/index.less @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import '~@oceanbase/design/es/theme/index.less'; + +.container { + font-weight: normal; + font-size: 12px; + + .icon { + color: @colorPrimary !important; + } + + .content { + color: rgba(0, 0, 0, 0.45); + // 可能位于 Card title,避免字体加粗,需要设置字体类型 + font-family: PingFangSC-Regular; + } +} diff --git a/frontend/src/component/ContentWithInfo/index.style.ts b/frontend/src/component/ContentWithInfo/index.style.ts new file mode 100644 index 00000000..230f0f78 --- /dev/null +++ b/frontend/src/component/ContentWithInfo/index.style.ts @@ -0,0 +1,18 @@ +import { createStyles } from "antd-style"; + +const useStyles = createStyles(({ token }) => { + return { + container: { + fontWeight: "normal", + fontSize: "12px", + }, + icon: { + color: token.colorPrimary, + }, + content: { + color: "rgba(0, 0, 0, 0.45)", + }, + }; +}); + +export default useStyles; diff --git a/frontend/src/component/ContentWithInfo/index.tsx b/frontend/src/component/ContentWithInfo/index.tsx new file mode 100644 index 00000000..5dc2fee3 --- /dev/null +++ b/frontend/src/component/ContentWithInfo/index.tsx @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import type { SpaceProps } from '@oceanbase/design'; +import { Space } from '@oceanbase/design'; +import { InfoCircleFilled } from '@oceanbase/icons'; +import useStyles from './index.style'; + +export interface ContentWithInfoProps extends SpaceProps { + content: React.ReactNode; + className?: string; + style?: React.CSSProperties; +} + +const ContentWithInfo: React.FC = ({ content, className, ...restProps }) => { + const { styles } = useStyles(); + return ( + + + {content} + + ); +}; + +export default ContentWithInfo; diff --git a/frontend/src/component/ContentWithQuestion/index.tsx b/frontend/src/component/ContentWithQuestion/index.tsx new file mode 100644 index 00000000..bf8dddd4 --- /dev/null +++ b/frontend/src/component/ContentWithQuestion/index.tsx @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { theme } from '@oceanbase/design'; +import type { TooltipProps } from '@oceanbase/design/es/tooltip'; +import { QuestionCircleOutlined } from '@oceanbase/icons'; +import ContentWithIcon from '@/component/ContentWithIcon'; + +export interface ContentWithQuestionProps { + content?: React.ReactNode; + /* tooltip 为空,则不展示 quertion 图标和 Tooltip */ + tooltip?: TooltipProps; + /* 是否作为 label */ + inLabel?: boolean; + onClick?: (e: React.SyntheticEvent) => void; + style?: React.CSSProperties; + className?: string; +} + +const ContentWithQuestion: React.FC = ({ + content, + tooltip, + inLabel, + ...restProps +}) => { + const { token } = theme.useToken(); + + return ( + + ); +}; + +export default ContentWithQuestion; diff --git a/frontend/src/component/ContentWithReload.tsx b/frontend/src/component/ContentWithReload.tsx new file mode 100644 index 00000000..fed895a7 --- /dev/null +++ b/frontend/src/component/ContentWithReload.tsx @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { formatMessage } from '@/util/intl'; +import React from 'react'; +import { SyncOutlined } from '@oceanbase/icons'; +import ContentWithIcon from '@/component/ContentWithIcon'; + +export interface ContentWithReloadProps { + content?: React.ReactNode; + spin?: boolean; + onClick?: (e: React.UIEvent) => void; + style?: React.CSSProperties; + className?: string; +} + +const ContentWithReload: React.FC = ({ + content, + spin = false, + onClick, + ...restProps +}) => { + return ( + + ); +}; + +export default ContentWithReload; diff --git a/frontend/src/component/DatabasePrivilegeTransfer/PrivilegesCheckbox.tsx b/frontend/src/component/DatabasePrivilegeTransfer/PrivilegesCheckbox.tsx new file mode 100644 index 00000000..f5e6e738 --- /dev/null +++ b/frontend/src/component/DatabasePrivilegeTransfer/PrivilegesCheckbox.tsx @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { formatMessage } from '@/util/intl'; +import React from 'react'; +import { Checkbox, Button } from '@oceanbase/design'; +import { DeleteOutlined } from '@oceanbase/icons'; +import { DATABASE_PRIVILEGE_LIST } from '@/constant/tenant'; +import styles from './index.less'; + +export interface PrivilegesCheckboxProps { + dbPrivilegeParam: API.DbPrivilege; + insideDb: boolean; + deleteFn: (value: string) => void; + updateDbPrivilege: (value: API.DbPrivilege) => void; +} + +interface PrivilegesCheckboxState { + checkedList: API.DbPrivType[]; + indeterminate: boolean; + checkAll: boolean; +} + +export default class PrivilegesCheckbox extends React.PureComponent< + PrivilegesCheckboxProps, + PrivilegesCheckboxState +> { + constructor(props: PrivilegesCheckboxProps) { + super(props); + const privilegesLength = props?.dbPrivilegeParam?.privileges?.length; + const isCheckAll = + privilegesLength === (props.insideDb ? ['SELECT'] : DATABASE_PRIVILEGE_LIST).length; + this.state = { + checkAll: isCheckAll, + indeterminate: privilegesLength !== 0 && !isCheckAll, + checkedList: props?.dbPrivilegeParam?.privileges, + }; + } + + onCheckAllChange = (e, dbName: string) => { + const { insideDb, updateDbPrivilege } = this.props; + const privilegeList = insideDb ? (['SELECT'] as API.DbPrivType[]) : DATABASE_PRIVILEGE_LIST; + this.setState({ + checkedList: e.target.checked ? privilegeList : [], + indeterminate: false, + checkAll: e.target.checked, + }); + + updateDbPrivilege({ + dbName, + // 由于 updateDbPrivilege 内部会对 privileges 做 splice 处理,因此需要解构赋值,避免影响原有的数组值 + // TODO: 待去掉 updateDbPrivilege 中的 splice 逻辑 + privileges: e.target.checked ? [...privilegeList] : [], + }); + }; + + collectCheckedParam = (checkedList: API.DbPrivType[], dbName: string) => { + const { insideDb, updateDbPrivilege } = this.props; + const privilegeList = insideDb ? (['SELECT'] as API.DbPrivType[]) : DATABASE_PRIVILEGE_LIST; + this.setState({ + checkedList, + indeterminate: !!checkedList.length && checkedList.length < privilegeList.length, + checkAll: checkedList.length === privilegeList.length, + }); + + updateDbPrivilege({ + dbName, + // 由于 updateDbPrivilege 内部会对 privileges 做 splice 处理,因此需要解构赋值,避免影响原有的数组值 + // TODO: 待去掉 updateDbPrivilege 中的 splice 逻辑 + privileges: [...checkedList], + }); + }; + + render() { + const { dbPrivilegeParam, insideDb, deleteFn } = this.props; + const { checkedList, indeterminate, checkAll } = this.state; + return ( +
+
+ {dbPrivilegeParam.dbName || '-'} +
+ this.onCheckAllChange(e, dbPrivilegeParam?.dbName)} + checked={checkAll} + > + {formatMessage({ + id: 'ocp-express.component.DatabasePrivilegeTransfer.PrivilegesCheckbox.All', + defaultMessage: '全部', + })} + + +
+
+ + this.collectCheckedParam(value as API.DbPrivType[], dbPrivilegeParam.dbName) + } + > + {(insideDb ? ['SELECT'] : DATABASE_PRIVILEGE_LIST).map((node) => ( + + {node} + + ))} + +
+ ); + } +} diff --git a/frontend/src/component/DatabasePrivilegeTransfer/index.less b/frontend/src/component/DatabasePrivilegeTransfer/index.less new file mode 100644 index 00000000..0b7df5fa --- /dev/null +++ b/frontend/src/component/DatabasePrivilegeTransfer/index.less @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import '~@oceanbase/design/es/theme/index.less'; + +.container { + display: flex; + + :global { + .ant-card-body { + .ant-empty { + margin-top: 120px; + } + } + } + + .db { + flex: 0.22; + + .ant-card-head { + background: #fff; + } + } + + .transferWrapper { + display: flex; + flex: 0.05; + align-items: center; + justify-content: center; + + .transfer { + display: flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + background-color: #f5f8fe; + border: 1px solid transparent; + border-color: #cdd5e4; + border-radius: 4px; + } + + .active { + color: #fff; + background-color: @colorPrimary; + border-color: @colorPrimary; + cursor: pointer; + } + + .disabled { + color: rgba(0, 0, 0, 0.25); + background-color: #f5f5f5; + border-color: #d9d9d9; + cursor: not-allowed; + } + } + + .privilegedListContainer { + flex: 0.73; + + .ant-card-head { + background: #fff; + } + } + + .description { + span { + margin-right: 8px; + } + + // color: #8592ad; + font-size: 12px; + } + + .privilegedList { + height: 340px; + overflow: auto; + + .privilegedItem { + margin-top: 8px; + padding: 10px; + padding-top: 0; + // background: #fafafa; + + .privilegedTitle { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 4px; + padding: 5px 0; + border-bottom: 1px solid #f0f0f0; + + .delete { + // background: #fafafa; + border: none; + box-shadow: none; + + .deleteIcon { + // color: rgba(0, 0, 0, 0.45); + } + + &:hover { + .deleteIcon { + color: @colorPrimary !important; + } + } + } + } + + .privilegeCheckbox { + width: 151px; + margin: 0; + line-height: 26px; + } + } + } +} \ No newline at end of file diff --git a/frontend/src/component/DatabasePrivilegeTransfer/index.style.ts b/frontend/src/component/DatabasePrivilegeTransfer/index.style.ts new file mode 100644 index 00000000..f42f0388 --- /dev/null +++ b/frontend/src/component/DatabasePrivilegeTransfer/index.style.ts @@ -0,0 +1,89 @@ +import { createStyles } from "antd-style"; + +const useStyles = createStyles(({ token }) => { + return { + container: { + display: "flex", + ".ant-card-body": { + ".ant-empty": { + marginTop: "120px", + }, + }, + }, + db: { + flex: "0.22", + ".ant-card-head": { background: "#fff" }, + }, + transferWrapper: { + display: "flex", + flex: "0.05", + alignItems: "center", + justifyContent: "center", + }, + transfer: { + display: "flex", + alignItems: "center", + justifyContent: "center", + width: "24px", + height: "24px", + backgroundColor: "#f5f8fe", + border: "1px solid transparent", + borderColor: "#cdd5e4", + borderRadius: "4px", + }, + active: { + color: "#fff", + backgroundColor: token.colorPrimary, + borderColor: token.colorPrimary, + cursor: "pointer", + }, + disabled: { + color: "rgba(0, 0, 0, 0.25)", + backgroundColor: "#f5f5f5", + borderColor: "#d9d9d9", + cursor: "not-allowed", + }, + privilegedListContainer: { + flex: "0.73", + ".ant-card-head": { background: "#fff" }, + }, + description: { + span: { marginRight: "8px" }, + color: "#8592ad", + fontSize: "12px", + }, + privilegedList: { + height: "340px", + overflow: "auto", + }, + privilegedItem: { + marginTop: "8px", + padding: "10px", + paddingTop: "0", + background: "#fafafa", + }, + privilegedTitle: { + display: "flex", + alignItems: "center", + justifyContent: "space-between", + marginBottom: "4px", + padding: "5px 0", + borderBottom: "1px solid #f0f0f0", + }, + delete: { + background: "#fafafa", + border: "none", + boxShadow: "none", + }, + deleteIcon: { + color: token.colorPrimary, + }, + privilegeCheckbox: { + width: "151px", + margin: "0", + lineHeight: "26px", + }, + }; +}); + +export default useStyles; diff --git a/frontend/src/component/DatabasePrivilegeTransfer/index.tsx b/frontend/src/component/DatabasePrivilegeTransfer/index.tsx new file mode 100644 index 00000000..1551e126 --- /dev/null +++ b/frontend/src/component/DatabasePrivilegeTransfer/index.tsx @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { formatMessage } from '@/util/intl'; +import React from 'react'; +import { Modal, Card, Checkbox, Col, Row, Spin, Button, Empty } from '@oceanbase/design'; +import { RightOutlined } from '@oceanbase/icons'; +import classNames from 'classnames'; +import MyInput from '@/component/MyInput'; +import { differenceBy, findIndex, includes } from 'lodash'; +import { FORBID_OPERATION_DBLIST } from '@/constant/tenant'; +import PrivilegesCheckbox from './PrivilegesCheckbox'; +import styles from './index.less'; + +const { confirm } = Modal; + +export interface DatabasePrivilegeTransferProps { + dbUserList?: API.DbPrivilege[]; + dbPrivilegedList?: API.DbPrivilege[]; + loading: boolean; + onChange?: (value: API.DbPrivilege[]) => void; +} + +interface DatabasePrivilegeTransferState { + checkAll: boolean; + checkedList: API.Database[]; + indeterminate: boolean; + searchLeftKey: string; + searchRightKey: string; + privilegedList: API.DbPrivilege[]; + unPrivilegedList: API.Database[]; + dbPrivilegeData: API.DbPrivilege[]; +} + +class DatabasePrivilegeTransfer extends React.PureComponent< + DatabasePrivilegeTransferProps, + DatabasePrivilegeTransferState +> { + constructor(props: DatabasePrivilegeTransferProps) { + super(props); + this.state = { + checkAll: false, + checkedList: [], + indeterminate: false, + searchLeftKey: '', + searchRightKey: '', + privilegedList: props.dbPrivilegedList || [], + unPrivilegedList: props.dbUserList || [], + dbPrivilegeData: props.dbPrivilegedList || [], + }; + } + + // 全选/不选 DB + handleCheckAllChange = (e: any) => { + const { unPrivilegedList } = this.state; + this.setState({ + checkedList: e.target.checked ? unPrivilegedList : [], + checkAll: e.target.checked, + indeterminate: false, + }); + }; + + handleCheckboxGroupChange = (checkedData: API.DbPrivilege[]) => { + const { unPrivilegedList } = this.state; + this.setState({ + checkedList: checkedData, + checkAll: checkedData.length === unPrivilegedList.length, + indeterminate: !!checkedData.length && checkedData.length < unPrivilegedList.length, + }); + }; + + handleTransfer = () => { + const { checkedList, privilegedList, unPrivilegedList } = this.state; + if (checkedList.length > 0) { + const checkedDbList = checkedList.map(item => { + return { + dbName: item.dbName, + privileges: [], + }; + }); + this.setState({ + checkedList: [], + checkAll: false, + indeterminate: false, + privilegedList: [...privilegedList, ...checkedDbList], + unPrivilegedList: differenceBy(unPrivilegedList, checkedList, 'dbName'), + }); + } + }; + + deleteAllAuthed = () => { + const { dbUserList, dbPrivilegedList, onChange } = this.props; + const removeList: API.DbPrivilege[] = [...(dbUserList || []), ...(dbPrivilegedList || [])]; + confirm({ + title: formatMessage({ + id: 'ocp-express.component.DatabasePrivilegeTransfer.AreYouSureYouWant', + defaultMessage: '确定要移除全部已选择对象吗?', + }), + okText: formatMessage({ + id: 'ocp-express.component.DatabasePrivilegeTransfer.Determine', + defaultMessage: '确定', + }), + cancelText: formatMessage({ + id: 'ocp-express.component.DatabasePrivilegeTransfer.Cancel', + defaultMessage: '取消', + }), + onOk: () => { + this.setState({ + unPrivilegedList: removeList, + dbPrivilegeData: [], + privilegedList: [], + }); + + if (onChange) { + onChange([]); + } + }, + }); + }; + + // 左侧搜索 + setUnPrivilegedList = (key: string) => { + this.setState({ + searchLeftKey: key, + }); + }; + + // 右侧搜索 + searchPrivilegedList = (key: string) => { + this.setState({ + searchRightKey: key, + }); + }; + + // 删除一项 DB 权限 + handleDeleteAuth = (dbName: string) => { + const { dbPrivilegedList, dbUserList, onChange } = this.props; + const { checkedList, unPrivilegedList, privilegedList, dbPrivilegeData } = this.state; + const privilegedListFilter: API.DbPrivilege[] = privilegedList.filter( + item => item.dbName !== dbName + ); + + // 收集到当前授权的数据库 + const dbPrivilegesData: API.DbPrivilege[] = dbPrivilegeData?.filter( + item => item.dbName !== dbName + ); + + const index = findIndex(dbPrivilegedList, o => o.dbName === dbName); + const count = findIndex(dbUserList, o => o.dbName === dbName); + const deleteDbPrivilegeParam = []; + // 匹配查找到移除的权限,整理后放入待添加的数据库列表 + if (index !== -1) { + deleteDbPrivilegeParam.push(dbPrivilegedList[index]); + } else if (count !== -1) { + deleteDbPrivilegeParam.push(dbUserList[count]); + } else { + deleteDbPrivilegeParam.push({ + dbName, + privileges: [], + }); + } + this.setState({ + checkAll: false, + indeterminate: !!checkedList?.length, + // 将被删除的放回未授权数组 + unPrivilegedList: [...unPrivilegedList, ...deleteDbPrivilegeParam], + privilegedList: privilegedListFilter, + dbPrivilegeData: dbPrivilegesData, + }); + + if (onChange) { + onChange( + dbPrivilegeData?.map(item => ({ + dbName: item?.dbName, + privileges: item.dbName === dbName ? [] : item.privileges, + })) + ); + } + }; + + public updateDbPrivilege = (dbPrivilege: API.DbPrivilege) => { + const { dbPrivilegeData, privilegedList } = this.state; + const privilegedIndex = findIndex(privilegedList, o => o.dbName === dbPrivilege.dbName); + if (privilegedIndex !== -1) { + this.setState({ + privilegedList: privilegedList?.map(item => ({ + dbName: item?.dbName, + privileges: + item?.dbName === dbPrivilege?.dbName ? dbPrivilege.privileges : item.privileges, + })), + }); + } else { + this.setState({ + privilegedList, + }); + } + // 收集到当前授权的数据库 + const dbPrivilegeIndex = findIndex(dbPrivilegeData, o => o.dbName === dbPrivilege.dbName); + if (dbPrivilegeIndex !== -1) { + const dbPrivileges = dbPrivilegeData?.map(item => ({ + dbName: item?.dbName, + privileges: item?.dbName === dbPrivilege?.dbName ? dbPrivilege.privileges : item.privileges, + })); + + this.setState({ + dbPrivilegeData: dbPrivileges, + }); + + this.props.onChange(dbPrivileges); + } else { + this.setState({ + dbPrivilegeData: [...dbPrivilegeData, dbPrivilege], + privilegedList, + }); + + this.props.onChange([...dbPrivilegeData, dbPrivilege]); + } + }; + + public render() { + const { loading } = this.props; + const { + searchLeftKey, + searchRightKey, + checkAll, + indeterminate, + unPrivilegedList, + checkedList, + privilegedList, + } = this.state; + + return ( +
+ + + {formatMessage({ + id: 'ocp-express.component.DatabasePrivilegeTransfer.Unauthorized', + defaultMessage: '未授权', + })} + + + {unPrivilegedList.length} + {formatMessage({ + id: 'ocp-express.component.DatabasePrivilegeTransfer.Item', + defaultMessage: '项', + })} + + + } + > + + {/* Search 组件需要用 div 组件包裹,因为 Search 组件是 inline-block,当授权所有数据库权限时,Search 会滑落到卡片底部,需要包裹一层 block 组件 */} +
+ this.setUnPrivilegedList(value)} + placeholder={formatMessage({ + id: 'ocp-express.component.DatabasePrivilegeTransfer.Enter', + defaultMessage: '请输入', + })} + /> +
+ + + {unPrivilegedList + ?.filter(o => includes(o.dbName, searchLeftKey)) + ?.map(item => { + if (item.dbName !== 'information_schema') { + return ( + + + {item.dbName} + + + ); + } + })} + + +
+
+ + + + + + + + {formatMessage({ + id: 'ocp-express.component.DatabasePrivilegeTransfer.Authorized', + defaultMessage: '已授权', + })} + + + {privilegedList.length} + {formatMessage({ + id: 'ocp-express.component.DatabasePrivilegeTransfer.Item', + defaultMessage: '项', + })} + + {privilegedList.length !== 0 && ( + + )} + + } + > + {privilegedList.length === 0 ? ( + + ) : ( + <> + this.searchPrivilegedList(value)} + placeholder={formatMessage({ + id: 'ocp-express.component.DatabasePrivilegeTransfer.Enter', + defaultMessage: '请输入', + })} + /> + +
+ {privilegedList + .filter(o => o.dbName.indexOf(searchRightKey) > -1) + ?.map(item => ( + + ))} +
+ + )} +
+
+ ); + } +} + +export default DatabasePrivilegeTransfer; diff --git a/frontend/src/component/DeleteUnitSpecModal.tsx b/frontend/src/component/DeleteUnitSpecModal.tsx new file mode 100644 index 00000000..fa61a3f2 --- /dev/null +++ b/frontend/src/component/DeleteUnitSpecModal.tsx @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { formatMessage } from '@/util/intl'; +import { connect } from 'umi'; +import { Descriptions, Modal } from '@oceanbase/design'; + +export interface DeleteUnitSpecModalProps { + dispatch: any; + visible: boolean; + unitSpec: API.UnitSpec; + onSuccess?: Function; + onCancel?: (e: any) => void; +} + +const DeleteUnitSpecModal: React.FC = ({ + dispatch, + visible, + unitSpec = {}, + onSuccess, + ...restProps +}) => { + const handleDelete = () => { + dispatch({ + type: 'tenant/deleteUnitSpec', + payload: { + specId: unitSpec.id, + }, + + name: unitSpec.name, + onSuccess: () => { + if (typeof onSuccess === 'function') { + onSuccess(); + } + }, + }); + }; + + return ( + + + + {unitSpec?.name} + + + {`${unitSpec?.minCpuCoreCount} ~ ${unitSpec?.maxCpuCoreCount}`} + + + {`${unitSpec?.minMemorySize || 0} ~ ${unitSpec?.maxMemorySize || 0} GB`} + + + + ); +}; + +export default connect(() => ({}))(DeleteUnitSpecModal); diff --git a/frontend/src/component/EditText.tsx b/frontend/src/component/EditText.tsx new file mode 100644 index 00000000..36d5f8bd --- /dev/null +++ b/frontend/src/component/EditText.tsx @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { useState, useEffect } from 'react'; +import { Input, Row, Col } from '@oceanbase/design'; +import { EditOutlined, CheckOutlined, CloseOutlined } from '@oceanbase/icons'; + +export interface EditTextProps { + address: string; + onOk: (address: string) => void; + style?: React.CSSProperties; +} + +const EditText: React.FC = ({ address: initAddress, onOk, ...restProps }) => { + const [edit, setEdit] = useState(false); + const [address, setAddress] = useState(initAddress as string); + const [oldAddress, setOldAddress] = useState(initAddress as string); + // 初始化默认值 + useEffect(() => { + if (initAddress) { + setAddress(initAddress); + setOldAddress(initAddress); + } + }, [initAddress]); + + return ( + + {edit ? ( + <> + + { + setAddress(value); + }} + /> + + + { + setAddress(oldAddress); + setEdit(false); + }} + /> + + + { + if (onOk) { + onOk(address); + } + }} + /> + + + ) : ( + <> + {address} + + + { + setEdit(true); + }} + /> + + + + )} + + ); +}; + +export default EditText; diff --git a/frontend/src/component/Empty/index.less b/frontend/src/component/Empty/index.less new file mode 100644 index 00000000..307106d4 --- /dev/null +++ b/frontend/src/component/Empty/index.less @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.page { + height: calc(100vh - 72px); +} +.empty { + .description { + margin: 24px 0; + color: #8592ad; + } + :global { + .ant-empty-image { + height: 102px; + } + .ant-empty-footer { + margin-top: 24px; + } + } +} +.small { + .title { + margin-bottom: 4px; + font-size: 14px; + } + .description { + margin: 20px 0; + font-size: 12px; + } + :global { + .ant-empty-image { + height: 72px; + } + } +} diff --git a/frontend/src/component/Empty/index.style.ts b/frontend/src/component/Empty/index.style.ts new file mode 100644 index 00000000..0d029beb --- /dev/null +++ b/frontend/src/component/Empty/index.style.ts @@ -0,0 +1,26 @@ +import { createStyles } from 'antd-style'; + +const useStyles = createStyles(() => { + return { + page: { + height: 'calc(100vh - 72px)', + }, + description: { + margin: '20px 0', + color: '#8592ad', + fontSize: '12px', + }, + empty: { + '.ant-empty-image': { height: '102px' }, + '.ant-empty-footer': { marginTop: '24px' }, + }, + title: { + marginBottom: '4px', + fontSize: '14px', + }, + small: { + '.ant-empty-image': { height: '72px' }, + }, + }; +}); +export default useStyles; diff --git a/frontend/src/component/Empty/index.tsx b/frontend/src/component/Empty/index.tsx new file mode 100644 index 00000000..8bb655bd --- /dev/null +++ b/frontend/src/component/Empty/index.tsx @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { Empty } from '@oceanbase/design'; +import type { EmptyProps as AntdEmptyProps } from '@oceanbase/design/es/empty'; +import { PageContainer } from '@oceanbase/ui'; +import PageCard from '@/component/PageCard'; +import useStyles from './index.style'; + +export interface EmptyProps extends AntdEmptyProps { + image?: React.ReactNode; + title?: React.ReactNode; + description?: React.ReactNode; + children?: React.ReactNode; + // 展示模式: 页面模式 | 组件模式 + mode?: 'page' | 'pageCard' | 'component'; + size?: 'default' | 'small'; +} + +export default ({ + image = '/assets/common/empty.svg', + title, + description, + children, + // 默认为页面模式 + mode = 'page', + size = 'default', + className, + style, + ...restProps +}: EmptyProps) => { + const { styles } = useStyles(); + const empty = ( + + {title &&

{title}

} + {description} + + } + {...restProps} + > + {children} +
+ ); + + const pageCard = ( + + {empty} + + ); + + if (mode === 'page') { + return {pageCard}; + } + if (mode === 'pageCard') { + return pageCard; + } + if (mode === 'component') { + return empty; + } + return {pageCard}; +}; diff --git a/frontend/src/component/ErrorBoundary.tsx b/frontend/src/component/ErrorBoundary.tsx new file mode 100644 index 00000000..fefd4d3d --- /dev/null +++ b/frontend/src/component/ErrorBoundary.tsx @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { formatMessage } from '@/util/intl'; +import { history } from 'umi'; +import React from 'react'; +import { Alert, Button } from '@oceanbase/design'; +import Empty from '@/component/Empty'; + +interface ErrorBoundaryProps { + message?: React.ReactNode; + description?: React.ReactNode; +} + +interface ErrorBoundaryState { + error?: Error | null; + info: { + componentStack?: string; + }; +} + +class ErrorBoundary extends React.Component { + state = { + error: undefined, + info: { + componentStack: '', + }, + }; + + componentDidCatch(error: Error | null, info: object) { + this.setState({ error, info }); + } + + render() { + const { message, description, children } = this.props; + const { error, info } = this.state; + const componentStack = info && info.componentStack ? info.componentStack : null; + const errorMessage = typeof message === 'undefined' ? (error || '').toString() : message; + const errorDescription = typeof description === 'undefined' ? componentStack : description; + if (error) { + return ( + + + {/* 展示报错详情,方便定位问题原因 */} + + + ); + } + return children; + } +} + +export default ErrorBoundary; diff --git a/frontend/src/component/FilterDropdown/index.less b/frontend/src/component/FilterDropdown/index.less new file mode 100644 index 00000000..f0d5870b --- /dev/null +++ b/frontend/src/component/FilterDropdown/index.less @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import '~@oceanbase/design/es/theme/index.less'; + +.filterIconFiltered { + color: @colorPrimary; + :global { + .anticon { + color: @colorPrimary !important; + } + } +} +.overlay { + width: 225px; + box-shadow: @boxShadowSecondary !important; + .searchWrapper { + padding: 8px; + .searchIcon { + opacity: 0.45; + } + } + ul { + margin-bottom: 0; + & > li { + display: flex; + align-items: center; + justify-content: space-between; + margin-right: 0; + padding: 7px 12px; + cursor: pointer; + .checkIcon { + margin-left: 8px; + visibility: hidden; + } + &:hover { + background-color: #e6f7ff; + .checkIcon { + color: rgba(0, 0, 0, 0.65); + visibility: visible; + } + } + .filterIconFiltered { + color: @colorPrimary; + :global { + .anticon { + color: @colorPrimary !important; + } + } + } + .overlay { + width: 225px; + .searchWrapper { + padding: 8px; + .searchIcon { + opacity: 0.45; + } + } + ul { + margin-bottom: 0; + & > li { + display: flex; + align-items: center; + justify-content: space-between; + margin-right: 0; + padding: 7px 12px; + cursor: pointer; + .checkIcon { + margin-left: 8px; + visibility: hidden; + } + &:hover { + background-color: #e6f7ff; + .checkIcon { + color: rgba(0, 0, 0, 0.65); + visibility: visible; + } + } + .filterIconFiltered { + color: @colorPrimary; + :global { + .anticon { + color: @colorPrimary !important; + } + } + } + .overlay { + width: 225px; + .searchWrapper { + padding: 8px; + .searchIcon { + opacity: 0.45; + } + } + ul { + margin-bottom: 0; + & > li { + display: flex; + align-items: center; + justify-content: space-between; + margin-right: 0; + padding: 7px 12px; + cursor: pointer; + .checkIcon { + margin-left: 8px; + visibility: hidden; + } + &:hover { + background-color: #e6f7ff; + .checkIcon { + color: rgba(0, 0, 0, 0.65); + visibility: visible; + } + } + .filterIconFiltered { + color: @colorPrimary; + :global { + .anticon { + color: @colorPrimary !important; + } + } + } + + .overlay { + width: 225px; + .searchWrapper { + padding: 8px; + .searchIcon { + opacity: 0.45; + } + } + + ul { + margin-bottom: 0; + & > li { + display: flex; + align-items: center; + justify-content: space-between; + margin-right: 0; + padding: 7px 12px; + cursor: pointer; + + .checkIcon { + margin-left: 8px; + visibility: hidden; + } + + &:hover { + background-color: #e6f7ff; + .checkIcon { + color: rgba(0, 0, 0, 0.65); + visibility: visible; + } + } + + // 选中态样式优先级要高于 hover 态 + &.selected { + font-weight: 600; + .checkIcon { + color: @colorPrimary; + visibility: visible; + } + } + } + } + } + + .singleOverlay { + ul { + & > li { + .checkIcon { + display: none; + } + } + } + } + &.selected { + font-weight: 600; + .checkIcon { + color: @colorPrimary; + visibility: visible; + } + } + } + } + } + .singleOverlay { + ul { + & > li { + .checkIcon { + display: none; + } + } + } + } + &.selected { + font-weight: 600; + .checkIcon { + color: @colorPrimary; + visibility: visible; + } + } + } + } + } + .singleOverlay { + ul { + & > li { + .checkIcon { + display: none; + } + } + } + } + &.selected { + font-weight: 600; + .checkIcon { + color: @colorPrimary; + visibility: visible; + } + } + } + } +} +.singleOverlay { + ul { + & > li { + .checkIcon { + display: none; + } + } + } +} diff --git a/frontend/src/component/FilterDropdown/index.style.ts b/frontend/src/component/FilterDropdown/index.style.ts new file mode 100644 index 00000000..77c9aabd --- /dev/null +++ b/frontend/src/component/FilterDropdown/index.style.ts @@ -0,0 +1,43 @@ +import { createStyles } from "antd-style"; + +const useStyles = createStyles(({ token }) => { + return { + filterIconFiltered: { + color: token.colorPrimary, + }, + anticon: { + color: token.colorPrimary, + }, + overlay: { + width: "225px", + ul: { + marginBottom: "0", + "& > li": { + display: "flex", + alignItems: "center", + justifyContent: "space-between", + marginRight: "0", + padding: "7px 12px", + cursor: "pointer", + "&:hover": { backgroundColor: "#e6f7ff" }, + }, + }, + }, + searchWrapper: { + padding: "8px", + }, + searchIcon: { + opacity: "0.45", + }, + checkIcon: { + color: token.colorPrimary, + visibility: "visible", + display: "none", + }, + selected: { + fontWeight: "600", + }, + }; +}); + +export default useStyles; diff --git a/frontend/src/component/FilterDropdown/index.tsx b/frontend/src/component/FilterDropdown/index.tsx new file mode 100644 index 00000000..1216264d --- /dev/null +++ b/frontend/src/component/FilterDropdown/index.tsx @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { formatMessage } from '@/util/intl'; +import React, { useState } from 'react'; +import { Card, Divider, Dropdown, Input, Typography } from '@oceanbase/design'; +import type { DropDownProps } from '@oceanbase/design/es/dropdown'; +import type { InputProps } from '@oceanbase/design/es/input'; +import { CheckOutlined, FilterOutlined, SearchOutlined } from '@oceanbase/icons'; +import { findByValue } from '@oceanbase/util'; +import useStyles from './index.style'; + +const { Text } = Typography; + +export type FilterValue = string | number | undefined; + +export interface Filter { + value: FilterValue; + label?: string; +} + +export interface FilterDropdownProps extends Omit { + mode?: 'multiple' | 'single'; + filters: Filter[]; + value?: FilterValue[]; + onChange?: (value: FilterValue[]) => void; + onClick?: (value: FilterValue) => void; + /* 是否展示搜索框 */ + showSearch?: boolean; + /* 是否展示选中项 */ + showSelection?: boolean; + inputProps?: InputProps; + children?: React.ReactElement; + style?: React.CSSProperties; + cardBodyStyle?: React.CSSProperties; + className?: string; +} + +const FilterDropdown: React.FC = ({ + mode = 'multiple', + filters = [], + value = [], + onChange, + onClick, + showSearch = true, + showSelection = false, + inputProps, + children, + style, + className, + cardBodyStyle, + ...restProps +}) => { + const { styles } = useStyles(); + const [keyword, setKeyword] = useState(''); + return ( + + {showSearch && ( +
{ + // 阻止事件冒泡,避免点击后隐藏下拉菜单 + e.stopPropagation(); + }} + > + { + setKeyword(e.target.value); + }} + prefix={} + {...inputProps} + /> +
+ )} + +
    + {filters + .filter(item => !keyword || (item.label && item.label.includes(keyword))) + .map(item => ( +
  • { + if (mode === 'multiple') { + // 阻止事件冒泡,避免点击后隐藏下拉菜单 + e.stopPropagation(); + } + const newValue = value.includes(item.value) + ? value.filter(valueItem => valueItem !== item.value) + : [...value, item.value]; + if (onChange) { + onChange(newValue); + } + if (onClick) { + onClick(item.value); + } + }} + className={value.includes(item.value) ? styles.selected : ''} + > + {item.label} + +
  • + ))} +
+ {mode === 'multiple' && ( + <> + + + + )} + + } + > + + {showSelection ? ( + value.length > 0 ? ( + + {value.map(item => findByValue(filters, item).label).join(',')} + + ) : ( + children + ) + ) : children ? ( + React.cloneElement(children, { + // 筛选项不为空时用主色调标记筛选 icon + className: `pointable ${ + value && value.length > 0 ? styles.filterIconFiltered : '' + } ${className}`, + style, + }) + ) : ( + 0 ? styles.filterIconFiltered : '' + } ${className}`} + style={style} + /> + )} + +
+ ); +}; + +export default FilterDropdown; diff --git a/frontend/src/component/FormEditTable/EditCell.tsx b/frontend/src/component/FormEditTable/EditCell.tsx new file mode 100644 index 00000000..2bc87087 --- /dev/null +++ b/frontend/src/component/FormEditTable/EditCell.tsx @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { SyntheticEvent } from 'react'; +import React from 'react'; +import { Form } from '@ant-design/compatible'; +import '@ant-design/compatible/assets/index.css'; +import type { GetFieldDecoratorOptions, FormItemProps } from '@oceanbase/design/es/form'; +import type { WrappedFormUtils } from '@ant-design/compatible/lib/form/Form'; +import { EditContext } from './EditRow'; + +const FormItem = Form.Item; + +interface CellValueType extends SyntheticEvent { + currentTarget: EventTarget & T; + target: EventTarget & { value: any }; +} + +export interface EditCellProps { + /* 是否为可编辑表单 */ + editable?: boolean; + /* 是否正在编辑 */ + editing?: boolean; + /* 列名称 */ + title: string; + /* 列字段 */ + dataIndex: string; + /* 是否禁用 */ + disabled: boolean; + /* 每行对应的单条记录 */ + record: T; + /* 单条记录对应的索引 */ + index: number; + /* 对应表单项的属性配置 */ + formItemProps: (text: any, record: T, index: number) => FormItemProps; + /* 对应字段的表单配置 */ + fieldProps: (text: any, record: T, index: number) => GetFieldDecoratorOptions; + /* 对应字段的表单组件 */ + fieldComponent: ( + text: any, + record: T, + index: number, + form: WrappedFormUtils + ) => React.ReactElement; + /* 处理编辑表单的逻辑 */ + handleEdit: (record: T) => void; +} + +class EditCell extends React.Component> { + // eslint-disable-next-line + getValue(record: T, fields: string[]) { + let value = record; + fields.forEach(item => { + value = value && value[item]; + }); + return value; + } + + renderCell = form => { + const { + editing, + dataIndex, + record, + index, + formItemProps = () => {}, + fieldProps = () => {}, + fieldComponent = () =>
, + handleEdit, + children, + disabled: tableDisabled, + } = this.props; + const { getFieldDecorator, validateFields } = form; + let text; + // 支持嵌套的数据格式 + if (dataIndex.includes('.')) { + const fields = dataIndex.split('.'); + text = this.getValue(record, fields); + } else { + text = record[dataIndex]; + } + const element = fieldComponent(text, record, index, form); + const { onChange, disabled } = element.props; + const FormComponent = React.cloneElement(element, { + // 表单组件本身的 disabled 优先级要高于整个表格的 disabled + disabled: disabled || tableDisabled, + onChange: (value: CellValueType) => { + if (onChange) { + onChange(value); + } + // 上层 EditFormTable 通过 handleEdit 去收集每次编辑后的最新值 + if (handleEdit) { + // 由于需要拿到 onChange 后的值,需要异步执行 + setTimeout(() => { + // TODO: 需要在上层提交表单时对 FormItem 进行校验,而不是只在 onChange 的时候校验 + validateFields((err: any, values: T) => { + handleEdit({ + ...record, + ...values, + } as any); + }); + }, 0); + } + }, + }); + return editing ? ( + + {getFieldDecorator(dataIndex, { + initialValue: text, + ...fieldProps(text, record, index), + })(FormComponent)} + + ) : ( + children + ); + }; + + render() { + const { + editable, + editing, + disabled, + dataIndex, + title, + record, + index, + fieldProps, + fieldComponent, + handleEdit, + children, + ...restProps + } = this.props; + return ( + + {editable ? ( + {this.renderCell} + ) : ( + {children} + )} + + ); + } +} + +export default EditCell; diff --git a/frontend/src/component/FormEditTable/EditRow.tsx b/frontend/src/component/FormEditTable/EditRow.tsx new file mode 100644 index 00000000..3d6afe77 --- /dev/null +++ b/frontend/src/component/FormEditTable/EditRow.tsx @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { Form } from '@ant-design/compatible'; +import '@ant-design/compatible/assets/index.css'; + +export const EditContext = React.createContext(); + +const EditRow = ({ form, index, ...props }) => ( + + + +); + +export default Form.create()(EditRow); diff --git a/frontend/src/component/FormEditTable/index.less b/frontend/src/component/FormEditTable/index.less new file mode 100644 index 00000000..21961096 --- /dev/null +++ b/frontend/src/component/FormEditTable/index.less @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.container { + .addButton { + margin-top: 4px; + border-style: dashed; + } + + :global { + // 兼容 antd 3 的表单样式 + .ant-legacy-form-item { + margin-bottom: 0; + + .ant-select { + width: 100%; + } + + .ant-input-number { + width: 100%; + } + } + + .ant-form-item { + margin-bottom: 0; + + .ant-select { + width: 100%; + } + + .ant-input-number { + width: 100%; + } + } + } +} + +.disabledBg { + padding: 10px 0; + background-color: #f5f5f5c2; +} + +.table { + :global { + // 第一列要与卡片 title 左对齐 + .ant-table-thead > tr > th:first-child, + .ant-table-tbody > tr > td:first-child { + padding-left: 24px; + } + + // 最后一列要与 extra 右对齐 + .ant-table-thead > tr > th:last-child, + .ant-table-tbody > tr > td:last-child { + padding-right: 24px; + } + } +} + +.editing { + :global { + .ant-table-tbody > tr > td { + // 设置单元格的直接子元素的最小高度为 40px,与表单对齐 + > * { + display: block; + min-height: 40px; + } + + .ant-legacy-form-item { + min-height: 60px; + } + + .ant-form-item { + min-height: 60px; + } + } + } +} + +.list { + :global { + .ant-table-thead > tr > th { + padding: 0 4px; + padding-bottom: 12px; + font-weight: normal; + background-color: transparent; + border-bottom: none; + } + + .ant-table-tbody > tr > td { + padding: 0 4px; + border-bottom: none; + + .ant-legacy-form-item { + // 设置单元格的最小高度,方便展示表单校验信息时布局不会抖动 + min-height: 60px; + + .ant-legacy-form-item-control { + height: 32px; + line-height: 32px; + } + } + + .ant-form-item { + // 设置单元格的最小高度,方便展示表单校验信息时布局不会抖动 + min-height: 60px; + + .ant-form-item-control { + height: 32px; + line-height: 32px; + } + } + + &:first-child { + padding-left: 0; + } + + &:last-child { + padding-right: 0; + } + } + + .ant-table-tbody > tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected) > td { + background: transparent; + } + + .ant-table-placeholder { + border: none; + + .ant-empty-normal { + margin: 0; + margin-top: 48px; + } + } + // 列表模式,去掉列头之间的分隔线 + .ant-table-thead + > tr + > th:not(:last-child):not(.ant-table-selection-column):not(.ant-table-row-expand-icon-cell):not([colspan])::before { + width: 0; + } + } +} diff --git a/frontend/src/component/FormEditTable/index.style.ts b/frontend/src/component/FormEditTable/index.style.ts new file mode 100644 index 00000000..707a3861 --- /dev/null +++ b/frontend/src/component/FormEditTable/index.style.ts @@ -0,0 +1,69 @@ +import { createStyles } from 'antd-style'; + +const useStyles = createStyles(() => { + return { + addButton: { + marginTop: '4px', + borderStyle: 'dashed', + }, + container: { + '.ant-form-item': { + marginBottom: '0', + '.ant-select': { + width: '100%', + }, + '.ant-input-number': { + width: '100%', + }, + }, + }, + disabledBg: { + padding: '10px 0', + backgroundColor: '#f5f5f5c2', + }, + editing: { + '.ant-table-tbody > tr > td': { + '.ant-legacy-form-item': { + minHeight: '60px', + }, + '.ant-form-item': { + minHeight: '60px', + }, + }, + }, + list: { + '.ant-table-thead > tr > th': { + padding: '0 4px', + paddingBottom: '12px', + fontWeight: 'normal', + backgroundColor: 'transparent', + borderBottom: 'none', + }, + '.ant-table-tbody > tr > td': { + padding: '0 4px', + borderBottom: 'none', + '.ant-legacy-form-item': { + '.ant-legacy-form-item-control': { height: '32px', lineHeight: '32px' }, + }, + '.ant-form-item': { + '.ant-form-item-control': { height: '32px', lineHeight: '32px' }, + }, + '&:first-child': { + paddingLeft: '0', + }, + '&:last-child': { + paddingRight: '0', + }, + }, + '.ant-table-expanded-row': { background: 'transparent' }, + '.ant-table-placeholder': { + border: 'none', + '.ant-empty-normal': { + margin: '0', + marginTop: '48px', + }, + }, + }, + }; +}); +export default useStyles; diff --git a/frontend/src/component/FormEditTable/index.tsx b/frontend/src/component/FormEditTable/index.tsx new file mode 100644 index 00000000..ac6c5694 --- /dev/null +++ b/frontend/src/component/FormEditTable/index.tsx @@ -0,0 +1,487 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { formatMessage } from '@/util/intl'; +import React from 'react'; +import { PlusOutlined, DeleteOutlined } from '@oceanbase/icons'; +import { Button, Popconfirm, Space, Table } from '@oceanbase/design'; +import { Form } from '@ant-design/compatible'; +import '@ant-design/compatible/assets/index.css'; +import type { ButtonProps } from '@oceanbase/design/es/button'; +import type { GetFieldDecoratorOptions } from '@oceanbase/design/es/form'; +import type { WrappedFormUtils } from '@ant-design/compatible/lib/form/Form'; +import type { TableProps, ColumnProps } from '@oceanbase/design/es/table'; +import classNames from 'classnames'; +import { uniqueId } from 'lodash'; +import EditRow, { EditContext } from './EditRow'; +import EditCell from './EditCell'; +import styles from './index.less'; + +export interface EditColumnProps extends ColumnProps { + editable?: boolean; + editing?: boolean; + formItemProps: (text: any, record: T, index: number) => FormItemProps; + fieldProps: (text: any, record: T, index: number) => GetFieldDecoratorOptions; + fieldComponent: (text: any, record: T, index: number) => React.ReactNode; +} + +export interface FormEditTableProps extends TableProps { + /* 保存是否在加载中 */ + saveLoading?: boolean; + /* 可编辑表格的模式: 表格模式 | 列表模式(无边框、间距更加紧凑,类似 List) */ + mode?: 'table' | 'list'; + /* 是否展示新增按钮 */ + allowAdd?: boolean; + /* 是否编辑态和阅读态相互切换 */ + allowSwitch?: boolean; + /* 是否整体禁用 */ + disabled?: boolean; + /* 是否展示删除入口 */ + allowDelete?: boolean; + /* 保存行的回调函数,第二个参数为保存成功的回调函数 */ + onSave?: (record: T, onSuccess: () => void) => void; + /* 删除行的回调函数,第二个参数为删除成功的回调函数 */ + onDelete?: (record: T, onSuccess: () => void) => void; + /* 删除行时是否展示气泡确认框 */ + showDeletePopconfirm: boolean; + deletePopconfirmTitle?: (record: T) => React.ReactNode; + /* 添加按钮文本 */ + addButtonText?: React.ReactNode; + addButtonProps?: ButtonProps; + columns: EditColumnProps[]; + value: T[]; + onValueChange: (value: T[]) => void; + className?: string; +} + +interface FormEditTableState { + editingKey: string; +} + +class FormEditTable extends React.Component, FormEditTableState> { + constructor(props: FormEditTableProps) { + super(props); + this.state = { + editingKey: '', + }; + } + + public isEditing = (record: T) => { + const { editingKey } = this.state; + return record.key === editingKey; + }; + + public handleValueChange = (value: T[]) => { + const { onValueChange } = this.props; + if (onValueChange) { + // 通过下发的 onValueChange 属性函数收集 EditFormTable 的值 + onValueChange(value); + } + }; + + public handleEdit = (record: T) => { + const { value, onValueChange } = this.props; + const newValue = (value || []).map(item => { + if (item.key === record.key) { + return { + ...item, + ...record, + }; + } + return item; + }); + if (onValueChange) { + // 通过下发的 onValueChange 属性函数收集 EditFormTable 的值 + onValueChange(newValue); + } + }; + + public handleAdd = () => { + const { value, onValueChange } = this.props; + const record: any = { + key: uniqueId(), + }; + + if (onValueChange) { + // 通过下发的 onValueChange 属性函数收集 EditFormTable 的值 + onValueChange([...(value || []), record]); + } + }; + + handleCancel = () => { + this.setState({ editingKey: '' }); + }; + + handleSave = (form: WrappedFormUtils, key: string) => { + const { value, onSave } = this.props; + const { validateFields } = form; + validateFields((err, values) => { + if (!err) { + // 浅拷贝 value 的值 + let newValue = [...(value || [])]; + let currentRecord; + const index = newValue.findIndex(item => key === item.key); + if (index > -1) { + const item = newValue[index]; + currentRecord = { + ...item, + ...values, + }; + + newValue.splice(index, 1, currentRecord); + } else { + newValue = [...newValue, values]; + currentRecord = values; + } + + if (onSave) { + onSave(currentRecord, () => { + this.handleValueChange(newValue); + this.setState({ + editingKey: '', + }); + }); + } + } + }); + }; + + handleEditing = (key: number) => { + this.setState({ + editingKey: key, + }); + }; + + handleDelete = (record: T) => { + const { value } = this.props; + const newValue = value.filter(item => item.key !== record.key); + this.handleValueChange(newValue); + }; + + public render() { + const { + saveLoading, + value, + /* 默认表格模式 */ + mode = 'table', + /* 默认不展示新增按钮 */ + allowAdd = false, + /* 默认为编辑态和阅读态之间不可切换 */ + allowSwitch = false, + /* 未设置 allowDelete 时,行数大于 1 才展示删除按钮 */ + allowDelete = value?.length > 1, + disabled, + onDelete, + showDeletePopconfirm = true, + deletePopconfirmTitle, + addButtonText, + addButtonProps, + columns, + className, + // 编辑权限默认为 true + editAccessible = true, + // 删除权限默认为 true + deleteAccessible = true, + ...restProps + } = this.props; + const { editingKey } = this.state; + let newColumns = columns + .map(column => { + const { title, dataIndex, editable, formItemProps, fieldProps, fieldComponent } = column; + + if (!editable) { + return column; + } + return { + ...column, + editable: true, + onCell: (record: any, index: number) => ({ + title, + disabled, + dataIndex, + record, + index, + /* + * 若允许切换,则 editing 根据 editingKey 判断; + * 若不允许切换,则 editing 总是为 true; + */ + editing: allowSwitch ? this.isEditing(record) : true, + editable, + formItemProps, + fieldProps, + fieldComponent, + // 若允许切换,则收集值的时机则是手动点击确定时,而不是每次更新都收集 + handleEdit: allowSwitch ? () => {} : this.handleEdit, + }), + }; + }) + .map(column => { + // 兼容默认的 table + if (column?.dataIndex?.includes('.')) { + column.dataIndex = column?.dataIndex?.split('.'); + } + return column; + }); + + if (allowSwitch && (editAccessible || deleteAccessible)) { + newColumns = [ + ...newColumns, + { + title: formatMessage({ + id: 'ocp-express.component.FormEditTable.Operation', + defaultMessage: '操作', + }), + dataIndex: 'operation', + render: (text, record) => { + const editing = this.isEditing(record); + return editing ? ( + + + {(form: WrappedFormUtils) => ( + { + setTimeout(() => { + this.handleSave(form, record.key); + }, 0); + }} + > + + + )} + + + + + ) : ( + + this.handleEditing(record.key)}> + {formatMessage({ + id: 'ocp-express.component.FormEditTable.Editing', + defaultMessage: '编辑', + })} + + + {showDeletePopconfirm ? ( + { + if (onDelete) { + onDelete(record, () => { + this.handleDelete(record); + }); + } + }} + > + + {formatMessage({ + id: 'ocp-express.component.FormEditTable.Delete', + defaultMessage: '删除', + })} + + + ) : ( + { + if (onDelete) { + onDelete(record, () => { + this.handleDelete(record); + }); + } + }} + > + {formatMessage({ + id: 'ocp-express.component.FormEditTable.Delete', + defaultMessage: '删除', + })} + + )} + + ); + }, + }, + ]; + } else if (allowDelete && deleteAccessible) { + // 在用户没有删除权限时,也不展示删除入口;权限所见即所得 + newColumns = [ + ...newColumns, + { + dataIndex: 'operation', + editable: false, + width: 20, + render: (text: any, record: T) => ( + // 为了保证 delete icon 与其他表单项垂直对齐,需要被 Form.Item 包裹 + + + {showDeletePopconfirm ? ( + { + if (onDelete) { + // 如果存在 onDelete,则表明需要自定义删除逻辑,handleDelete 需要由上层决定是否调用 + onDelete(record, () => { + this.handleDelete(record); + }); + } else { + this.handleDelete(record); + } + }} + > + + + ) : ( + { + if (onDelete) { + // 如果存在 onDelete,则表明需要自定义删除逻辑,handleDelete 需要由上层决定是否调用 + onDelete(record, () => { + this.handleDelete(record); + }); + } else { + this.handleDelete(record); + } + }} + // 保证 icon 与表单垂直居中对齐 + style={{ display: 'inline-block', marginTop: 8 }} + /> + )} + + + ), + }, + ]; + } + const components = { + body: { + row: EditRow, + cell: EditCell, + }, + }; + + const newProps = { + ...restProps, + columns: newColumns, + // 对于可编辑表格,数据源等价于自身的 value + dataSource: value, + components, + }; + + return ( +
+ {/* 因为 cursor: not-allowed 失效问题, 所以需要单独用 span 包裹 Table */} + record.key} {...newProps} /> + {allowAdd && ( + + )} + + ); + } +} + +export default FormEditTable; diff --git a/frontend/src/component/FormEditZoneReplicaTable/index.tsx b/frontend/src/component/FormEditZoneReplicaTable/index.tsx new file mode 100644 index 00000000..1ec91482 --- /dev/null +++ b/frontend/src/component/FormEditZoneReplicaTable/index.tsx @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { formatMessage } from '@/util/intl'; +import React from 'react'; +import { InputNumber } from '@oceanbase/design'; +import { findByValue, findBy, byte2GB } from '@oceanbase/util'; +import { REPLICA_TYPE_LIST } from '@/constant/oceanbase'; +import { getUnitSpecLimit } from '@/util/cluster'; +import type { FormEditTableProps } from '@/component/FormEditTable'; +import FormEditTable from '@/component/FormEditTable'; +import MySelect from '@/component/MySelect'; +import UnitSpec from '@/component/UnitSpec'; +import { format } from 'crypto-js'; +import { formatSize } from '@/util'; + +const { Option } = MySelect; + +export interface FormEditZoneReplicaTableProps extends FormEditTableProps { + className?: string; + value: T[]; + tenantData: API.TenantInfo; + unitSpecLimit?: any; + saveLoading?: boolean; + dispatch?: any; +} + +class FormEditZoneReplicaTable extends FormEditTable> { + constructor(props: FormEditZoneReplicaTableProps) { + super(props); + this.state = { + ...(super.state || {}), + }; + } + + // 删除 zone + public handleDeleteRecord = (record: any) => { + const { value } = this.props; + const newValue = value.filter(item => item.key !== record.key); + this.handleValueChange(newValue); + }; + + public render() { + const { saveLoading, clusterData, unitSpecLimit } = this.props; + + const columns = [ + { + title: formatMessage({ + id: 'ocp-express.component.FormEditZoneReplicaTable.ZoneName', + defaultMessage: 'Zone 名称', + }), + + dataIndex: 'name', + }, + + { + title: formatMessage({ + id: 'ocp-express.component.FormEditZoneReplicaTable.CopyType', + defaultMessage: '副本类型', + }), + + dataIndex: 'replicaType', + width: '20%', + editable: false, + fieldProps: () => ({ + rules: [ + { + required: true, + message: formatMessage({ + id: 'ocp-express.component.FormEditZoneReplicaTable.SelectAReplicaType', + defaultMessage: '请选择副本类型', + }), + }, + ], + }), + + fieldComponent: () => ( + + {REPLICA_TYPE_LIST.map(item => ( + + ))} + + ), + + render: (text: API.ReplicaType) => ( + {findByValue(REPLICA_TYPE_LIST, text).label} + ), + }, + { + title: formatMessage({ + id: 'ocp-express.component.FormEditZoneReplicaTable.UnitSpecification', + defaultMessage: 'Unit 规格', + }), + dataIndex: 'resourcePool.unitConfig', + width: '40%', + editable: true, + fieldComponent: (text, record) => { + const zoneData = findBy(clusterData?.zones || [], 'name', record.name); + + let idleCpuCore, idleMemoryInBytes; + if (zoneData?.servers?.length > 0 && zoneData?.servers[0]?.stats) { + const { idleCpuCoreTotal, idleMemoryInBytesTotal } = getUnitSpecLimit( + zoneData?.servers[0]?.stats + ); + + idleCpuCore = idleCpuCoreTotal; + idleMemoryInBytes = idleMemoryInBytesTotal; + } + + console.log(record?.resourcePool?.unitConfig, 'record?.resourcePool?.unitConfig'); + + return ( + + ); + }, + + render: (text: string, record: API.TenantZone) => { + const { unitConfig } = (record.resourcePool as API.ResourcePool) || {}; + const { max_cpu: maxCpuCoreCount, memory_size } = (unitConfig as API.UnitConfig) || {}; + + const maxMemorySizeGB = byte2GB(memory_size); + + return ( +
    +
  • + {formatMessage( + { + id: 'ocp-express.component.FormEditZoneReplicaTable.CpuCoreMincpucorecountMaxcpucorecount', + defaultMessage: 'CPU(核): {maxCpuCoreCount}', + }, + + { maxCpuCoreCount } + )} +
  • +
  • + {formatMessage( + { + id: 'ocp-express.component.FormEditZoneReplicaTable.MemoryGbMinmemorysizegbMaxmemorysizegb', + defaultMessage: '内存(GB):{maxMemorySizeGB}', + }, + + { maxMemorySizeGB } + )} +
  • +
+ ); + }, + }, + + // { + // title: ( + // + // ), + + // dataIndex: 'resourcePool.unitSpecName', + // width: '25%', + // editable: true, + // fieldComponent: () => ( + // + // + // {formatMessage({ + // id: 'ocp-express.component.FormEditZoneReplicaTable.EmptyIndicatesThatTheUnit', + // defaultMessage: '为空表示不修改 Unit 规格', + // })} + // + // + // } + // /> + // ), + // fieldProps: (text, record) => ({ + // rules: [ + // { + // validator: (rule, value = text, callback) => { + // if (value) { + // return validatorUnitResource( + // rule, + // record.resourcePool.unitConfig, + // callback, + // findBy(tenantData.zones || [], 'name', record.name) + // ); + // } else { + // return callback(); + // } + // }, + // }, + // ], + // }), + + // render: (text: string, record: API.TenantZone) => { + // const { unitConfig } = (record.resourcePool as API.ResourcePool) || {}; + // const { maxCpuCoreCount, maxMemorySize: maxMemorySizeGB } = + // (unitConfig as API.UnitConfig) || {}; + + // return ( + //
    + //
  • + // {formatMessage( + // { + // id: 'ocp-express.component.FormEditZoneReplicaTable.CpuCoreMincpucorecountMaxcpucorecount', + // defaultMessage: 'CPU(核): {maxCpuCoreCount}', + // }, + + // { maxCpuCoreCount } + // )} + //
  • + //
  • + // {formatMessage( + // { + // id: 'ocp-express.component.FormEditZoneReplicaTable.MemoryGbMinmemorysizegbMaxmemorysizegb', + // defaultMessage: '内存(GB):{maxMemorySizeGB}', + // }, + + // { maxMemorySizeGB } + // )} + //
  • + //
+ // ); + // }, + // }, + + { + title: formatMessage({ + id: 'ocp-express.component.FormEditZoneReplicaTable.UnitQuantity', + defaultMessage: 'Unit 数量', + }), + + dataIndex: 'resourcePool.unit_num', + editable: false, + fieldProps: () => ({ + rules: [ + { + required: true, + message: formatMessage({ + id: 'ocp-express.component.FormEditZoneReplicaTable.EnterTheUnitQuantity', + defaultMessage: '请输入 Unit 数量', + }), + }, + ], + }), + + fieldComponent: () => ( + + ), + }, + ]; + + return ( + + ); + } +} + +export default FormEditZoneReplicaTable; diff --git a/frontend/src/component/FormPrimaryZone/index.less b/frontend/src/component/FormPrimaryZone/index.less new file mode 100644 index 00000000..bb60b230 --- /dev/null +++ b/frontend/src/component/FormPrimaryZone/index.less @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import '~@oceanbase/design/es/theme/index.less'; + +.container { + display: flex; + justify-content: space-between; + :global { + .ant-card-body { + min-height: 300px; + } + .ant-typography-ellipsis { + // 覆盖 typography 的 display,否则 ellipsis 的文案不显示 + display: inline; + } + } + + .zone { + display: inline-block; + width: calc((100% - 96px) / 2); + } + + .transferWrapper { + display: inline-block; + margin-top: 150px; + padding: 0 24px; + // TODO: 以下两行代码可以保证大部分情况下穿梭按钮保持垂直居中,先这样临时处理,后续要寻找更完善的优化方案 + vertical-align: top; + + .transfer { + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + background-color: #f5f8fe; + border: 1px solid #cdd5e4; + border-radius: 4px; + } + + .active { + color: @colorPrimary; + background-color: @colorPrimary; + border-color: @colorPrimary; + cursor: pointer; + .icon { + color: #fff; + } + } + + .disabled { + color: rgba(0, 0, 0, 0.25); + background-color: #f5f5f5; + border-color: #d9d9d9; + cursor: not-allowed; + } + } + + .description { + margin-left: 8px; + color: @colorTextTertiary; + font-weight: normal; + font-size: 12px; + font-family: PingFangSC-Regular; + line-height: 22px; + } + + .priorityList { + display: inline-block; + width: calc((100% - 96px) / 2); + + // 解决无法顶部对齐的问题 + vertical-align: top; + + :global { + .ant-card-body { + padding: 0; + } + } + + .dragList { + height: 100%; + + .dragItem { + display: flex; + align-items: center; + justify-content: space-between; + padding: 8px 16px; + border-bottom: 1px solid #e2e8f3; + + .deleteIcon { + cursor: pointer; + } + } + } + } +} diff --git a/frontend/src/component/FormPrimaryZone/index.style.ts b/frontend/src/component/FormPrimaryZone/index.style.ts new file mode 100644 index 00000000..1f3e8858 --- /dev/null +++ b/frontend/src/component/FormPrimaryZone/index.style.ts @@ -0,0 +1,73 @@ +import { createStyles } from "antd-style"; + +const useStyles = createStyles(({ token }) => { + return { + container: { + display: "flex", + justifyContent: "space-between", + ".ant-card-body": { minHeight: "300px" }, + }, + zone: { + display: "inline-block", + width: "calc((100% - 96px) / 2)", + }, + transferWrapper: { + display: "inline-block", + marginTop: "150px", + padding: "0 24px", + }, + transfer: { + display: "flex", + alignItems: "center", + justifyContent: "center", + width: "32px", + height: "32px", + backgroundColor: "#f5f8fe", + border: "1px solid #cdd5e4", + borderRadius: "4px", + }, + active: { + color: token.colorPrimary, + backgroundColor: token.colorPrimary, + borderColor: token.colorPrimary, + cursor: "pointer", + }, + icon: { + color: "#fff", + }, + disabled: { + color: "rgba(0, 0, 0, 0.25)", + backgroundColor: "#f5f5f5", + borderColor: "#d9d9d9", + cursor: "not-allowed", + }, + description: { + marginLeft: "8px", + color: token.colorTextTertiary, + fontWeight: "normal", + fontSize: "12px", + fontFamily: "PingFangSC-Regular", + lineHeight: "22px", + }, + priorityList: { + display: "inline-block", + width: "calc((100% - 96px) / 2)", + ".ant-card-body": { padding: "0" }, + }, + dragList: { + height: "100%", + }, + dragItem: { + display: "flex", + alignItems: "center", + justifyContent: "space-between", + padding: "8px 16px", + borderBottom: "1px solid #e2e8f3", + }, + deleteIcon: { + cursor: "pointer", + }, + }; +}); + +export default useStyles; diff --git a/frontend/src/component/FormPrimaryZone/index.tsx b/frontend/src/component/FormPrimaryZone/index.tsx new file mode 100644 index 00000000..cf07f9f8 --- /dev/null +++ b/frontend/src/component/FormPrimaryZone/index.tsx @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { formatMessage } from '@/util/intl'; +import React from 'react'; +import { Checkbox, Col, Row, Spin, Typography, Card, Tooltip } from '@oceanbase/design'; +import classNames from 'classnames'; +import { flatten, isEqual, uniq } from 'lodash'; +import { sortByEnum } from '@oceanbase/util'; +import { RightOutlined, DeleteOutlined } from '@oceanbase/icons'; +import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd'; +import { isEnglish } from '@/util'; +import ContentWithIcon from '@/component/ContentWithIcon'; +import { ReactComponent as DragIconSvg } from '@/asset/drag_icon.svg'; +import styles from './index.less'; + +const { Text } = Typography; + +export interface FormPrimaryZoneProps { + zoneList: string[]; + loading: boolean; + value?: string; + onChange?: (value: string) => void; +} + +export interface FormPrimaryZoneState { + zoneList: string[]; + checkedList: string[]; + checkAll: boolean; + indeterminate: boolean; + priorityList: string[]; +} + +class FormPrimaryZone extends React.Component { + public constructor(props: FormPrimaryZoneProps) { + super(props); + this.state = { + // 候选 zone 列表 + zoneList: props.zoneList, + // 选中的 zone 列表 + checkedList: [], + // 是否全部选中 + checkAll: false, + // 是否部分选中 + indeterminate: false, + // zone 优先级列表,形如 zone1,zone2;zone3 + priorityList: [], + }; + } + + public static getDerivedStateFromProps(props: FormPrimaryZoneProps, state: FormPrimaryZoneState) { + const newState: Partial = state; + const { value, zoneList } = props; + if ('value' in props) { + const nestPriorityList = + (value && value.split(';') && value.split(';').map((item) => item.split(','))) || []; + const priorityList = nestPriorityList + // 将不在 zone 列表中的优先级去除 + .map((item) => (item || []).filter((subItem) => zoneList.indexOf(subItem) !== -1)) + // 筛选掉空数组 + .filter((item) => item && item.length > 0) + // 以逗号连接优先级相同的 zone + .map((item) => item.join(',')); + // 更新右侧的优先级列表 + newState.priorityList = priorityList; + // 已经设置了优先级的 zone 列表 + const zoneListInPriority = flatten(priorityList.map((item) => item.split(','))); + // 更新左侧的 zone 列表 + // 最后需要做去重,否则在某些交互条件下,会出现预期外的重复 zone + // TODO: 可能是 zone 相同时,会触发 Checkbox 的相关 bug,具体原因待排查 + newState.zoneList = uniq( + zoneList + // 筛掉空值 + .filter((item) => item) + .filter((item) => zoneListInPriority.indexOf(item) === -1), + ); + } + return newState; + } + + public componentDidUpdate(prevProps: FormPrimaryZoneProps) { + const { zoneList, onChange } = this.props; + // priorityList 已经在 getDerivedStateFromProps 做了处理,是最新的值,直接使用即可 + const { priorityList } = this.state; + // 当上层设置的 zone 列表变化时,zone 的优先级也需要联动 + if (!isEqual(zoneList, prevProps.zoneList)) { + if (onChange) { + onChange(priorityList.join(';')); + } + } + } + + public handleChange = (value: string) => { + const { onChange } = this.props; + if (onChange) { + onChange(value); + } + }; + + // 根据原始的 zone 列表进行排序 + public sortByZoneList = (list: string[]) => { + const { zoneList } = this.props; + return list.sort((a, b) => sortByEnum(a, b, '', zoneList)); + }; + + // 勾选 zone + public handleCheckboxGroupChange = (checkedList: string[]) => { + const { zoneList } = this.state; + this.setState({ + checkedList: this.sortByZoneList(checkedList), + checkAll: checkedList.length === zoneList.length, + indeterminate: !!checkedList.length && checkedList.length < zoneList.length, + }); + }; + + // 全选/不选 zone + public handleCheckAllChange = (e: any) => { + const { zoneList } = this.state; + this.setState({ + checkedList: e.target.checked ? zoneList : [], + checkAll: e.target.checked, + indeterminate: false, + }); + }; + + // 新增一项 zone 优先级 + public handleTransfer = () => { + const { checkedList, priorityList } = this.state; + // 只有选中了 zone,才能允许新增 zone 优先级 + if (checkedList.length) { + this.setState( + { + checkedList: [], + checkAll: false, + indeterminate: false, + }, + + // 更新组件值 + () => { + this.handleChange( + [...priorityList, this.sortByZoneList(checkedList).join(',')].join(';'), + ); + }, + ); + } + }; + + public getItemStyle = (isDragging, draggableStyle) => ({ + userSelect: 'none', + backgroundColor: isDragging ? '#fafafa' : 'transparent', + // 需要应用的拖拽样式 + ...draggableStyle, + }); + + // zone 优先级拖拽排序 + public onDragEnd = (result: any) => { + const { priorityList } = this.state; + const { source, destination } = result; + // dropped outside the list + if (!destination) { + return; + } + const newPriorityList = this.reorder(priorityList, source.index, destination.index); + this.handleChange(newPriorityList.join(';')); + }; + + public reorder = (list: any[], startIndex: number, endIndex: number) => { + const result = Array.from(list); + const [removed] = result.splice(startIndex, 1); + result.splice(endIndex, 0, removed); + return result; + }; + + // 删除一项 zone 优先级 + public handleDeletePriority = (priority: string) => { + const { checkedList, priorityList } = this.state; + this.setState( + { + checkAll: false, + indeterminate: !!checkedList.length, + }, + + // 更新组件值 + () => { + this.handleChange(priorityList.filter((item) => item !== priority).join(';')); + }, + ); + }; + + public resetPrioritization = () => { + this.setState( + { + zoneList: this.props.zoneList, + priorityList: [], + }, + + () => { + this.handleChange(''); + }, + ); + }; + + public render() { + const { loading = false } = this.props; + const { zoneList, checkAll, indeterminate, checkedList, priorityList } = this.state; + return ( +
+ + + Zone + + + {formatMessage({ + id: 'ocp-express.component.FormPrimaryZone.AfterYouSelectMultipleZones', + defaultMessage: '同时选择多个 Zone 穿梭到右侧后,可设置为同一优先级', + })} + + + } + > + + + {/** + * 栅格布局在内容为空时,高度会出现异常 + * **/} + 0 ? 'auto' : 0 }}> + {zoneList.map((item) => ( +
+ + {item} + + + ))} + + + + + + + + + + + + {formatMessage({ + id: 'ocp-express.component.FormPrimaryZone.PrioritySorting', + defaultMessage: '优先级排序', + })} + + + + {formatMessage({ + id: 'ocp-express.component.FormPrimaryZone.PriorityFromTopToBottom', + defaultMessage: '优先级从上到下代表从高到低,可拖拽排序', + })} + + + this.resetPrioritization()} + style={{ float: 'right', fontWeight: 'normal' }} + > + {formatMessage({ + id: 'ocp-express.component.FormPrimaryZone.RestoreToDefault', + defaultMessage: '恢复为默认', + })} + + + } + > + + + {({ droppableProps, innerRef }) => ( +
+ {priorityList.map((item, index) => ( + + {( + { draggableProps, dragHandleProps, innerRef: subInnerRef }, + { isDragging }, + ) => ( +
+ + + this.handleDeletePriority(item)} + /> +
+ )} +
+ ))} +
+ )} +
+
+
+ + ); + } +} + +export default FormPrimaryZone; diff --git a/frontend/src/component/FormTable/index.less b/frontend/src/component/FormTable/index.less new file mode 100644 index 00000000..ed147e0d --- /dev/null +++ b/frontend/src/component/FormTable/index.less @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.addButton { + border-style: dashed; +} diff --git a/frontend/src/component/FormTable/index.style.ts b/frontend/src/component/FormTable/index.style.ts new file mode 100644 index 00000000..2399c387 --- /dev/null +++ b/frontend/src/component/FormTable/index.style.ts @@ -0,0 +1,10 @@ +import { createStyles } from 'antd-style'; + +const useStyles = createStyles(() => { + return { + addButton: { + borderStyle: 'dashed', + }, + }; +}); +export default useStyles; diff --git a/frontend/src/component/FormTable/index.tsx b/frontend/src/component/FormTable/index.tsx new file mode 100644 index 00000000..95f7ebec --- /dev/null +++ b/frontend/src/component/FormTable/index.tsx @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { formatMessage } from '@/util/intl'; +import type { ReactElement, SyntheticEvent } from 'react'; +import React from 'react'; +import { PlusOutlined } from '@oceanbase/icons'; +import { Button, Table } from '@oceanbase/design'; +import type { ButtonProps } from '@oceanbase/design/es/button'; +import type { TableProps, ColumnProps } from '@oceanbase/design/es/table'; +import styles from './index.less'; + +export interface CellValueType extends SyntheticEvent { + currentTarget: EventTarget & T; + target: EventTarget & { value: any }; +} + +export interface AobEditFormTableProps extends TableProps { + disabled?: boolean; + value: T[]; + onEditChange: (value: T[]) => void; // 编辑值变化 + addButtonProps?: ButtonProps; +} + +interface AobEditFormTableState { + data: any[]; +} + +class AobEditFormTable extends React.Component, AobEditFormTableState> { + public static getDerivedStateFromProps(props: AobEditFormTableProps) { + const newState: any = { + prevProps: props, + }; + + const { value } = props; + if ('value' in props) { + // 将下发的 value 赋值给 AobEditFormTable,这里将 data 作为 AobEditFormTable 的值 + newState.data = value; + } + return newState; + } + + public state = { + data: [], + }; + + public handleEditChange = (record: any, index: number) => { + const { onEditChange } = this.props; + const { data } = this.state; + let newData: any[] = [...data]; + const prevRecord: any = newData[index]; + newData = newData.map((item, itemIndex) => { + if (index === itemIndex) { + return { + ...prevRecord, + ...record, + }; + } + return item; + }); + if (onEditChange) { + // 通过下发的 onEditChange 属性函数收集 AobEditFormTable 的值 + onEditChange(newData); + } + }; + + public handleCellChange = (item: any, record: any, index: number) => { + this.handleEditChange( + { + ...record, + ...item, + }, + + index + ); + }; + + public handleAddChange = (record: any) => { + const { onEditChange } = this.props; + const { data } = this.state; + if (onEditChange) { + // 通过下发的 onEditChange 属性函数收集 AobEditFormTable 的值 + onEditChange([...data, record]); + } + }; + + public handleAdd = () => { + const { columns } = this.props; + const record = {}; + columns!.forEach(column => { + if (column) { + record[column.dataIndex] = ''; + } + }); + this.handleAddChange(record); + }; + + public render() { + const { disabled, addButtonProps, columns, ...restProps } = this.props; + const newColumns = columns!.map((column: ColumnProps) => { + const { dataIndex, render } = column; + const newColumn = { + ...column, + render: (text: string, record: any, index: number) => { + const element = (render ? render!(text, record, index) : ) as ReactElement; + const { onChange } = element.props; + const nodeWithRender = React.cloneElement(element, { + disabled: element.props.disabled || disabled, + onChange: (value: CellValueType) => { + if (onChange) { + onChange(value); + } + this.handleCellChange( + { + [dataIndex!]: value.nativeEvent // 判断 value 是否为 Raect 合成事件 + ? (value.target as HTMLInputElement) && value.target.value + : value, + }, + + record, + index + ); + }, + }); + + const nodeWithoutRender = React.cloneElement( + element, + { + onChange: (value: CellValueType) => { + this.handleCellChange( + { + [dataIndex!]: value.nativeEvent // 判断 value 是否为 Raect 合成事件 + ? (value.target as HTMLInputElement) && value.target.value + : value, + }, + + record, + index + ); + }, + }, + + text + ); + + return render ? nodeWithRender : nodeWithoutRender; + }, + }; + + return newColumn; + }); + const newProps = { + ...restProps, + columns: newColumns, + }; + + return ( +
+
+ + + ); + } +} + +export default AobEditFormTable; diff --git a/frontend/src/component/FormZoneReplicaTable/index.tsx b/frontend/src/component/FormZoneReplicaTable/index.tsx new file mode 100644 index 00000000..c8c211e9 --- /dev/null +++ b/frontend/src/component/FormZoneReplicaTable/index.tsx @@ -0,0 +1,215 @@ +// ! 此文件全局暂时没有用到 +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { formatMessage } from '@/util/intl'; +import React from 'react'; +import { Checkbox, InputNumber } from '@oceanbase/design'; +import { some } from 'lodash'; +import { findBy } from '@oceanbase/util'; +import { REPLICA_TYPE_LIST } from '@/constant/oceanbase'; +import { validateUnitCount } from '@/util/oceanbase'; +import type { FormEditTableProps } from '@/component/FormEditTable'; +import FormEditTable from '@/component/FormEditTable'; +import MySelect from '@/component/MySelect'; +import UnitSpecSelect from '@/component/UnitSpecSelect'; + +const { Option } = MySelect; + +export interface FormZoneReplicaTableProps extends FormEditTableProps { + className?: string; + value: T[]; + clusterData: API.ClusterInfo; + zonesUnitCount?: number; +} + +class FormZoneReplicaTable extends FormEditTable> { + static validate = (rule, value, callback) => { + if ( + value && + // 仅校验勾选行 + (some(value, item => item.checked && !item?.replicaType) || + some(value, item => item.checked && !item?.resourcePool?.unitSpecName) || + some(value, item => item.checked && !item?.resourcePool?.unitCount)) + ) { + callback( + formatMessage({ + id: 'ocp-express.component.FormZoneReplicaTable.IncompleteReplicaSettings', + defaultMessage: '副本设置不完整', + }) + ); + } + callback(); + }; + + public render() { + const { clusterData, zonesUnitCount, ...restProps } = this.props; + const columnWidth = '30%'; + + const columns = [ + { + title: '', + dataIndex: 'checked', + width: 24, + editable: true, + fieldProps: () => ({ + valuePropName: 'checked', + }), + fieldComponent: () => , + }, + { + title: formatMessage({ + id: 'ocp-express.component.FormZoneReplicaTable.ZoneName', + defaultMessage: 'Zone 名称', + }), + + dataIndex: 'name', + width: columnWidth, + editable: true, + fieldComponent: () => ( + // 由于每个 zone 都需要设置副本,直接从集群的 zones 同步过来即可,并置为不可编辑 + + {((clusterData as API.ClusterInfo).zones || []).map(item => ( + + ))} + + ), + }, + + { + title: formatMessage({ + id: 'ocp-express.component.FormZoneReplicaTable.CopyType', + defaultMessage: '副本类型', + }), + + dataIndex: 'replicaType', + width: columnWidth, + editable: true, + fieldProps: (text, record) => { + const zoneData = findBy(clusterData.zones || [], 'name', record.name); + return { + rules: [ + { + // 仅勾选行需要必填 + required: zoneData.checked, + message: formatMessage({ + id: 'ocp-express.component.FormZoneReplicaTable.SelectAReplicaType', + defaultMessage: '请选择副本类型', + }), + }, + ], + }; + }, + + fieldComponent: () => ( + + {REPLICA_TYPE_LIST.map(item => ( + + ))} + + ), + }, + + { + title: formatMessage({ + id: 'ocp-express.component.FormZoneReplicaTable.UnitSpecification', + defaultMessage: 'Unit 规格', + }), + + // 嵌套的数据格式 + dataIndex: 'resourcePool.unitSpecName', + width: columnWidth, + editable: true, + fieldProps: (text, record) => { + const zoneData = findBy(clusterData.zones || [], 'name', record.name); + return { + rules: [ + { + // 仅勾选行需要必填 + required: zoneData.checked, + message: formatMessage({ + id: 'ocp-express.component.FormZoneReplicaTable.SelectAUnit', + defaultMessage: '请选择 Unit 规格', + }), + }, + ], + }; + }, + + fieldComponent: () => , + }, + { + title: formatMessage({ + id: 'ocp-express.component.FormZoneReplicaTable.UnitQuantity', + defaultMessage: 'Unit 数量', + }), + + // 嵌套的数据格式 + dataIndex: 'resourcePool.unitCount', + editable: true, + fieldProps: (text, record) => { + const zoneData = findBy(clusterData.zones || [], 'name', record.name); + return { + initialValue: zonesUnitCount, + rules: [ + { + // 仅勾选行需要必填 + required: zoneData.checked, + message: formatMessage({ + id: 'ocp-express.component.FormZoneReplicaTable.UnitQuantityCannotBeEmpty', + defaultMessage: '请输入 Unit 数量', + }), + }, + + { + validator: (rule, value, callback) => + validateUnitCount(rule, value, callback, zoneData), + }, + ], + }; + }, + fieldComponent: () => ( + + ), + }, + ]; + + return ( + + ); + } +} + +export default FormZoneReplicaTable; diff --git a/frontend/src/component/FrameBox.tsx b/frontend/src/component/FrameBox.tsx new file mode 100644 index 00000000..83523f5c --- /dev/null +++ b/frontend/src/component/FrameBox.tsx @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 OceanBase. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; + +interface Props { + data: string; + title: string; +} + +/** + * 使用 iframe 用于展示后端返回的文件内容,例如 ASH、AWR 报告文件 + */ +const FrameBox: React.FC = ({ title, data }) => { + return ( +