From 9866cf840d613be672507e2392c1ffedf2660502 Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Mon, 17 Feb 2025 07:01:09 +0000 Subject: [PATCH 001/113] PullRequest: 349 fix: hung when start the cluster --- agent/repository/model/oceanbase/dag_instance.go | 5 +++-- agent/repository/model/sqlite/dag_instance.go | 5 +++-- agent/service/task/status_maintainer.go | 10 ++++++++-- 3 files changed, 14 insertions(+), 6 deletions(-) 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/sqlite/dag_instance.go b/agent/repository/model/sqlite/dag_instance.go index a619066c..1af8443f 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,9 @@ type DagInstance struct { } func (d *DagInstance) ToBO() *bo.DagInstance { - MaintenanceType := 0 + MaintenanceType := task.NOT_UNDER_MAINTENANCE if d.IsMaintenance { - MaintenanceType = 2 + MaintenanceType = task.GLOBAL_MAINTENANCE } return &bo.DagInstance{ Id: d.Id, diff --git a/agent/service/task/status_maintainer.go b/agent/service/task/status_maintainer.go index 9c4d3786..a9d2cde5 100644 --- a/agent/service/task/status_maintainer.go +++ b/agent/service/task/status_maintainer.go @@ -192,8 +192,14 @@ func (maintainer *agentStatusMaintainer) setStatus(tx *gorm.DB, newStatus int, o 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 resp.RowsAffected == 0 && 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 set status to %d: agent status is not %d", newStatus, oldStatus) } return nil } From 095cdd839b2a3c22c72b811349e93d7eed1b9ca1 Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Mon, 17 Feb 2025 10:01:01 +0000 Subject: [PATCH 002/113] PullRequest: 351 fix: daemon startup fails when the PID in daemon.pid is already occupied. --- agent/cmd/admin/start.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 } From 34e57c88e69aabd56ce566bc1fc30323765e9ae1 Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Mon, 17 Feb 2025 10:01:15 +0000 Subject: [PATCH 003/113] PullRequest: 352 fix: upgrade failed --- agent/cmd/server/init.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/agent/cmd/server/init.go b/agent/cmd/server/init.go index d3aa3e5b..f165e8ae 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" @@ -267,12 +267,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) From 94027f3593d6f3f8dd65f8a944c7e397903c4b6a Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Tue, 18 Feb 2025 07:01:59 +0000 Subject: [PATCH 004/113] PullRequest: 350 rewrite the logic of set tenant variable --- agent/api/agent_route.go | 1 + agent/api/tenant_handler.go | 2 +- agent/executor/tenant/create_tenant.go | 79 +++++++++++++------ agent/executor/tenant/enter.go | 19 ++++- agent/executor/tenant/optimize.go | 76 ------------------- agent/executor/tenant/parameter.go | 6 ++ agent/executor/tenant/set_root_pwd.go | 4 +- agent/executor/tenant/variable.go | 101 ++++++++++++++++++++++--- agent/service/tenant/tenant.go | 23 ++++++ client/cmd/recyclebin/tenant/enter.go | 2 +- client/cmd/tenant/variable/enter.go | 11 ++- param/tenant.go | 5 +- 12 files changed, 209 insertions(+), 120 deletions(-) diff --git a/agent/api/agent_route.go b/agent/api/agent_route.go index aed220a6..e834ed98 100644 --- a/agent/api/agent_route.go +++ b/agent/api/agent_route.go @@ -55,6 +55,7 @@ func InitOcsAgentRoutes(s *http2.State, r *gin.Engine, isLocalRoute bool) { constant.URI_TASK_RPC_PREFIX+constant.URI_SUB_TASK, constant.URI_API_V1+constant.URI_TENANT_GROUP, constant.URI_TENANT_API_PREFIX+constant.URI_PATH_PARAM_NAME+constant.URI_ROOTPASSWORD, + constant.URI_TENANT_API_PREFIX+constant.URI_PATH_PARAM_NAME+constant.URI_VARIABLES, ), common.SetContentType, ) diff --git a/agent/api/tenant_handler.go b/agent/api/tenant_handler.go index 02352c39..36320cfb 100644 --- a/agent/api/tenant_handler.go +++ b/agent/api/tenant_handler.go @@ -435,7 +435,7 @@ 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 diff --git a/agent/executor/tenant/create_tenant.go b/agent/executor/tenant/create_tenant.go index 89f07dbc..70633bcf 100644 --- a/agent/executor/tenant/create_tenant.go +++ b/agent/executor/tenant/create_tenant.go @@ -31,6 +31,7 @@ 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" tenantservice "github.com/oceanbase/obshell/agent/service/tenant" "github.com/oceanbase/obshell/param" "github.com/oceanbase/obshell/utils" @@ -101,7 +102,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 +111,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 +203,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 +223,10 @@ func checkCreateTenantParam(param *param.CreateTenantParam) (err error) { return } + if err = checkAndLoadScenario(param, param.Scenario); err != nil { + return + } + return nil } @@ -320,7 +341,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 +353,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 +365,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(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 +398,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 +446,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 +494,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(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 +525,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/enter.go b/agent/executor/tenant/enter.go index bf83c0df..8e107ff5 100644 --- a/agent/executor/tenant/enter.go +++ b/agent/executor/tenant/enter.go @@ -34,14 +34,24 @@ var ( clusterTaskService = taskservice.NewClusterTaskService() unitService unit.UnitService agentService agent.AgentService + + // 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", + } ) 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 +84,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" @@ -136,7 +147,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/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..8d235df2 100644 --- a/agent/executor/tenant/parameter.go +++ b/agent/executor/tenant/parameter.go @@ -75,6 +75,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..5b10ec8f 100644 --- a/agent/executor/tenant/set_root_pwd.go +++ b/agent/executor/tenant/set_root_pwd.go @@ -32,7 +32,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 @@ -57,7 +57,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 } diff --git a/agent/executor/tenant/variable.go b/agent/executor/tenant/variable.go index 28b99691..a3a73e5d 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(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/service/tenant/tenant.go b/agent/service/tenant/tenant.go index 76bef2f4..016e1dac 100644 --- a/agent/service/tenant/tenant.go +++ b/agent/service/tenant/tenant.go @@ -313,6 +313,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 { 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/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/param/tenant.go b/param/tenant.go index de483ec7..2fc64f51 100644 --- a/param/tenant.go +++ b/param/tenant.go @@ -27,7 +27,7 @@ type CreateTenantParam struct { Collation string `json:"collation"` ReadOnly bool `json:"read_only"` // Default to false. Comment string `json:"comment"` // Messages. - Variables map[string]interface{} `json:"variables"` // Teantn global variables. + Variables map[string]interface{} `json:"variables"` // Tenant global variables. Parameters map[string]interface{} `json:"parameters"` // Tenant parameters. Scenario string `json:"scenario"` // Tenant scenario. ImportScript bool `json:"import_script"` // whether to import script. @@ -92,7 +92,8 @@ type SetTenantParametersParam struct { } type SetTenantVariablesParam struct { - Variables map[string]interface{} `json:"variables" binding:"required"` + Variables map[string]interface{} `json:"variables" binding:"required"` + TenantPassword string `json:"tenant_password"` } // Task Param From 9f23d2e91feed108fc5be385026e8d645ac3199e Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Mon, 3 Mar 2025 03:00:32 +0000 Subject: [PATCH 005/113] PullRequest: 354 fix agent status --- agent/service/task/status_maintainer.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/agent/service/task/status_maintainer.go b/agent/service/task/status_maintainer.go index a9d2cde5..275fabb5 100644 --- a/agent/service/task/status_maintainer.go +++ b/agent/service/task/status_maintainer.go @@ -192,12 +192,14 @@ func (maintainer *agentStatusMaintainer) setStatus(tx *gorm.DB, newStatus int, o if resp.Error != nil { return resp.Error } - if resp.RowsAffected == 0 && 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 + 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 set status to %d: agent status is not %d", newStatus, oldStatus) } From 4070e8180ffb44149587eb9dcecda25a3e72f5a4 Mon Sep 17 00:00:00 2001 From: frf12 Date: Mon, 3 Mar 2025 03:01:50 +0000 Subject: [PATCH 006/113] PullRequest: 355 feat: support ipv6 --- agent/api/agent_handler.go | 50 ++-- agent/api/common/forward_handler.go | 2 +- agent/api/obcluster_handler.go | 374 ++++++++++++------------ agent/api/zone_handler.go | 24 +- agent/cmd/server/init.go | 21 +- agent/config/oceanbase.go | 5 +- agent/config/server.go | 32 ++ agent/constant/gorm.go | 6 +- agent/engine/coordinator/coordinator.go | 4 +- agent/engine/executor/executor.go | 2 +- agent/engine/executor/task_log_sync.go | 2 +- agent/engine/scheduler/task_handler.go | 6 +- agent/engine/task/context.go | 2 +- agent/engine/task/task.go | 2 +- agent/executor/agent/follower_remove.go | 12 +- agent/executor/agent/join_follower.go | 4 +- agent/executor/ob/bootstrap.go | 6 +- agent/executor/ob/config.go | 46 +-- agent/executor/ob/convert.go | 2 +- agent/executor/ob/info.go | 27 +- agent/executor/ob/minor_freeze.go | 15 +- agent/executor/ob/scale_out.go | 34 ++- agent/executor/ob/start_obsvr.go | 18 +- agent/executor/ob/stop.go | 10 +- agent/executor/ob/stop_obsvr.go | 8 +- agent/executor/ob/update_agents.go | 2 +- agent/executor/script/script.go | 2 +- agent/executor/tenant/create_tenant.go | 13 +- agent/lib/http/http.go | 2 +- agent/meta/agent.go | 101 ++++++- agent/rpc/agent_handler.go | 12 +- agent/secure/body.go | 2 +- agent/secure/crypto.go | 6 +- agent/secure/handler.go | 2 +- agent/secure/header.go | 5 +- agent/service/agent/all_agents.go | 2 +- agent/service/agent/binary.go | 3 + agent/service/obcluster/config.go | 9 + agent/service/obcluster/obcluster.go | 28 +- agent/service/task/sub_task.go | 2 +- client/cmd/cluster/join.go | 34 +-- client/cmd/cluster/remove.go | 3 +- client/cmd/cluster/scale_in.go | 3 +- client/cmd/cluster/scale_out.go | 30 +- client/cmd/cluster/start.go | 2 +- client/cmd/cluster/stop.go | 2 +- client/cmd/cluster/take_over.go | 31 +- client/lib/http/ssh.go | 9 +- utils/address.go | 41 +++ 49 files changed, 595 insertions(+), 465 deletions(-) create mode 100644 utils/address.go diff --git a/agent/api/agent_handler.go b/agent/api/agent_handler.go index 1044ca7b..f02994cf 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 } @@ -96,18 +96,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 { diff --git a/agent/api/common/forward_handler.go b/agent/api/common/forward_handler.go index 73ce6970..d867e501 100644 --- a/agent/api/common/forward_handler.go +++ b/agent/api/common/forward_handler.go @@ -104,7 +104,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/obcluster_handler.go b/agent/api/obcluster_handler.go index e0576134..daa81f14 100644 --- a/agent/api/obcluster_handler.go +++ b/agent/api/obcluster_handler.go @@ -48,20 +48,20 @@ 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 [put] +// @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 +120,20 @@ 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 [put] +// @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 +178,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 +214,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 +247,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 +298,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 [get] func obClusterScaleOutHandler(c *gin.Context) { var param param.ClusterScaleOutParam if err := c.BindJSON(¶m); err != nil { @@ -320,19 +320,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 +359,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() @@ -392,19 +392,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 +415,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 +438,18 @@ 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 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.")) @@ -465,53 +465,53 @@ 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 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 +522,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 { diff --git a/agent/api/zone_handler.go b/agent/api/zone_handler.go index 7852884a..ea40f4f0 100644 --- a/agent/api/zone_handler.go +++ b/agent/api/zone_handler.go @@ -27,18 +27,18 @@ import ( // @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/cmd/server/init.go b/agent/cmd/server/init.go index f165e8ae..02d5a7d1 100644 --- a/agent/cmd/server/init.go +++ b/agent/cmd/server/init.go @@ -98,14 +98,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 +225,9 @@ 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, _ := config.NewServerConfig(meta.OCS_AGENT.GetIp(), meta.OCS_AGENT.GetPort(), path.RunDir(), false) 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) } diff --git a/agent/config/oceanbase.go b/agent/config/oceanbase.go index c92ca16d..a6aedb37 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, @@ -182,7 +183,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..f2a5aea7 100644 --- a/agent/config/server.go +++ b/agent/config/server.go @@ -16,6 +16,12 @@ package config +import ( + "errors" + "fmt" + "net" +) + type AgentMode = string const ( @@ -30,3 +36,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/gorm.go b/agent/constant/gorm.go index 9ef3507a..de3cd3e0 100644 --- a/agent/constant/gorm.go +++ b/agent/constant/gorm.go @@ -18,8 +18,10 @@ package constant const ( // source config default value - DB_USERNAME = "root" - LOCAL_IP = "127.0.0.1" + DB_USERNAME = "root" + LOCAL_IP = "127.0.0.1" + LOCAL_IP_V6 = "::1" + DB_DEFAILT_TIMEOUT = 10 DB_DEFAULT_CHARSET = "utf8mb4" DB_DEFAULT_LOCATION = "Local" 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/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/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..81db97f6 100644 --- a/agent/executor/agent/join_follower.go +++ b/agent/executor/agent/join_follower.go @@ -126,7 +126,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) @@ -144,7 +144,7 @@ func UpdateFollowerAgent(agentInstance meta.Agent, param param.JoinMasterParam) 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) } if err = agentService.UpdateAgent(agentInstance, param.HomePath, param.Os, param.Architecture, param.PublicKey, targetToken); err != 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/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/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/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/scale_out.go b/agent/executor/ob/scale_out.go index 76f123b7..cb5074ab 100644 --- a/agent/executor/ob/scale_out.go +++ b/agent/executor/ob/scale_out.go @@ -104,11 +104,17 @@ func HandleClusterScaleOut(param param.ClusterScaleOutParam) (*task.DagDetailDTO return nil, errors.Occur(errors.ErrUnexpected, err.Error()) } + rpcPort, err := strconv.Atoi(param.ObConfigs[constant.CONFIG_RPC_PORT]) + if err != nil { + return nil, errors.Occur(errors.ErrIllegalArgument, "rpc_port is not a number") + } + 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 @@ -1207,9 +1213,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_MYSQL_PORT]) if err != nil { - return errors.Errorf("add server %s:%s failed", agentInfo.Ip, configs[constant.CONFIG_RPC_PORT]) + 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 failed", serverInfo.String()) } t.GetContext().SetParam(PARAM_ADD_SERVER_SUCCEED, true) @@ -1248,17 +1260,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_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..a2f7d464 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,10 @@ 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]) + serverInfo, err := meta.ConvertAddressToAgentInfo(server) for _, agent := range agents { - if ip == agent.Ip && port == agent.Port { - sql := fmt.Sprintf("alter system stop server '%s:%d'", ip, agent.RpcPort) + if serverInfo.Ip == agent.Ip && serverInfo.Port == agent.Port { + 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/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/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/tenant/create_tenant.go b/agent/executor/tenant/create_tenant.go index 70633bcf..221a32f4 100644 --- a/agent/executor/tenant/create_tenant.go +++ b/agent/executor/tenant/create_tenant.go @@ -32,6 +32,7 @@ import ( "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" @@ -266,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 @@ -298,7 +301,7 @@ type gatheredUnitInfo struct { 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 { diff --git a/agent/lib/http/http.go b/agent/lib/http/http.go index bebe2f3d..1528e7f5 100644 --- a/agent/lib/http/http.go +++ b/agent/lib/http/http.go @@ -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/meta/agent.go b/agent/meta/agent.go index 2d876e97..e9cf3868 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) } @@ -199,21 +221,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 { diff --git a/agent/rpc/agent_handler.go b/agent/rpc/agent_handler.go index d67e6058..1b16cbb4 100644 --- a/agent/rpc/agent_handler.go +++ b/agent/rpc/agent_handler.go @@ -32,7 +32,7 @@ import ( func agentJoinHandler(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())) + common.SendResponse(c, nil, errors.Occurf(errors.ErrBadRequest, "%s is not master", meta.OCS_AGENT.String())) return } @@ -53,7 +53,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 +73,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 +132,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 +151,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 +228,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/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..69a6fae0 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 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..7e94cef4 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" ) @@ -50,7 +49,7 @@ func BuildHeader(agentInfo meta.AgentInfoInterface, uri string, isForword bool, headers := make(map[string]string) 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 nil } diff --git a/agent/service/agent/all_agents.go b/agent/service/agent/all_agents.go index 02d3f9e6..a40493a9 100644 --- a/agent/service/agent/all_agents.go +++ b/agent/service/agent/all_agents.go @@ -394,7 +394,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/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/obcluster.go b/agent/service/obcluster/obcluster.go index 38e412ee..287bcf5c 100644 --- a/agent/service/obcluster/obcluster.go +++ b/agent/service/obcluster/obcluster.go @@ -125,10 +125,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 } @@ -234,21 +234,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 +257,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 +266,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 +643,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") } 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/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..5134d96c 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 { 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/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/utils/address.go b/utils/address.go new file mode 100644 index 00000000..390c06e2 --- /dev/null +++ b/utils/address.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 utils + +import ( + "net" + "strconv" +) + +func IsValidIp(ip string) bool { + return net.ParseIP(ip) != nil +} + +func IsValidPort(port string) bool { + if port == "" { + return true + } + p, err := strconv.Atoi(port) + if err != nil { + return false + } + return IsValidPortValue(p) +} + +func IsValidPortValue(p int) bool { + return p > 1024 && p < 65536 +} From d96347f76577d63cbc7bccf3f2a3b24d2f4b122a Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Mon, 3 Mar 2025 04:00:34 +0000 Subject: [PATCH 007/113] PullRequest: 357 fix: bugs of sp_ipv6 --- agent/executor/ob/scale_out.go | 2 +- agent/executor/ob/stop.go | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/agent/executor/ob/scale_out.go b/agent/executor/ob/scale_out.go index cb5074ab..e9f68350 100644 --- a/agent/executor/ob/scale_out.go +++ b/agent/executor/ob/scale_out.go @@ -1213,7 +1213,7 @@ func (t *AddServerTask) Execute() error { return errors.New("get zone failed") } - port, err := strconv.Atoi(configs[constant.CONFIG_MYSQL_PORT]) + port, err := strconv.Atoi(configs[constant.CONFIG_RPC_PORT]) if err != nil { return errors.Wrap(err, "convert port to integer failed") } diff --git a/agent/executor/ob/stop.go b/agent/executor/ob/stop.go index a2f7d464..5509697c 100644 --- a/agent/executor/ob/stop.go +++ b/agent/executor/ob/stop.go @@ -237,9 +237,13 @@ func (t *ExecStopSqlTask) stopServer() (err error) { } for _, server := range t.scope.Target { t.ExecuteLogf("Stop %s", server) - serverInfo, err := meta.ConvertAddressToAgentInfo(server) + 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 serverInfo.Ip == agent.Ip && serverInfo.Port == agent.Port { + 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 { From e1dd129344e6df78a971709a1b071534f6d388dd Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Tue, 4 Mar 2025 04:00:33 +0000 Subject: [PATCH 008/113] PullRequest: 358 use default rpc_port if not set when scale out --- agent/executor/ob/scale_out.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/agent/executor/ob/scale_out.go b/agent/executor/ob/scale_out.go index e9f68350..634c0690 100644 --- a/agent/executor/ob/scale_out.go +++ b/agent/executor/ob/scale_out.go @@ -104,9 +104,15 @@ func HandleClusterScaleOut(param param.ClusterScaleOutParam) (*task.DagDetailDTO return nil, errors.Occur(errors.ErrUnexpected, err.Error()) } - rpcPort, err := strconv.Atoi(param.ObConfigs[constant.CONFIG_RPC_PORT]) - if err != nil { - return nil, errors.Occur(errors.ErrIllegalArgument, "rpc_port is not a number") + 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) From 43dd33237082054dda0d997fd46bbe637e8dace5 Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Thu, 6 Mar 2025 06:31:25 +0000 Subject: [PATCH 009/113] PullRequest: 353 sp obproxy --- agent/api/agent_handler.go | 18 +- agent/api/agent_route.go | 6 + agent/api/common/forward_handler.go | 6 +- agent/api/common/middleware.go | 274 ++++++--- agent/api/info_handler.go | 2 +- agent/api/obproxy_route.go | 162 +++++ agent/api/task_handler.go | 5 +- agent/api/tenant_handler.go | 65 ++ agent/api/zone_handler.go | 2 +- agent/assets/i18n/error/en.json | 2 +- agent/cmd/daemon/start_daemon.go | 18 +- agent/cmd/daemon/start_process.go | 2 +- agent/cmd/server/init.go | 2 + agent/cmd/server/run.go | 26 +- agent/config/oceanbase.go | 13 + agent/constant/agent.go | 3 + agent/constant/gorm.go | 8 +- agent/constant/obproxy.go | 58 ++ agent/constant/oceanbase.go | 17 +- agent/constant/secure.go | 1 + agent/constant/task.go | 10 +- agent/constant/uri.go | 11 +- agent/engine/task/dag.go | 14 + agent/engine/task/maintenance_type.go | 7 + agent/engine/task/node.go | 8 +- agent/engine/task/task_dto.go | 52 +- agent/engine/task/template.go | 6 + agent/errors/type.go | 4 + agent/executor/agent/enter.go | 1 + agent/executor/agent/join_follower.go | 53 +- agent/executor/ob/create_user.go | 63 ++ agent/executor/ob/enter.go | 7 + agent/executor/ob/init.go | 11 +- agent/executor/ob/scale_out.go | 19 +- agent/executor/ob/start.go | 4 +- agent/executor/ob/upgrade_agent_check.go | 6 +- agent/executor/ob/upgrade_ob.go | 3 +- agent/executor/ob/upgrade_ob_check.go | 14 +- agent/executor/ob/upgrade_pkg_install.go | 94 +-- agent/executor/ob/upgrade_pkg_upload.go | 14 +- agent/executor/obproxy/add.go | 570 ++++++++++++++++++ agent/executor/obproxy/delete.go | 95 +++ agent/executor/obproxy/enter.go | 128 ++++ agent/executor/obproxy/package.go | 398 ++++++++++++ agent/executor/obproxy/start.go | 41 ++ agent/executor/obproxy/stop.go | 135 +++++ agent/executor/obproxy/upgrade.go | 416 +++++++++++++ agent/executor/obproxy/upload_pkg.go | 113 ++++ agent/executor/obproxy/utils.go | 37 ++ agent/executor/task/dag.go | 17 +- agent/executor/task/node.go | 21 +- agent/executor/task/sub_task.go | 24 +- agent/executor/tenant/user.go | 123 ++++ agent/global/variable.go | 23 +- agent/lib/binary/ob.go | 6 +- agent/lib/parse/time.go | 67 ++ agent/lib/path/obproxy.go | 65 ++ agent/lib/pkg/rpm.go | 153 +++++ agent/lib/process/process.go | 101 ++++ agent/meta/agent.go | 4 +- agent/meta/obproxy.go | 28 + agent/meta/security.go | 34 +- agent/repository/db/obproxy/instance.go | 126 ++++ agent/repository/db/oceanbase/loader.go | 9 + agent/repository/db/sqlite/builder.go | 3 + agent/repository/driver/oceanbase.go | 8 + agent/repository/model/bo/obproxy_config.go | 27 + agent/repository/model/sqlite/obproxy_info.go | 23 + .../model/sqlite/upgrade_pkg_chunk.go | 24 + .../model/sqlite/upgrade_pkg_info.go | 34 ++ agent/rpc/agent_handler.go | 28 + agent/rpc/agent_route.go | 1 + agent/secure/auth.go | 67 +- agent/secure/crypto.go | 51 +- agent/secure/header.go | 28 +- agent/secure/http.go | 9 + agent/secure/service.go | 16 + agent/secure/token.go | 10 +- agent/service/agent/all_agents.go | 33 +- agent/service/agent/config.go | 24 + agent/service/agent/enter.go | 53 +- agent/service/agent/info.go | 1 + agent/service/agent/obproxy.go | 134 ++++ agent/service/obcluster/obcluster.go | 35 +- agent/service/obproxy/enter.go | 25 + agent/service/obproxy/obproxy.go | 184 ++++++ agent/service/task/convert.go | 2 +- agent/service/task/dag.go | 33 +- agent/service/task/interface.go | 2 + agent/service/task/status_maintainer.go | 29 +- agent/service/tenant/enter.go | 1 + agent/service/tenant/user.go | 51 ++ client/cmd/cluster/enter.go | 20 +- client/cmd/cluster/init.go | 14 +- client/cmd/cluster/stop.go | 2 - cmd/main.go | 21 + param/agent.go | 14 +- param/ob.go | 5 +- param/obproxy.go | 36 ++ param/tenant.go | 18 + utils/path.go | 35 ++ utils/port.go | 31 + utils/sha1.go | 30 + 103 files changed, 4586 insertions(+), 401 deletions(-) create mode 100644 agent/api/obproxy_route.go create mode 100644 agent/constant/obproxy.go create mode 100644 agent/executor/ob/create_user.go create mode 100644 agent/executor/obproxy/add.go create mode 100644 agent/executor/obproxy/delete.go create mode 100644 agent/executor/obproxy/enter.go create mode 100644 agent/executor/obproxy/package.go create mode 100644 agent/executor/obproxy/start.go create mode 100644 agent/executor/obproxy/stop.go create mode 100644 agent/executor/obproxy/upgrade.go create mode 100644 agent/executor/obproxy/upload_pkg.go create mode 100644 agent/executor/obproxy/utils.go create mode 100644 agent/executor/tenant/user.go create mode 100644 agent/lib/parse/time.go create mode 100644 agent/lib/path/obproxy.go create mode 100644 agent/lib/pkg/rpm.go create mode 100644 agent/meta/obproxy.go create mode 100644 agent/repository/db/obproxy/instance.go create mode 100644 agent/repository/model/bo/obproxy_config.go create mode 100644 agent/repository/model/sqlite/obproxy_info.go create mode 100644 agent/repository/model/sqlite/upgrade_pkg_chunk.go create mode 100644 agent/repository/model/sqlite/upgrade_pkg_info.go create mode 100644 agent/service/agent/obproxy.go create mode 100644 agent/service/obproxy/enter.go create mode 100644 agent/service/obproxy/obproxy.go create mode 100644 agent/service/tenant/user.go create mode 100644 param/obproxy.go create mode 100644 utils/port.go create mode 100644 utils/sha1.go diff --git a/agent/api/agent_handler.go b/agent/api/agent_handler.go index f02994cf..6c0d9ea0 100644 --- a/agent/api/agent_handler.go +++ b/agent/api/agent_handler.go @@ -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 { @@ -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 e834ed98..ef47bb0d 100644 --- a/agent/api/agent_route.go +++ b/agent/api/agent_route.go @@ -52,9 +52,13 @@ 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, + constant.URI_API_V1+constant.URI_INIT, constant.URI_TASK_RPC_PREFIX+constant.URI_SUB_TASK, constant.URI_API_V1+constant.URI_TENANT_GROUP, constant.URI_TENANT_API_PREFIX+constant.URI_PATH_PARAM_NAME+constant.URI_ROOTPASSWORD, + constant.URI_TENANT_API_PREFIX+constant.URI_PATH_PARAM_NAME+constant.URI_USER, + constant.URI_TENANT_API_PREFIX+constant.URI_PATH_PARAM_NAME, + constant.URI_OBPROXY_API_PREFIX, constant.URI_TENANT_API_PREFIX+constant.URI_PATH_PARAM_NAME+constant.URI_VARIABLES, ), common.SetContentType, @@ -108,6 +112,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) @@ -127,6 +132,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)) diff --git a/agent/api/common/forward_handler.go b/agent/api/common/forward_handler.go index d867e501..68aab998 100644 --- a/agent/api/common/forward_handler.go +++ b/agent/api/common/forward_handler.go @@ -44,7 +44,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 +62,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 } diff --git a/agent/api/common/middleware.go b/agent/api/common/middleware.go index 38c9210f..4b60d1f8 100644 --- a/agent/api/common/middleware.go +++ b/agent/api/common/middleware.go @@ -31,6 +31,7 @@ import ( log "github.com/sirupsen/logrus" "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" @@ -307,20 +308,30 @@ 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) for _, route := range secure.GetSkipBodyEncryptRoutes() { if route == c.Request.RequestURI { @@ -334,7 +345,7 @@ func BodyDecrypt(skipRoutes ...string) func(*gin.Context) { 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 +356,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 +366,210 @@ 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 Verify(routeType ...secure.RouteType) func(*gin.Context) { + return func(c *gin.Context) { + 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 !pass { - log.WithContext(NewContextWithTraceId(c)).Error("Security verification failed") + 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)) + 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/info_handler.go b/agent/api/info_handler.go index d7989005..a041eaaa 100644 --- a/agent/api/info_handler.go +++ b/agent/api/info_handler.go @@ -63,7 +63,7 @@ func TimeHandler(c *gin.Context) { 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) + agentStatus := meta.NewAgentStatus(meta.OCS_AGENT, global.Pid, s.GetState(), global.StartAt, global.HomePath, obVersion, meta.AGENT_PWD.Inited()) common.SendResponse(c, agentStatus, err) } } diff --git a/agent/api/obproxy_route.go b/agent/api/obproxy_route.go new file mode 100644 index 00000000..702ca827 --- /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("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/task_handler.go b/agent/api/task_handler.go index 472a7563..6570ff10 100644 --- a/agent/api/task_handler.go +++ b/agent/api/task_handler.go @@ -22,16 +22,18 @@ 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_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) @@ -39,5 +41,4 @@ func InitTaskRoutes(r *gin.RouterGroup, isLocalRoute bool) { 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.POST(constant.URI_DAG+"/:id", task.DagHandler) } diff --git a/agent/api/tenant_handler.go b/agent/api/tenant_handler.go index 36320cfb..479354db 100644 --- a/agent/api/tenant_handler.go +++ b/agent/api/tenant_handler.go @@ -53,6 +53,8 @@ func InitTenantRoutes(v1 *gin.RouterGroup, isLocalRoute bool) { 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, createUserHandler) + tenant.DELETE(constant.URI_PATH_PARAM_NAME+constant.URI_USER+constant.URI_PATH_PARAM_USER, dropUserHandler) tenants.GET(constant.URI_OVERVIEW, getTenantOverView) } @@ -587,3 +589,66 @@ func getTenantOverView(c *gin.Context) { tenants, err := tenant.GetTenantsOverView() 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 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, param)) +} + +// @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 + } + userName := c.Param(constant.URI_PARAM_USER) + if userName == "" { + 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, userName, param.RootPassword)) +} diff --git a/agent/api/zone_handler.go b/agent/api/zone_handler.go index ea40f4f0..932e2967 100644 --- a/agent/api/zone_handler.go +++ b/agent/api/zone_handler.go @@ -25,7 +25,7 @@ import ( "github.com/oceanbase/obshell/agent/meta" ) -// @ID DeleteZone +// @ID DeleteZone // // @Summary delete zone // @Description delete zone diff --git a/agent/assets/i18n/error/en.json b/agent/assets/i18n/error/en.json index 1cbbb92d..698b8128 100644 --- a/agent/assets/i18n/error/en.json +++ b/agent/assets/i18n/error/en.json @@ -10,5 +10,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/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/server/init.go b/agent/cmd/server/init.go index 02d5a7d1..245fa950 100644 --- a/agent/cmd/server/init.go +++ b/agent/cmd/server/init.go @@ -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" @@ -246,6 +247,7 @@ func (a *Agent) initTask() { recyclebin.RegisterRecyclebinTask() task.RegisterTaskType(script.ImportScriptForTenantTask{}) pool.RegisterPoolTask() + obproxy.RegisterTaskType() } // Check if the ob config file exists. 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 a6aedb37..4e25cce6 100644 --- a/agent/config/oceanbase.go +++ b/agent/config/oceanbase.go @@ -38,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 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 de3cd3e0..747c7fc6 100644 --- a/agent/constant/gorm.go +++ b/agent/constant/gorm.go @@ -18,11 +18,11 @@ package constant const ( // source config default value - DB_USERNAME = "root" - LOCAL_IP = "127.0.0.1" - LOCAL_IP_V6 = "::1" + DB_USERNAME = "root" + DB_PROXYSYS_USERNAME = "root@proxysys" + LOCAL_IP = "127.0.0.1" + LOCAL_IP_V6 = "::1" - DB_DEFAILT_TIMEOUT = 10 DB_DEFAULT_CHARSET = "utf8mb4" DB_DEFAULT_LOCATION = "Local" 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..e09c2fe7 100644 --- a/agent/constant/oceanbase.go +++ b/agent/constant/oceanbase.go @@ -28,18 +28,23 @@ 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/uri.go b/agent/constant/uri.go index 9e81baea..43480349 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,8 +42,10 @@ 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" @@ -90,6 +93,7 @@ const ( URI_PARAMETER = "/parameter" URI_OVERVIEW = "/overview" URI_TENANT = "/tenant" + URI_USER = "/user" URI_PARAM_NAME = "name" URI_PATH_PARAM_NAME = "/:" + URI_PARAM_NAME @@ -97,6 +101,8 @@ const ( 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 // Used for backup URI_ARCHIVE = "/log" @@ -112,6 +118,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/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_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/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/join_follower.go b/agent/executor/agent/join_follower.go index 81db97f6..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)) @@ -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' failed: %v", param.JoinApiParam.AgentInfo.String(), 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/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..50808afc 100644 --- a/agent/executor/ob/enter.go +++ b/agent/executor/ob/enter.go @@ -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,7 @@ const ( TASK_NAME_MIGRATE_TABLE = "Migrate table" TASK_NAME_MODIFY_PWD = "Modify password" TASK_NAME_MIGRATE_DATA = "Migrate data" + 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,6 +381,7 @@ func RegisterObInitTask() { task.RegisterTaskType(ClusterBoostrapTask{}) task.RegisterTaskType(MigrateTableTask{}) task.RegisterTaskType(ModifyPwdTask{}) + task.RegisterTaskType(CreateDefaultUserTask{}) task.RegisterTaskType(MigrateDataTask{}) task.RegisterTaskType(ConvertFollowerToClusterAgentTask{}) task.RegisterTaskType(AgentSyncTask{}) diff --git a/agent/executor/ob/init.go b/agent/executor/ob/init.go index a517f660..1338dccd 100644 --- a/agent/executor/ob/init.go +++ b/agent/executor/ob/init.go @@ -36,8 +36,15 @@ 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)) diff --git a/agent/executor/ob/scale_out.go b/agent/executor/ob/scale_out.go index 634c0690..2bbf4c56 100644 --- a/agent/executor/ob/scale_out.go +++ b/agent/executor/ob/scale_out.go @@ -169,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") @@ -245,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 } @@ -738,6 +745,7 @@ func (t *IntegrateSingleObConfigTask) Execute() error { type CreateLocalScaleOutDagTask struct { scaleCoordinateTask + targetAgentPassword string } func newCreateLocalScaleOutDagTask() *CreateLocalScaleOutDagTask { @@ -753,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 { @@ -764,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) 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/upgrade_agent_check.go b/agent/executor/ob/upgrade_agent_check.go index 7f5d4d69..d8236c4c 100644 --- a/agent/executor/ob/upgrade_agent_check.go +++ b/agent/executor/ob/upgrade_agent_check.go @@ -71,7 +71,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 +90,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 +106,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..66975384 100644 --- a/agent/executor/ob/upgrade_ob.go +++ b/agent/executor/ob/upgrade_ob.go @@ -26,6 +26,7 @@ import ( "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/meta" "github.com/oceanbase/obshell/agent/repository/model/oceanbase" "github.com/oceanbase/obshell/param" @@ -74,7 +75,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). diff --git a/agent/executor/ob/upgrade_ob_check.go b/agent/executor/ob/upgrade_ob_check.go index f37c7168..71346cc1 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,19 +133,9 @@ 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) { // Param 'targetRelease' is like '***.**.el7'. - targetBuildNumber, targetDistribution, err := splitRelease(targetRelease) + targetBuildNumber, targetDistribution, err := pkg.SplitRelease(targetRelease) if err != nil { return nil, err } 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/obproxy/add.go b/agent/executor/obproxy/add.go new file mode 100644 index 00000000..3413bd31 --- /dev/null +++ b/agent/executor/obproxy/add.go @@ -0,0 +1,570 @@ +/* + * 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.SetCanRetry().SetCanContinue() + 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 + version string + encryptedSysPwd string + encryptedProxyroPassword string +} + +func newPersistObproxyInfoTask() *PersistObproxyInfoTask { + newTask := &PersistObproxyInfoTask{ + Task: *task.NewSubTask(TASK_PERSIST_OBPROXY_INFP), + } + newTask.SetCanRetry().SetCanContinue() + 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_VERSION, &t.version); 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.version, 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.SetCanRetry().SetCanContinue() + + 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.SetCanRetry().SetCanContinue() + 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..1b3c0868 --- /dev/null +++ b/agent/executor/obproxy/delete.go @@ -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. + */ + +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.SetCanRetry().SetCanContinue().SetCanCancel() + 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.SetCanRetry().SetCanContinue().SetCanCancel() + 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..7aa06e15 --- /dev/null +++ b/agent/executor/obproxy/stop.go @@ -0,0 +1,135 @@ +/* + * 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.SetCanRetry().SetCanContinue() + 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..1c6a3ad7 --- /dev/null +++ b/agent/executor/obproxy/upgrade.go @@ -0,0 +1,416 @@ +/* + * 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() + 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().SetCanCancel() + 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() + 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().SetCanCancel() + 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/task/dag.go b/agent/executor/task/dag.go index fd5e33c8..037f9758 100644 --- a/agent/executor/task/dag.go +++ b/agent/executor/task/dag.go @@ -67,6 +67,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,6 +116,10 @@ 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) } @@ -167,7 +174,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 } @@ -215,6 +222,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 +251,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) 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..cc99ee52 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,8 +112,8 @@ 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()) } diff --git a/agent/executor/tenant/user.go b/agent/executor/tenant/user.go new file mode 100644 index 00000000..8c80e831 --- /dev/null +++ b/agent/executor/tenant/user.go @@ -0,0 +1,123 @@ +/* + * 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 ( + "github.com/oceanbase/obshell/agent/constant" + "github.com/oceanbase/obshell/agent/errors" + "github.com/oceanbase/obshell/agent/repository/db/oceanbase" + "github.com/oceanbase/obshell/param" + "gorm.io/gorm" +) + +func CreateUser(tenantName string, param param.CreateUserParam) *errors.OcsAgentError { + if exist, err := tenantService.IsTenantExist(tenantName); err != nil { + return errors.Occurf(errors.ErrUnexpected, "check tenant '%s' exist failed", tenantName) + } else if !exist { + return errors.Occurf(errors.ErrBadRequest, "Tenant '%s' not exists.", tenantName) + } + + var db *gorm.DB + var err error + if tenantName == constant.TENANT_SYS { + db, err = oceanbase.GetInstance() + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "get oceanbase instance failed") + } + } else { + defer func() { + if db != nil { + tempDb, _ := db.DB() + if tempDb != nil { + tempDb.Close() + } + } + }() + db, err = oceanbase.LoadGormWithTenant(tenantName, param.RootPassword) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "load gorm with tenant '%s' failed", tenantName) + } + } + + 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.GrantGlobalPrivileges(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.GrantDbPrivileges(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, rootPassword string) *errors.OcsAgentError { + if exist, err := tenantService.IsTenantExist(tenantName); err != nil { + return errors.Occurf(errors.ErrUnexpected, "check tenant '%s' exist failed", tenantName) + } else if !exist { + return errors.Occurf(errors.ErrBadRequest, "Tenant '%s' not exists.", tenantName) + } + + var db *gorm.DB + var err error + if tenantName == constant.TENANT_SYS { + db, err = oceanbase.GetInstance() + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "get oceanbase instance failed") + } + } else { + defer func() { + if db != nil { + tempDb, _ := db.DB() + if tempDb != nil { + tempDb.Close() + } + } + }() + db, err = oceanbase.LoadGormWithTenant(tenantName, rootPassword) + if err != nil { + return errors.Occurf(errors.ErrUnexpected, "load gorm with tenant '%s' failed", tenantName) + } + } + + // 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 +} 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..39cfe3cf 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" @@ -30,9 +31,12 @@ import ( func GetMyOBVersion() (version string, 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 "", 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 "", err } res := string(out) 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..faac14be 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" @@ -81,6 +82,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 +162,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 { @@ -208,3 +247,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 e9cf3868..d37bea51 100644 --- a/agent/meta/agent.go +++ b/agent/meta/agent.go @@ -155,6 +155,7 @@ type AgentStatus struct { HomePath string `json:"homePath"` OBVersion string `json:"obVersion"` AgentInstance + Security bool `json:"security"` SupportedAuth []string `json:"supportedAuth"` } @@ -383,13 +384,14 @@ 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) *AgentStatus { return &AgentStatus{ Pid: pid, State: state, StartAt: startAt, HomePath: homePath, OBVersion: obVersion, + Security: isAgentPasswordSet, 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..ed5d7974 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,15 @@ func GetOceanbasePwd() string { func SetOceanbasePwd(pwd string) { OCEANBASE_PWD = pwd + if !OCEANBASE_PASSWORD_INITIALIZED { + OCEANBASE_PASSWORD_INITIALIZED = true + } +} + +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/loader.go b/agent/repository/db/oceanbase/loader.go index 2a96ecbc..a54228e8 100644 --- a/agent/repository/db/oceanbase/loader.go +++ b/agent/repository/db/oceanbase/loader.go @@ -281,3 +281,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..4af7137b 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. 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/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/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 1b16cbb4..264cc71f 100644 --- a/agent/rpc/agent_handler.go +++ b/agent/rpc/agent_handler.go @@ -30,6 +30,34 @@ import ( "github.com/oceanbase/obshell/param" ) +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())) 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..6069cc1f 100644 --- a/agent/secure/auth.go +++ b/agent/secure/auth.go @@ -18,46 +18,71 @@ 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() { + log.Infof("agent password is incorrect, pwd:%v, agentPwd:%v", 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/crypto.go b/agent/secure/crypto.go index 69a6fae0..53907f77 100644 --- a/agent/secure/crypto.go +++ b/agent/secure/crypto.go @@ -113,12 +113,12 @@ 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 @@ -129,11 +129,33 @@ func LoadPassword(password *string) error { // 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/header.go b/agent/secure/header.go index 7e94cef4..94aaa296 100644 --- a/agent/secure/header.go +++ b/agent/secure/header.go @@ -45,12 +45,27 @@ type HttpHeader struct { 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'", agentInfo.String()) - return nil + return "" } var token string @@ -67,7 +82,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, @@ -82,15 +97,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..e7c632fc 100644 --- a/agent/secure/http.go +++ b/agent/secure/http.go @@ -144,3 +144,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 a40493a9..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 { 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..fba2c2d2 100644 --- a/agent/service/agent/info.go +++ b/agent/service/agent/info.go @@ -308,6 +308,7 @@ func (s *AgentService) BeScalingOutAgent(zone string) error { }) } + func (s *AgentService) SyncAgentData() (err error) { oceanbaseDb, err := oceanbasedb.GetOcsInstance() if err != nil { diff --git a/agent/service/agent/obproxy.go b/agent/service/agent/obproxy.go new file mode 100644 index 00000000..db355104 --- /dev/null +++ b/agent/service/agent/obproxy.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 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, version, 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) + infos[constant.OBPROXY_INFO_VERSION] = version + + 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/obcluster.go b/agent/service/obcluster/obcluster.go index 287bcf5c..15e1756b 100644 --- a/agent/service/obcluster/obcluster.go +++ b/agent/service/obcluster/obcluster.go @@ -737,7 +737,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 +746,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 +755,34 @@ 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 +} 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..89bc541e 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. diff --git a/agent/service/task/dag.go b/agent/service/task/dag.go index db1eeb04..1894b9ab 100644 --- a/agent/service/task/dag.go +++ b/agent/service/task/dag.go @@ -56,7 +56,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 +65,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 +79,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 +140,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 +249,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..4e422f11 100644 --- a/agent/service/task/interface.go +++ b/agent/service/task/interface.go @@ -102,6 +102,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) diff --git a/agent/service/task/status_maintainer.go b/agent/service/task/status_maintainer.go index 275fabb5..add6e262 100644 --- a/agent/service/task/status_maintainer.go +++ b/agent/service/task/status_maintainer.go @@ -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,9 +188,17 @@ 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)) - if resp.Error != nil { - return resp.Error + var resp *gorm.DB + if newStatus == task.OBPROXY_MAINTENACE { + 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 + } + } else { + resp = tx.Model(&sqlite.OcsInfo{}).Where("name=? and value=?", constant.OCS_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 { @@ -210,7 +218,7 @@ 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) + return maintainer.setStatus(tx, dag.GetMaintenanceType(), task.NOT_UNDER_MAINTENANCE) } func (maintainer *agentStatusMaintainer) UpdateMaintenanceTask(tx *gorm.DB, dag *task.Dag) error { @@ -218,7 +226,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.setStatus(tx, task.NOT_UNDER_MAINTENANCE, task.OBPROXY_MAINTENACE) + default: + return nil + } } func (maintainer *agentStatusMaintainer) IsRunning() (bool, error) { diff --git a/agent/service/tenant/enter.go b/agent/service/tenant/enter.go index 5dc9fef4..73d2db64 100644 --- a/agent/service/tenant/enter.go +++ b/agent/service/tenant/enter.go @@ -28,6 +28,7 @@ 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" CDB_OB_SYS_VARIABLES = "oceanbase.CDB_OB_SYS_VARIABLES" CDB_OB_ARCHIVELOG = "oceanbase.CDB_OB_ARCHIVELOG" diff --git a/agent/service/tenant/user.go b/agent/service/tenant/user.go new file mode 100644 index 00000000..ab2ffd5a --- /dev/null +++ b/agent/service/tenant/user.go @@ -0,0 +1,51 @@ +/* + * 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/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) GrantGlobalPrivileges(db *gorm.DB, userName, hostName string, privilege []string) error { + sql := fmt.Sprintf("GRANT %s ON *.* TO `%s`@`%s`", strings.Join(privilege, ","), userName, hostName) + return db.Exec(sql).Error +} + +func (t *TenantService) GrantDbPrivileges(db *gorm.DB, userName, hostName string, privilege param.DbPrivilegeParam) error { + sql := fmt.Sprintf("GRANT %s ON `%s`.* TO `%s`@`%s`", strings.Join(privilege.Privileges, ","), privilege.DbName, userName, hostName) + return db.Exec(sql).Error +} + +func (t *TenantService) DropUser(db *gorm.DB, userName string) error { + sql := fmt.Sprintf("DROP USER `%s`", userName) + return db.Exec(sql).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/stop.go b/client/cmd/cluster/stop.go index 5134d96c..c9ae302f 100644 --- a/client/cmd/cluster/stop.go +++ b/client/cmd/cluster/stop.go @@ -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/cmd/main.go b/cmd/main.go index 4359bc91..a9708811 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -18,7 +18,9 @@ package main import ( "os" + "os/signal" "runtime" + "syscall" "github.com/spf13/cobra" @@ -37,6 +39,7 @@ import ( "github.com/oceanbase/obshell/client/cmd/tenant" "github.com/oceanbase/obshell/client/cmd/unit" "github.com/oceanbase/obshell/client/command" + "github.com/oceanbase/obshell/client/lib/stdio" ) func main() { @@ -71,6 +74,12 @@ func main() { } agentcmd.PreHandler() + + defer func() { + stdio.LoadFailedWithoutMsg() + }() + go gracefulTermination() + if err := cmds.Execute(); err != nil { os.Exit(-1) } @@ -88,3 +97,15 @@ func newCmd() *cobra.Command { cmd.SetHelpCommand(&cobra.Command{Hidden: true}) return cmd.Command } + +func gracefulTermination() { + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + sig := <-sigs + stdio.StopLoading() + if sig == syscall.SIGINT { + os.Exit(130) + } else { + os.Exit(143) + } +} diff --git a/param/agent.go b/param/agent.go index 0e08cfaf..89293d79 100644 --- a/param/agent.go +++ b/param/agent.go @@ -24,8 +24,9 @@ import ( ) type JoinApiParam struct { - AgentInfo meta.AgentInfo `json:"agentInfo" binding:"required"` - ZoneName string `json:"zoneName" binding:"required"` + AgentInfo meta.AgentInfo `json:"agentInfo" binding:"required"` + ZoneName string `json:"zoneName" binding:"required"` + MasterPassword string `json:"masterPassword"` } type JoinMasterParam struct { @@ -43,3 +44,12 @@ type AllAgentsSyncData struct { AllAgents []oceanbase.AllAgent `json:"all_agents" binding:"required"` LastSyncTime time.Time `json:"last_sync_time" binding:"required"` } + +type SetAgentPasswordParam struct { + Password string `json:"password" binding:"required"` +} + +type AddTokenParam struct { + AgentInfo meta.AgentInfo `json:"agentInfo" binding:"required"` + Token string `json:"token" binding:"required"` +} diff --git a/param/ob.go b/param/ob.go index 14593465..42f6b192 100644 --- a/param/ob.go +++ b/param/ob.go @@ -53,6 +53,7 @@ type ScaleOutParam struct { type ClusterScaleOutParam struct { ScaleOutParam + TargetAgentPassword string `json:"targetAgentPassword"` } type LocalScaleOutParam struct { @@ -74,7 +75,9 @@ type ClusterScaleInParam struct { } type ObInitParam struct { - ImportScript bool `json:"import_script"` + ImportScript bool `json:"import_script"` + CreateProxyroUser bool `json:"create_proxyro_user"` + ProxyroPassword string `json:"proxyro_password"` } type ObStopParam struct { diff --git a/param/obproxy.go b/param/obproxy.go new file mode 100644 index 00000000..9f7eeb86 --- /dev/null +++ b/param/obproxy.go @@ -0,0 +1,36 @@ +/* + * 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 param + +type AddObproxyParam struct { + Name string `json:"name"` + HomePath string `json:"home_path" binding:"required"` + SqlPort *int `json:"sql_port"` // Default to 2883. + RpcPort *int `json:"rpc_port"` // Default to 2884. + ExporterPort *int `json:"exporter_port"` // Default to 2885. + ProxyroPassword string `json:"proxyro_password"` + ObproxySysPassword string `json:"obproxy_sys_password"` + RsList *string `json:"rs_list"` + ConfigUrl *string `json:"config_url"` + Parameters map[string]string `json:"parameters"` +} + +type UpgradeObproxyParam struct { + Version string `json:"version" binding:"required"` + Release string `json:"release" binding:"required"` + UpgradeDir string `json:"upgrade_dir"` +} diff --git a/param/tenant.go b/param/tenant.go index 2fc64f51..2972d705 100644 --- a/param/tenant.go +++ b/param/tenant.go @@ -103,3 +103,21 @@ type CreateResourcePoolTaskParam struct { UnitConfigName string UnitNum int } + +type CreateUserParam struct { + UserName string `json:"user_name" binding:"required"` + Password string `json:"password" binding:"required"` + RootPassword string `json:"root_password"` + GlobalPrivileges []string `json:"global_privileges"` + DbPrivileges []DbPrivilegeParam `json:"db_privileges"` + HostName string `json:"host_name"` +} + +type DbPrivilegeParam struct { + DbName string `json:"db_name" binding:"required"` + Privileges []string `json:"privileges" binding:"required"` +} + +type DropUserParam struct { + RootPassword string `json:"root_password"` +} diff --git a/utils/path.go b/utils/path.go index f1e16420..7d85d5e3 100644 --- a/utils/path.go +++ b/utils/path.go @@ -18,6 +18,7 @@ package utils import ( "fmt" + "io" "os" "path/filepath" "regexp" @@ -67,3 +68,37 @@ func CheckPathExistAndValid(path string) error { } return CheckPathValid(path) } + +// CheckDirExists checks if the provided filesystem path exists and is a dir. +// It returns an error if the path does not exist or if the path is not a dir. +func CheckDirExists(dir string) error { + fileInfo, err := os.Stat(dir) + if err != nil { + if os.IsNotExist(err) { + return err + } + return errors.Wrapf(err, "failed to stat path %s", dir) + } + + if !fileInfo.IsDir() { + return errors.Errorf("path '%s' is not a directory", dir) + } + return nil +} + +func CheckDirEmpty(path string) error { + dir, err := os.Open(path) + if err != nil { + return errors.Wrapf(err, "failed to open directory %s", path) + } + defer dir.Close() + + _, err = dir.Readdir(1) + if err == io.EOF { + return nil // Directory is empty + } + if err != nil { + return errors.Wrapf(err, "failed to read directory %s", path) + } + return errors.Errorf("directory '%s' is not empty", path) +} diff --git a/utils/port.go b/utils/port.go new file mode 100644 index 00000000..40817c72 --- /dev/null +++ b/utils/port.go @@ -0,0 +1,31 @@ +/* + * 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 utils + +import ( + "fmt" + "net" +) + +func IsPortFree(port int) (bool, error) { + ln, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) + if err != nil { + return false, nil + } + ln.Close() + return true, nil +} diff --git a/utils/sha1.go b/utils/sha1.go new file mode 100644 index 00000000..fa52d43a --- /dev/null +++ b/utils/sha1.go @@ -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. + */ + +package utils + +import ( + "crypto/sha1" + "encoding/hex" +) + +func Sha1(input string) string { + hasher := sha1.New() + hasher.Write([]byte(input)) + hashBytes := hasher.Sum(nil) + hashString := hex.EncodeToString(hashBytes) + return hashString +} From cd4f61b73fd8b5c018c7c15bbb5ba1f6eb6480af Mon Sep 17 00:00:00 2001 From: chris-sun-star Date: Tue, 25 Mar 2025 09:35:42 +0000 Subject: [PATCH 010/113] fix openapi definitions errors --- agent/api/agent_route.go | 2 - agent/api/obcluster_handler.go | 2 - agent/api/tenant_handler.go | 18 +++++ agent/executor/task/dag.go | 140 ++++++++++++++++----------------- 4 files changed, 88 insertions(+), 74 deletions(-) diff --git a/agent/api/agent_route.go b/agent/api/agent_route.go index ef47bb0d..77f44378 100644 --- a/agent/api/agent_route.go +++ b/agent/api/agent_route.go @@ -139,11 +139,9 @@ 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)) // observer routes observer.PUT(constant.URI_CONFIG, obServerConfigHandler(true)) - observer.POST(constant.URI_CONFIG, obServerConfigHandler(true)) observer.DELETE("", obClusterScaleInHandler) // zone routes diff --git a/agent/api/obcluster_handler.go b/agent/api/obcluster_handler.go index daa81f14..1c27a96d 100644 --- a/agent/api/obcluster_handler.go +++ b/agent/api/obcluster_handler.go @@ -61,7 +61,6 @@ func parseRootPwd(pwd string, isForward bool) (string, error) { // @Failure 400 object http.OcsAgentResponse // @Failure 500 object http.OcsAgentResponse // @Router /api/v1/obcluster/config [put] -// @Router /api/v1/obcluster/config [post] func obclusterConfigHandler(deleteAll bool) func(c *gin.Context) { return func(c *gin.Context) { var params param.ObClusterConfigParams @@ -133,7 +132,6 @@ func obclusterConfigHandler(deleteAll bool) func(c *gin.Context) { // @Failure 401 object http.OcsAgentResponse // @Failure 500 object http.OcsAgentResponse // @Router /api/v1/observer/config [put] -// @Router /api/v1/observer/config [post] func obServerConfigHandler(deleteAll bool) func(c *gin.Context) { return func(c *gin.Context) { var params param.ObServerConfigParams diff --git a/agent/api/tenant_handler.go b/agent/api/tenant_handler.go index 479354db..85b1b4e7 100644 --- a/agent/api/tenant_handler.go +++ b/agent/api/tenant_handler.go @@ -109,6 +109,7 @@ func tenantCheckWithName(c *gin.Context) (string, error) { // @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 @@ -141,6 +142,7 @@ func tenantDropHandler(c *gin.Context) { // @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 @@ -169,6 +171,7 @@ func tenantRenameHandler(c *gin.Context) { // @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 @@ -190,6 +193,7 @@ func tenantLockHandler(c *gin.Context) { // @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 @@ -211,6 +215,7 @@ func tenantUnlockHandler(c *gin.Context) { // @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 @@ -239,6 +244,7 @@ func tenantAddReplicasHandler(c *gin.Context) { // @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 @@ -270,6 +276,7 @@ func tenantRemoveReplicasHandler(c *gin.Context) { // @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 @@ -302,6 +309,7 @@ func tenantModifyReplicasHandler(c *gin.Context) { // @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 @@ -334,6 +342,7 @@ func tenantModifyWhitelistHandler(c *gin.Context) { // @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 @@ -365,6 +374,7 @@ func tenantModifyPasswordHandler(c *gin.Context) { // @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 @@ -393,6 +403,7 @@ func tenantModifyPrimaryZoneHandler(c *gin.Context) { // @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 @@ -420,6 +431,7 @@ func tenantSetParametersHandler(c *gin.Context) { // @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 @@ -447,6 +459,7 @@ func tenantSetVariableHandler(c *gin.Context) { // @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 @@ -469,6 +482,7 @@ func getTenantInfo(c *gin.Context) { // @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 @@ -499,6 +513,7 @@ func getTenantParameter(c *gin.Context) { // @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 @@ -523,6 +538,7 @@ func getTenantParameters(c *gin.Context) { // @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 @@ -553,6 +569,7 @@ func getTenantVariable(c *gin.Context) { // @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 @@ -597,6 +614,7 @@ func getTenantOverView(c *gin.Context) { // @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 diff --git a/agent/executor/task/dag.go b/agent/executor/task/dag.go index 037f9758..3279f6b1 100644 --- a/agent/executor/task/dag.go +++ b/agent/executor/task/dag.go @@ -193,9 +193,9 @@ func convertDagDetailDTO(dag *task.Dag, fillDeatil bool) (dagDetailDTO *task.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"}) +// @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 @@ -276,17 +276,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() @@ -303,17 +303,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() { @@ -341,17 +341,17 @@ 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) { param := getTaskQueryParams(c) dagDetailDTOs := make([]*task.DagDetailDTO, 0) @@ -384,17 +384,17 @@ func GetAllAgentLastMaintenanceDag(c *gin.Context) { common.SendResponse(c, dagDetailDTOs, nil) } -// @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() { @@ -424,18 +424,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")) @@ -447,17 +447,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) From 6d7c936cdcd260a68bdef49af6137e0251b2e9ed Mon Sep 17 00:00:00 2001 From: chris-sun-star Date: Tue, 25 Mar 2025 09:43:50 +0000 Subject: [PATCH 011/113] keep post method to match existing sdk code --- agent/api/agent_route.go | 4 ++-- agent/api/obcluster_handler.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/agent/api/agent_route.go b/agent/api/agent_route.go index 77f44378..83ac5ff3 100644 --- a/agent/api/agent_route.go +++ b/agent/api/agent_route.go @@ -138,10 +138,10 @@ func InitOcsAgentRoutes(s *http2.State, r *gin.Engine, isLocalRoute bool) { agents.GET(constant.URI_STATUS, GetAllAgentStatus(s)) // obcluster routes - obcluster.PUT(constant.URI_CONFIG, obclusterConfigHandler(true)) + obcluster.POST(constant.URI_CONFIG, obclusterConfigHandler(true)) // observer routes - observer.PUT(constant.URI_CONFIG, obServerConfigHandler(true)) + observer.POST(constant.URI_CONFIG, obServerConfigHandler(true)) observer.DELETE("", obClusterScaleInHandler) // zone routes diff --git a/agent/api/obcluster_handler.go b/agent/api/obcluster_handler.go index 1c27a96d..0e20b0de 100644 --- a/agent/api/obcluster_handler.go +++ b/agent/api/obcluster_handler.go @@ -60,7 +60,7 @@ func parseRootPwd(pwd string, isForward bool) (string, error) { // @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] func obclusterConfigHandler(deleteAll bool) func(c *gin.Context) { return func(c *gin.Context) { var params param.ObClusterConfigParams @@ -131,7 +131,7 @@ func obclusterConfigHandler(deleteAll bool) func(c *gin.Context) { // @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] func obServerConfigHandler(deleteAll bool) func(c *gin.Context) { return func(c *gin.Context) { var params param.ObServerConfigParams From c5f09c86a2ae63bfcf6eccccc7fc98b48a41c101 Mon Sep 17 00:00:00 2001 From: chris-sun-star Date: Tue, 25 Mar 2025 09:59:40 +0000 Subject: [PATCH 012/113] change wrong method for scale out --- agent/api/obcluster_handler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent/api/obcluster_handler.go b/agent/api/obcluster_handler.go index 0e20b0de..2e97ad9d 100644 --- a/agent/api/obcluster_handler.go +++ b/agent/api/obcluster_handler.go @@ -307,7 +307,7 @@ func obStartHandler(c *gin.Context) { // @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] +// @Router /api/v1/ob/scale_out [POST] func obClusterScaleOutHandler(c *gin.Context) { var param param.ClusterScaleOutParam if err := c.BindJSON(¶m); err != nil { From 0e4e29365d2f6d09617ad9594b5e9eb16be98ea8 Mon Sep 17 00:00:00 2001 From: chris-sun-star Date: Thu, 27 Mar 2025 02:45:42 +0000 Subject: [PATCH 013/113] add config put method back --- agent/api/agent_route.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/agent/api/agent_route.go b/agent/api/agent_route.go index 83ac5ff3..ef47bb0d 100644 --- a/agent/api/agent_route.go +++ b/agent/api/agent_route.go @@ -138,9 +138,11 @@ func InitOcsAgentRoutes(s *http2.State, r *gin.Engine, isLocalRoute bool) { agents.GET(constant.URI_STATUS, GetAllAgentStatus(s)) // obcluster routes + obcluster.PUT(constant.URI_CONFIG, obclusterConfigHandler(true)) obcluster.POST(constant.URI_CONFIG, obclusterConfigHandler(true)) // observer routes + observer.PUT(constant.URI_CONFIG, obServerConfigHandler(true)) observer.POST(constant.URI_CONFIG, obServerConfigHandler(true)) observer.DELETE("", obClusterScaleInHandler) From 6783191e29d31f205fbce5c6d9f845eb100493f4 Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Thu, 10 Apr 2025 07:32:11 +0000 Subject: [PATCH 014/113] PullRequest: 360 fix: panic when start agent with invalid ipv6 address --- agent/api/obcluster_handler.go | 8 +- agent/api/tenant_handler.go | 18 ----- agent/cmd/server/init.go | 5 +- agent/executor/task/dag.go | 140 ++++++++++++++++----------------- 4 files changed, 79 insertions(+), 92 deletions(-) diff --git a/agent/api/obcluster_handler.go b/agent/api/obcluster_handler.go index 2e97ad9d..daa81f14 100644 --- a/agent/api/obcluster_handler.go +++ b/agent/api/obcluster_handler.go @@ -60,7 +60,8 @@ func parseRootPwd(pwd string, isForward bool) (string, error) { // @Failure 401 object http.OcsAgentResponse // @Failure 400 object http.OcsAgentResponse // @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/obcluster/config [POST] +// @Router /api/v1/obcluster/config [put] +// @Router /api/v1/obcluster/config [post] func obclusterConfigHandler(deleteAll bool) func(c *gin.Context) { return func(c *gin.Context) { var params param.ObClusterConfigParams @@ -131,7 +132,8 @@ func obclusterConfigHandler(deleteAll bool) func(c *gin.Context) { // @Failure 400 object http.OcsAgentResponse // @Failure 401 object http.OcsAgentResponse // @Failure 500 object http.OcsAgentResponse -// @Router /api/v1/observer/config [POST] +// @Router /api/v1/observer/config [put] +// @Router /api/v1/observer/config [post] func obServerConfigHandler(deleteAll bool) func(c *gin.Context) { return func(c *gin.Context) { var params param.ObServerConfigParams @@ -307,7 +309,7 @@ func obStartHandler(c *gin.Context) { // @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] +// @Router /api/v1/ob/scale_out [get] func obClusterScaleOutHandler(c *gin.Context) { var param param.ClusterScaleOutParam if err := c.BindJSON(¶m); err != nil { diff --git a/agent/api/tenant_handler.go b/agent/api/tenant_handler.go index 85b1b4e7..479354db 100644 --- a/agent/api/tenant_handler.go +++ b/agent/api/tenant_handler.go @@ -109,7 +109,6 @@ func tenantCheckWithName(c *gin.Context) (string, error) { // @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 @@ -142,7 +141,6 @@ func tenantDropHandler(c *gin.Context) { // @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 @@ -171,7 +169,6 @@ func tenantRenameHandler(c *gin.Context) { // @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 @@ -193,7 +190,6 @@ func tenantLockHandler(c *gin.Context) { // @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 @@ -215,7 +211,6 @@ func tenantUnlockHandler(c *gin.Context) { // @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 @@ -244,7 +239,6 @@ func tenantAddReplicasHandler(c *gin.Context) { // @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 @@ -276,7 +270,6 @@ func tenantRemoveReplicasHandler(c *gin.Context) { // @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 @@ -309,7 +302,6 @@ func tenantModifyReplicasHandler(c *gin.Context) { // @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 @@ -342,7 +334,6 @@ func tenantModifyWhitelistHandler(c *gin.Context) { // @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 @@ -374,7 +365,6 @@ func tenantModifyPasswordHandler(c *gin.Context) { // @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 @@ -403,7 +393,6 @@ func tenantModifyPrimaryZoneHandler(c *gin.Context) { // @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 @@ -431,7 +420,6 @@ func tenantSetParametersHandler(c *gin.Context) { // @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 @@ -459,7 +447,6 @@ func tenantSetVariableHandler(c *gin.Context) { // @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 @@ -482,7 +469,6 @@ func getTenantInfo(c *gin.Context) { // @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 @@ -513,7 +499,6 @@ func getTenantParameter(c *gin.Context) { // @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 @@ -538,7 +523,6 @@ func getTenantParameters(c *gin.Context) { // @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 @@ -569,7 +553,6 @@ func getTenantVariable(c *gin.Context) { // @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 @@ -614,7 +597,6 @@ func getTenantOverView(c *gin.Context) { // @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 diff --git a/agent/cmd/server/init.go b/agent/cmd/server/init.go index 245fa950..9249d73d 100644 --- a/agent/cmd/server/init.go +++ b/agent/cmd/server/init.go @@ -226,7 +226,10 @@ 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.NewServerConfig(meta.OCS_AGENT.GetIp(), meta.OCS_AGENT.GetPort(), path.RunDir(), false) + 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.startChan = make(chan bool, 1) diff --git a/agent/executor/task/dag.go b/agent/executor/task/dag.go index 3279f6b1..037f9758 100644 --- a/agent/executor/task/dag.go +++ b/agent/executor/task/dag.go @@ -193,9 +193,9 @@ func convertDagDetailDTO(dag *task.Dag, fillDeatil bool) (dagDetailDTO *task.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)" +// @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 @@ -276,17 +276,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() @@ -303,17 +303,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() { @@ -341,17 +341,17 @@ 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) { param := getTaskQueryParams(c) dagDetailDTOs := make([]*task.DagDetailDTO, 0) @@ -384,17 +384,17 @@ func GetAllAgentLastMaintenanceDag(c *gin.Context) { common.SendResponse(c, dagDetailDTOs, nil) } -// @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() { @@ -424,18 +424,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")) @@ -447,17 +447,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) From d4e1d2ed7d0b343d590d08a875abb5702951f924 Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Thu, 10 Apr 2025 07:32:24 +0000 Subject: [PATCH 015/113] PullRequest: 362 fix: hung when restart agent --- cmd/main.go | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index a9708811..341962c8 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -18,9 +18,7 @@ package main import ( "os" - "os/signal" "runtime" - "syscall" "github.com/spf13/cobra" @@ -39,7 +37,6 @@ import ( "github.com/oceanbase/obshell/client/cmd/tenant" "github.com/oceanbase/obshell/client/cmd/unit" "github.com/oceanbase/obshell/client/command" - "github.com/oceanbase/obshell/client/lib/stdio" ) func main() { @@ -75,11 +72,6 @@ func main() { agentcmd.PreHandler() - defer func() { - stdio.LoadFailedWithoutMsg() - }() - go gracefulTermination() - if err := cmds.Execute(); err != nil { os.Exit(-1) } @@ -97,15 +89,3 @@ func newCmd() *cobra.Command { cmd.SetHelpCommand(&cobra.Command{Hidden: true}) return cmd.Command } - -func gracefulTermination() { - sigs := make(chan os.Signal, 1) - signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) - sig := <-sigs - stdio.StopLoading() - if sig == syscall.SIGINT { - os.Exit(130) - } else { - os.Exit(143) - } -} From ff1fb9d5fbac9e0b4afcc2cbcde4252834e894a5 Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Thu, 10 Apr 2025 07:32:38 +0000 Subject: [PATCH 016/113] PullRequest: 361 fix the maintenance of obproxy --- agent/repository/model/sqlite/dag_instance.go | 6 ++- agent/service/task/status_maintainer.go | 42 +++++++++++++------ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/agent/repository/model/sqlite/dag_instance.go b/agent/repository/model/sqlite/dag_instance.go index 1af8443f..dccd7906 100644 --- a/agent/repository/model/sqlite/dag_instance.go +++ b/agent/repository/model/sqlite/dag_instance.go @@ -45,7 +45,11 @@ type DagInstance struct { func (d *DagInstance) ToBO() *bo.DagInstance { MaintenanceType := task.NOT_UNDER_MAINTENANCE if d.IsMaintenance { - MaintenanceType = task.GLOBAL_MAINTENANCE + 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/service/task/status_maintainer.go b/agent/service/task/status_maintainer.go index add6e262..f24da8e5 100644 --- a/agent/service/task/status_maintainer.go +++ b/agent/service/task/status_maintainer.go @@ -188,17 +188,28 @@ type agentStatusMaintainer struct { } func (maintainer *agentStatusMaintainer) setStatus(tx *gorm.DB, newStatus int, oldStatus int) error { - var resp *gorm.DB - if newStatus == task.OBPROXY_MAINTENACE { - 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 - } - } else { - resp = tx.Model(&sqlite.OcsInfo{}).Where("name=? and value=?", constant.OCS_INFO_STATUS, oldStatus).Update("value", strconv.Itoa(newStatus)) - if resp.Error != nil { - return resp.Error + 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 { + 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 set status to %d: agent status is not %d", newStatus, oldStatus) + } + 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 { @@ -218,7 +229,14 @@ func (maintainer *agentStatusMaintainer) StartMaintenance(tx *gorm.DB, dag task. if !dag.IsMaintenance() { return nil } - return maintainer.setStatus(tx, dag.GetMaintenanceType(), 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 { @@ -230,7 +248,7 @@ func (maintainer *agentStatusMaintainer) StopMaintenance(tx *gorm.DB, dag task.M case task.GLOBAL_MAINTENANCE: return maintainer.setStatus(tx, task.NOT_UNDER_MAINTENANCE, task.GLOBAL_MAINTENANCE) case task.OBPROXY_MAINTENACE: - return maintainer.setStatus(tx, task.NOT_UNDER_MAINTENANCE, task.OBPROXY_MAINTENACE) + return maintainer.setObproxyStatus(tx, task.NOT_UNDER_MAINTENANCE, task.OBPROXY_MAINTENACE) default: return nil } From e11001a5e24b2e8a3be1b43062452969e76a2153 Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Thu, 10 Apr 2025 07:32:53 +0000 Subject: [PATCH 017/113] PullRequest: 364 mask password --- agent/api/agent_route.go | 20 +++++++++++++++++++- agent/api/obproxy_route.go | 2 +- agent/secure/crypto.go | 2 +- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/agent/api/agent_route.go b/agent/api/agent_route.go index ef47bb0d..f07aa8fa 100644 --- a/agent/api/agent_route.go +++ b/agent/api/agent_route.go @@ -52,14 +52,32 @@ 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_API_V1+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, - constant.URI_TENANT_API_PREFIX+constant.URI_PATH_PARAM_NAME, + // 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, ), common.SetContentType, ) diff --git a/agent/api/obproxy_route.go b/agent/api/obproxy_route.go index 702ca827..85e2f616 100644 --- a/agent/api/obproxy_route.go +++ b/agent/api/obproxy_route.go @@ -38,7 +38,7 @@ func InitObproxyRoutes(r *gin.RouterGroup, isLocalRoute bool) { obproxy.DELETE("", obproxyDeleteHandler) obproxy.POST(constant.URI_START, obproxyStartHandler) obproxy.POST(constant.URI_STOP, obproxyStopHandler) - obproxy.POST("package", obproxyPkgUploadHandler) + obproxy.POST(constant.URI_PACKAGE, obproxyPkgUploadHandler) obproxy.POST(constant.URI_UPGRADE, obproxyUpgradeHandler) } diff --git a/agent/secure/crypto.go b/agent/secure/crypto.go index 53907f77..cf309246 100644 --- a/agent/secure/crypto.go +++ b/agent/secure/crypto.go @@ -123,7 +123,7 @@ func LoadOceanbasePassword(password *string) error { 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 From 26377690709e68d3435dda8e17bc90f94d60ce3d Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Thu, 10 Apr 2025 07:33:08 +0000 Subject: [PATCH 018/113] PullRequest: 363 clear oceanbase password when be SINGLE --- agent/meta/security.go | 5 +++++ agent/service/agent/info.go | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/agent/meta/security.go b/agent/meta/security.go index ed5d7974..b976d337 100644 --- a/agent/meta/security.go +++ b/agent/meta/security.go @@ -55,6 +55,11 @@ func SetOceanbasePwd(pwd string) { } } +func ClearOceanbasePwd() { + OCEANBASE_PWD = "" + OCEANBASE_PASSWORD_INITIALIZED = false +} + func GetObproxySysPwd() string { return OBPROXY_SYS_PWD } diff --git a/agent/service/agent/info.go b/agent/service/agent/info.go index fba2c2d2..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 }) } @@ -308,7 +309,6 @@ func (s *AgentService) BeScalingOutAgent(zone string) error { }) } - func (s *AgentService) SyncAgentData() (err error) { oceanbaseDb, err := oceanbasedb.GetOcsInstance() if err != nil { From 9fc8a8d7e13ab8b0c6fa3bccd18dbd5d855e1537 Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Thu, 10 Apr 2025 07:33:23 +0000 Subject: [PATCH 019/113] PullRequest: 366 fix: delete obproxy version in sqlite --- agent/executor/obproxy/add.go | 5 +---- agent/service/agent/obproxy.go | 3 +-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/agent/executor/obproxy/add.go b/agent/executor/obproxy/add.go index 3413bd31..95caa086 100644 --- a/agent/executor/obproxy/add.go +++ b/agent/executor/obproxy/add.go @@ -479,16 +479,13 @@ func (t *PersistObproxyInfoTask) Execute() error { if err := t.GetContext().GetParamWithValue(PARAM_OBPROXY_SQL_PORT, &t.sqlPort); err != nil { return err } - if err := t.GetContext().GetParamWithValue(PARAM_OBPROXY_VERSION, &t.version); 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.version, t.encryptedSysPwd, t.encryptedProxyroPassword); err != nil { + if err := agentService.AddObproxy(t.homePath, t.sqlPort, t.encryptedSysPwd, t.encryptedProxyroPassword); err != nil { return err } diff --git a/agent/service/agent/obproxy.go b/agent/service/agent/obproxy.go index db355104..808e9b0a 100644 --- a/agent/service/agent/obproxy.go +++ b/agent/service/agent/obproxy.go @@ -43,7 +43,7 @@ func (*AgentService) DeleteObproxy() error { }) } -func (*AgentService) AddObproxy(homePath string, sqlPort int, version, enObproxySysPwd, enObproxyProxyroPwd string) error { +func (*AgentService) AddObproxy(homePath string, sqlPort int, enObproxySysPwd, enObproxyProxyroPwd string) error { db, err := sqlitedb.GetSqliteInstance() if err != nil { return err @@ -53,7 +53,6 @@ func (*AgentService) AddObproxy(homePath string, sqlPort int, version, enObproxy infos[constant.OBPROXY_INFO_PROXYRO_PASSWORD] = enObproxyProxyroPwd infos[constant.OBPROXY_INFO_HOME_PATH] = homePath infos[constant.OBPROXY_INFO_SQL_PORT] = strconv.Itoa(sqlPort) - infos[constant.OBPROXY_INFO_VERSION] = version return db.Transaction(func(tx *gorm.DB) error { for k, v := range infos { From 9cf72de5d7bcda5169f17f92193f1f92ccb7512a Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Thu, 10 Apr 2025 07:33:39 +0000 Subject: [PATCH 020/113] PullRequest: 365 chore: mask password --- agent/api/agent_route.go | 2 +- agent/secure/auth.go | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/agent/api/agent_route.go b/agent/api/agent_route.go index f07aa8fa..32a294a9 100644 --- a/agent/api/agent_route.go +++ b/agent/api/agent_route.go @@ -53,7 +53,7 @@ func InitOcsAgentRoutes(s *http2.State, r *gin.Engine, isLocalRoute bool) { 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_API_V1+constant.URI_INIT, + 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, diff --git a/agent/secure/auth.go b/agent/secure/auth.go index 6069cc1f..5763c816 100644 --- a/agent/secure/auth.go +++ b/agent/secure/auth.go @@ -64,7 +64,6 @@ func VerifyAuth(pwd string, ts string, curTs int64, verifyType VerifyType) error if verifyType == AGENT_PASSWORD { if pwd != meta.AGENT_PWD.GetPassword() { - log.Infof("agent password is incorrect, pwd:%v, agentPwd:%v", pwd, meta.AGENT_PWD.GetPassword()) return fmt.Errorf("access denied: %s", "agent password is incorrect") } } else if verifyType == OCEANBASE_PASSWORD { From 22831f35f96d8e7030c98de8fb33e017c34b2e3f Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Thu, 10 Apr 2025 07:33:56 +0000 Subject: [PATCH 021/113] PullRequest: 367 add isObproxyAgent in info and return nil when bin/observer does not exist --- agent/api/info_handler.go | 6 +++--- agent/meta/agent.go | 24 +++++++++++++----------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/agent/api/info_handler.go b/agent/api/info_handler.go index a041eaaa..fabf4ee2 100644 --- a/agent/api/info_handler.go +++ b/agent/api/info_handler.go @@ -62,9 +62,9 @@ func TimeHandler(c *gin.Context) { // @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, meta.AGENT_PWD.Inited()) - 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()) + common.SendResponse(c, agentStatus, nil) } } diff --git a/agent/meta/agent.go b/agent/meta/agent.go index d37bea51..b882476d 100644 --- a/agent/meta/agent.go +++ b/agent/meta/agent.go @@ -155,8 +155,9 @@ type AgentStatus struct { HomePath string `json:"homePath"` OBVersion string `json:"obVersion"` AgentInstance - Security bool `json:"security"` - SupportedAuth []string `json:"supportedAuth"` + IsObproxyAgent bool `json:"isObproxyAgent"` + Security bool `json:"security"` + SupportedAuth []string `json:"supportedAuth"` } func (agent *ZoneDTO) GetZone() string { @@ -384,15 +385,16 @@ func NewAgentSecretByAgentInfo(agent AgentInfoInterface, publicKey string) *Agen } } -func NewAgentStatus(agent Agent, pid int, state int32, startAt int64, homePath string, obVersion string, isAgentPasswordSet bool) *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, - Security: isAgentPasswordSet, - 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}, } } From 737982a4c16955a3babadf368a425d53edb771ee Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Thu, 10 Apr 2025 07:34:12 +0000 Subject: [PATCH 022/113] PullRequest: 368 ore: update version to 4.2.6.0 --- Makefile.common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.common b/Makefile.common index b04dced6..a1bf17f8 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 From 600387605b40e60f97e1992f79e737547ab9a8c7 Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Thu, 10 Apr 2025 07:34:27 +0000 Subject: [PATCH 023/113] PullRequest: 369 chore: add attributes for obproxy task --- agent/executor/obproxy/add.go | 22 +++++++++++++++++----- agent/executor/obproxy/delete.go | 10 ++++++++-- agent/executor/obproxy/stop.go | 6 +++++- agent/executor/obproxy/upgrade.go | 24 ++++++++++++++++++++---- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/agent/executor/obproxy/add.go b/agent/executor/obproxy/add.go index 95caa086..8e7e516e 100644 --- a/agent/executor/obproxy/add.go +++ b/agent/executor/obproxy/add.go @@ -332,7 +332,11 @@ func newStartObproxyTask() *StartObproxyTask { newTask := &StartObproxyTask{ Task: *task.NewSubTask(TASK_START_OBPROXY), } - newTask.SetCanRetry().SetCanContinue() + newTask.SetCanContinue(). + SetCanRetry(). + SetCanRollback(). + SetCanCancel(). + SetCanPass() return newTask } @@ -459,7 +463,6 @@ type PersistObproxyInfoTask struct { task.Task homePath string sqlPort int - version string encryptedSysPwd string encryptedProxyroPassword string } @@ -468,7 +471,10 @@ func newPersistObproxyInfoTask() *PersistObproxyInfoTask { newTask := &PersistObproxyInfoTask{ Task: *task.NewSubTask(TASK_PERSIST_OBPROXY_INFP), } - newTask.SetCanRetry().SetCanContinue() + newTask.SetCanContinue(). + SetCanRetry(). + SetCanCancel(). + SetCanPass() return newTask } @@ -503,7 +509,10 @@ func newPrepareForObproxyAgentNode(expectObproxyAgent bool) *task.Node { newTask := &PrepareForAddObproxyTask{ Task: *task.NewSubTask(TASK_CHECK_OBPROXY_STATUS), } - newTask.SetCanRetry().SetCanContinue() + 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) @@ -543,7 +552,10 @@ func NewSetObproxyUserPasswordForObNode(encryptedProxyroPassword string) *task.N newTask := &SetObproxyUserPasswordForObTask{ Task: *task.NewSubTask(TASK_SET_OBPROXY_USER_PASSWORD), } - newTask.SetCanRetry().SetCanContinue() + newTask.SetCanContinue(). + SetCanRetry(). + SetCanCancel(). + SetCanPass() ctx := task.NewTaskContext().SetParam(PARAM_OBPROXY_PROXYRO_PASSWORD, encryptedProxyroPassword) return task.NewNodeWithContext(newTask, false, ctx) } diff --git a/agent/executor/obproxy/delete.go b/agent/executor/obproxy/delete.go index 1b3c0868..e40261cf 100644 --- a/agent/executor/obproxy/delete.go +++ b/agent/executor/obproxy/delete.go @@ -56,7 +56,10 @@ func newDeleteObproxyTask() *DeleteObproxyTask { newTask := &DeleteObproxyTask{ Task: *task.NewSubTask(TASK_DELETE_OBPROXY), } - newTask.SetCanRetry().SetCanContinue().SetCanCancel() + newTask.SetCanContinue(). + SetCanRetry(). + SetCanCancel(). + SetCanPass() return newTask } @@ -76,7 +79,10 @@ func newCleanObproxyDirTask() *CleanObproxyDirTask { newTask := &CleanObproxyDirTask{ Task: *task.NewSubTask(TASK_CLEAN_OBPROXY_DIR), } - newTask.SetCanRetry().SetCanContinue().SetCanCancel() + newTask.SetCanContinue(). + SetCanRetry(). + SetCanCancel(). + SetCanPass() return newTask } diff --git a/agent/executor/obproxy/stop.go b/agent/executor/obproxy/stop.go index 7aa06e15..e24e665b 100644 --- a/agent/executor/obproxy/stop.go +++ b/agent/executor/obproxy/stop.go @@ -56,7 +56,11 @@ func newStopObproxyTask() *StopObproxyTask { newTask := &StopObproxyTask{ Task: *task.NewSubTask(TASK_STOP_OBPROXY), } - newTask.SetCanRetry().SetCanContinue() + newTask.SetCanContinue(). + SetCanRetry(). + SetCanRollback(). + SetCanCancel(). + SetCanPass() return newTask } diff --git a/agent/executor/obproxy/upgrade.go b/agent/executor/obproxy/upgrade.go index 1c6a3ad7..ec08de3a 100644 --- a/agent/executor/obproxy/upgrade.go +++ b/agent/executor/obproxy/upgrade.go @@ -149,7 +149,11 @@ func newCopyConfigDbFileTask() *CopyConfigDbFileTask { newTask := &CopyConfigDbFileTask{ Task: *task.NewSubTask(TASK_COPY_CONFIG_DB_FILE), } - newTask.SetCanContinue().SetCanRetry().SetCanRollback() + newTask.SetCanContinue(). + SetCanRetry(). + SetCanRollback(). + SetCanCancel(). + SetCanPass() return newTask } @@ -187,7 +191,11 @@ func newHotRestartObproxyTask() *HotRestartObproxyTask { newTask := &HotRestartObproxyTask{ Task: *task.NewSubTask(TASK_HOT_RESTART_OBPROXY), } - newTask.SetCanContinue().SetCanRetry().SetCanCancel() + newTask.SetCanContinue(). + SetCanRetry(). + SetCanRollback(). + SetCanCancel(). + SetCanPass() return newTask } @@ -204,7 +212,11 @@ func newRecordObproxyInfoTask() *RecordObproxyInfoTask { newTask := &RecordObproxyInfoTask{ Task: *task.NewSubTask(TASK_RECORD_OBPROXY_INFO), } - newTask.SetCanContinue().SetCanRetry().SetCanRollback() + newTask.SetCanContinue(). + SetCanRetry(). + SetCanRollback(). + SetCanCancel(). + SetCanPass() return newTask } @@ -234,7 +246,11 @@ func newWaitHotRestartObproxyFinishTask() *WaitHotRestartObproxyFinishTask { newTask := &WaitHotRestartObproxyFinishTask{ Task: *task.NewSubTask(TASK_WAIT_HOT_RESTART_OBPROXY_FINISH), } - newTask.SetCanContinue().SetCanRetry().SetCanCancel() + newTask.SetCanContinue(). + SetCanRetry(). + SetCanRollback(). + SetCanCancel(). + SetCanPass() return newTask } From f6cf0ad5624c23dc1470af8676b03b194fab24cf Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Thu, 10 Apr 2025 07:34:42 +0000 Subject: [PATCH 024/113] PullRequest: 371 fix: auto migrate sqlite table when exist non-exist table --- agent/repository/db/sqlite/builder.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/agent/repository/db/sqlite/builder.go b/agent/repository/db/sqlite/builder.go index 4af7137b..ac680ce0 100644 --- a/agent/repository/db/sqlite/builder.go +++ b/agent/repository/db/sqlite/builder.go @@ -144,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. From 626a7ebb3f7ea549833376b82770537aff18c839 Mon Sep 17 00:00:00 2001 From: obdev Date: Thu, 10 Apr 2025 08:06:14 +0000 Subject: [PATCH 025/113] PullRequest: 376 api-def --- .gitignore | 4 + agent/api/obcluster_handler.go | 8 +- agent/api/tenant_handler.go | 18 +++++ agent/executor/task/dag.go | 140 ++++++++++++++++----------------- 4 files changed, 95 insertions(+), 75 deletions(-) diff --git a/.gitignore b/.gitignore index 66372caa..9e85344c 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,7 @@ vendor *.iml .vscode/* .OWNERS +.meta +etc/ +log_obshell/ +run/ diff --git a/agent/api/obcluster_handler.go b/agent/api/obcluster_handler.go index daa81f14..2e97ad9d 100644 --- a/agent/api/obcluster_handler.go +++ b/agent/api/obcluster_handler.go @@ -60,8 +60,7 @@ func parseRootPwd(pwd string, isForward bool) (string, error) { // @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] +// @Router /api/v1/obcluster/config [POST] func obclusterConfigHandler(deleteAll bool) func(c *gin.Context) { return func(c *gin.Context) { var params param.ObClusterConfigParams @@ -132,8 +131,7 @@ func obclusterConfigHandler(deleteAll bool) func(c *gin.Context) { // @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] +// @Router /api/v1/observer/config [POST] func obServerConfigHandler(deleteAll bool) func(c *gin.Context) { return func(c *gin.Context) { var params param.ObServerConfigParams @@ -309,7 +307,7 @@ func obStartHandler(c *gin.Context) { // @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] +// @Router /api/v1/ob/scale_out [POST] func obClusterScaleOutHandler(c *gin.Context) { var param param.ClusterScaleOutParam if err := c.BindJSON(¶m); err != nil { diff --git a/agent/api/tenant_handler.go b/agent/api/tenant_handler.go index 479354db..85b1b4e7 100644 --- a/agent/api/tenant_handler.go +++ b/agent/api/tenant_handler.go @@ -109,6 +109,7 @@ func tenantCheckWithName(c *gin.Context) (string, error) { // @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 @@ -141,6 +142,7 @@ func tenantDropHandler(c *gin.Context) { // @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 @@ -169,6 +171,7 @@ func tenantRenameHandler(c *gin.Context) { // @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 @@ -190,6 +193,7 @@ func tenantLockHandler(c *gin.Context) { // @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 @@ -211,6 +215,7 @@ func tenantUnlockHandler(c *gin.Context) { // @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 @@ -239,6 +244,7 @@ func tenantAddReplicasHandler(c *gin.Context) { // @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 @@ -270,6 +276,7 @@ func tenantRemoveReplicasHandler(c *gin.Context) { // @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 @@ -302,6 +309,7 @@ func tenantModifyReplicasHandler(c *gin.Context) { // @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 @@ -334,6 +342,7 @@ func tenantModifyWhitelistHandler(c *gin.Context) { // @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 @@ -365,6 +374,7 @@ func tenantModifyPasswordHandler(c *gin.Context) { // @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 @@ -393,6 +403,7 @@ func tenantModifyPrimaryZoneHandler(c *gin.Context) { // @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 @@ -420,6 +431,7 @@ func tenantSetParametersHandler(c *gin.Context) { // @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 @@ -447,6 +459,7 @@ func tenantSetVariableHandler(c *gin.Context) { // @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 @@ -469,6 +482,7 @@ func getTenantInfo(c *gin.Context) { // @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 @@ -499,6 +513,7 @@ func getTenantParameter(c *gin.Context) { // @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 @@ -523,6 +538,7 @@ func getTenantParameters(c *gin.Context) { // @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 @@ -553,6 +569,7 @@ func getTenantVariable(c *gin.Context) { // @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 @@ -597,6 +614,7 @@ func getTenantOverView(c *gin.Context) { // @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 diff --git a/agent/executor/task/dag.go b/agent/executor/task/dag.go index 037f9758..3279f6b1 100644 --- a/agent/executor/task/dag.go +++ b/agent/executor/task/dag.go @@ -193,9 +193,9 @@ func convertDagDetailDTO(dag *task.Dag, fillDeatil bool) (dagDetailDTO *task.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"}) +// @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 @@ -276,17 +276,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() @@ -303,17 +303,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() { @@ -341,17 +341,17 @@ 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) { param := getTaskQueryParams(c) dagDetailDTOs := make([]*task.DagDetailDTO, 0) @@ -384,17 +384,17 @@ func GetAllAgentLastMaintenanceDag(c *gin.Context) { common.SendResponse(c, dagDetailDTOs, nil) } -// @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() { @@ -424,18 +424,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")) @@ -447,17 +447,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) From 87a599d547e5dc95b66e9736f45fafdd4a0ec027 Mon Sep 17 00:00:00 2001 From: obdev Date: Mon, 14 Apr 2025 04:01:36 +0000 Subject: [PATCH 026/113] PullRequest: 377 user-db-api --- Makefile | 6 + Makefile.common | 1 + agent/api/agent_handler.go | 48 +- agent/api/agent_route.go | 1 - agent/api/common/middleware.go | 10 + agent/api/info_handler.go | 80 +-- agent/api/obcluster_handler.go | 370 +++++------ agent/api/pool_handler.go | 50 +- agent/api/recyclebin_handler.go | 78 +-- agent/api/secure_handler.go | 16 +- agent/api/tenant_handler.go | 804 ++++++++++++++--------- agent/api/unit_handler.go | 96 +-- agent/api/zone_handler.go | 26 +- agent/config/server.go | 7 + agent/repository/model/bo/database.go | 27 + agent/repository/model/bo/tenant_user.go | 46 ++ go.mod | 2 +- go.sum | 16 + param/database.go | 28 + param/tenant_user.go | 29 + 20 files changed, 1064 insertions(+), 677 deletions(-) create mode 100644 agent/repository/model/bo/database.go create mode 100644 agent/repository/model/bo/tenant_user.go create mode 100644 param/database.go create mode 100644 param/tenant_user.go diff --git a/Makefile b/Makefile index 956ee59f..9260fc3c 100644 --- a/Makefile +++ b/Makefile @@ -20,9 +20,15 @@ build-release: set-release-flags obshell buildsucc build-with-swagger: enable-swagger build-release +build-for-test: enable-swagger set-disable-encryption-flags build-debug + 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 a1bf17f8..a1784c21 100644 --- a/Makefile.common +++ b/Makefile.common @@ -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 6c0d9ea0..01d69f32 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 { @@ -102,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 { diff --git a/agent/api/agent_route.go b/agent/api/agent_route.go index 32a294a9..1cc30679 100644 --- a/agent/api/agent_route.go +++ b/agent/api/agent_route.go @@ -44,7 +44,6 @@ func InitOcsAgentRoutes(s *http2.State, r *gin.Engine, isLocalRoute bool) { common.PostHandlers("/debug/pprof", "/swagger"), common.BodyDecrypt(), // 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, diff --git a/agent/api/common/middleware.go b/agent/api/common/middleware.go index 4b60d1f8..9e6976b2 100644 --- a/agent/api/common/middleware.go +++ b/agent/api/common/middleware.go @@ -30,6 +30,7 @@ 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" @@ -300,6 +301,11 @@ func SetContentType(c *gin.Context) { 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() @@ -512,6 +518,10 @@ func VerifyTaskRoutes(c *gin.Context, curTs int64, header *secure.HttpHeader, pa 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) diff --git a/agent/api/info_handler.go b/agent/api/info_handler.go index fabf4ee2..f77c0be5 100644 --- a/agent/api/info_handler.go +++ b/agent/api/info_handler.go @@ -38,28 +38,28 @@ 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, _ := binary.GetMyOBVersion() // when occur err, obVersion is empty @@ -70,14 +70,14 @@ func InfoHandler(s *http.State) gin.HandlerFunc { // 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) } @@ -102,14 +102,14 @@ func GetAgentStatus(s *http.State) (http.AgentStatus, error) { // 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 +119,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{dat=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 2e97ad9d..a101ee16 100644 --- a/agent/api/obcluster_handler.go +++ b/agent/api/obcluster_handler.go @@ -48,19 +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 [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 @@ -119,19 +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 [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 @@ -176,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 { @@ -212,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 { @@ -245,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 { @@ -296,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 [POST] +// @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 { @@ -318,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 { @@ -357,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() @@ -390,19 +390,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 { @@ -413,19 +413,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 { @@ -436,18 +436,18 @@ 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 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.")) @@ -463,53 +463,53 @@ 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 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 { @@ -520,19 +520,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 { 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/tenant_handler.go b/agent/api/tenant_handler.go index 85b1b4e7..219d50a3 100644 --- a/agent/api/tenant_handler.go +++ b/agent/api/tenant_handler.go @@ -59,20 +59,20 @@ func InitTenantRoutes(v1 *gin.RouterGroup, isLocalRoute bool) { 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 { @@ -102,20 +102,20 @@ func tenantCheckWithName(c *gin.Context) (string, error) { 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 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] +// @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 { @@ -135,20 +135,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 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] +// @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 { @@ -164,19 +164,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" -// @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] +// @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 { @@ -186,19 +186,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" -// @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] +// @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 { @@ -208,20 +208,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 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] +// @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 { @@ -237,20 +237,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 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] +// @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 { @@ -269,20 +269,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 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] +// @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 { @@ -302,20 +302,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 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] +// @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 { @@ -335,20 +335,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 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}/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}/rootpassword [put] func tenantModifyPasswordHandler(c *gin.Context) { name, err := tenantCheckWithName(c) if err != nil { @@ -367,20 +367,20 @@ 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 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}/primaryzone [put] +// @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}/primaryzone [put] func tenantModifyPrimaryZoneHandler(c *gin.Context) { name, err := tenantCheckWithName(c) if err != nil { @@ -396,20 +396,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 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] +// @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 { @@ -424,20 +424,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 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] +// @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 { @@ -452,19 +452,19 @@ func tenantSetVariableHandler(c *gin.Context) { 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" -// @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] +// @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 { @@ -475,20 +475,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 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] +// @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 { @@ -506,20 +506,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 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] +// @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 { @@ -531,20 +531,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 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] +// @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 { @@ -562,20 +562,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 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}/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}/variable/{} [get] func getTenantVariables(c *gin.Context) { name, err := tenantCheckWithName(c) if err != nil { @@ -587,18 +587,18 @@ 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" +// @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())) @@ -607,20 +607,20 @@ func getTenantOverView(c *gin.Context) { 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] +// @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 { @@ -635,29 +635,29 @@ func createUserHandler(c *gin.Context) { common.SendResponse(c, nil, tenant.CreateUser(name, param)) } -// @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] +// @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 } - userName := c.Param(constant.URI_PARAM_USER) - if userName == "" { + user := c.Param(constant.URI_PARAM_USER) + if user == "" { common.SendResponse(c, nil, errors.Occur(errors.ErrIllegalArgument, "User name is empty.")) return } @@ -668,5 +668,223 @@ func dropUserHandler(c *gin.Context) { return } - common.SendResponse(c, nil, tenant.DropUser(name, userName, param.RootPassword)) + common.SendResponse(c, nil, tenant.DropUser(name, user, param.RootPassword)) +} + +// @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) { + common.SendResponse(c, nil, nil) +} + +// @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) { + common.SendResponse(c, nil, nil) +} + +// @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) { + common.SendResponse(c, nil, nil) +} + +// @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) { + common.SendResponse(c, nil, nil) +} + +// @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) { + common.SendResponse(c, nil, nil) +} + +// @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) { + common.SendResponse(c, nil, nil) +} + +// @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) { + common.SendResponse(c, nil, nil) +} + +// @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) { + common.SendResponse(c, nil, nil) +} + +// @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 databaseName 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/{databaseName} [GET] +func getDatabase(c *gin.Context) { + common.SendResponse(c, nil, nil) +} + +// @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 databaseName 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/{databaseName} [DELETE] +func deleteDatabase(c *gin.Context) { + common.SendResponse(c, nil, nil) +} + +// @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 databaseName 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/{databaseName} [PUT] +func updateDatabase(c *gin.Context) { + common.SendResponse(c, nil, nil) +} + +// @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) { + common.SendResponse(c, nil, 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/zone_handler.go b/agent/api/zone_handler.go index 932e2967..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/config/server.go b/agent/config/server.go index f2a5aea7..75d1d640 100644 --- a/agent/config/server.go +++ b/agent/config/server.go @@ -20,8 +20,15 @@ import ( "errors" "fmt" "net" + "strings" ) +var EncryptionDisabled string = "false" + +func IsEncryptionDisabled() bool { + return strings.ToUpper(EncryptionDisabled) == "TRUE" +} + type AgentMode = string const ( diff --git a/agent/repository/model/bo/database.go b/agent/repository/model/bo/database.go new file mode 100644 index 00000000..ab40bf0c --- /dev/null +++ b/agent/repository/model/bo/database.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 Database struct { + DbName string `json:"db_name"` + Charset string `json:"charset"` + Collation string `json:"collation"` + ReadOnly string `json:"read_only"` + CreateTime int64 `json:"create_time"` + RequiredSize int64 `json:"required_size"` + ConnectionUrls []ObproxyAndConnectionString `json:"connection_urls"` +} diff --git a/agent/repository/model/bo/tenant_user.go b/agent/repository/model/bo/tenant_user.go new file mode 100644 index 00000000..d3614b84 --- /dev/null +++ b/agent/repository/model/bo/tenant_user.go @@ -0,0 +1,46 @@ +/* + * 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 ObUser struct { + UserName string `json:"user_name"` + IsLocked bool `json:"is_locked"` + CreateTime int64 `json:"create_time"` + 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/go.mod b/go.mod index 3372a6d8..ce44c3f3 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/oceanbase/obshell -go 1.18 +go 1.23 require ( github.com/GmSSL/GmSSL-Go v1.3.1 diff --git a/go.sum b/go.sum index 4f9a3659..9b8f23d1 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,5 @@ github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/GmSSL/GmSSL-Go v1.3.1 h1:Vmy6G4sCyA/IDyNdZW2M0MFdoyraKWEt3blhzp9RTC4= github.com/GmSSL/GmSSL-Go v1.3.1/go.mod h1:uQlaHGIi40mL6uHqGOaSxqmrrv0Zxhb7uDlqQgcgjhc= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= @@ -39,6 +40,7 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= +github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= @@ -56,6 +58,7 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= @@ -70,7 +73,9 @@ github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9 github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= +github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -86,13 +91,21 @@ github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= +github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/pgconn v1.13.0 h1:3L1XMNV2Zvca/8BYhzcRFS70Lr0WlDg16Di6SFGAbys= +github.com/jackc/pgconn v1.13.0/go.mod h1:AnowpAqO4CMIIJNZl2VJp+KrkAZciAkhEl0W0JIobpI= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= +github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y4Y= +github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w= +github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.17.2 h1:0Ut0rpeKwvIVbMQ1KbMBU4h6wxehBI535LK6Flheh8E= +github.com/jackc/pgx/v4 v4.17.2/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw= github.com/jedib0t/go-pretty/v6 v6.5.4 h1:gOGo0613MoqUcf0xCj+h/V3sHDaZasfv152G6/5l91s= github.com/jedib0t/go-pretty/v6 v6.5.4/go.mod h1:5LQIxa52oJ/DlDSLv0HEkWOFMDGoWkJb9ss5KqPpJBg= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= @@ -137,6 +150,7 @@ github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI= github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE= +github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= @@ -313,10 +327,12 @@ gorm.io/driver/mysql v1.3.2/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2 gorm.io/driver/mysql v1.5.1-0.20230509030346-3715c134c25b h1:O7DuK4tml7U+sG1NJmGXz3LXaO6Goblps5Gx4NBuxis= gorm.io/driver/mysql v1.5.1-0.20230509030346-3715c134c25b/go.mod h1:RpAr+f2lUtJUm0e2FAbttXiUKgAqKSUtzI1ulJfz9xU= gorm.io/driver/postgres v1.4.5 h1:mTeXTTtHAgnS9PgmhN2YeUbazYpLhUI1doLnw42XUZc= +gorm.io/driver/postgres v1.4.5/go.mod h1:GKNQYSJ14qvWkvPwXljMGehpKrhlDNsqYRr5HnYGncg= gorm.io/driver/sqlite v1.1.6/go.mod h1:W8LmC/6UvVbHKah0+QOC7Ja66EaZXHwUTjgXY8YNWX8= gorm.io/driver/sqlite v1.5.4 h1:IqXwXi8M/ZlPzH/947tn5uik3aYQslP9BVveoax0nV0= gorm.io/driver/sqlite v1.5.4/go.mod h1:qxAuCol+2r6PannQDpOP1FP6ag3mKi4esLnB/jHed+4= gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0= +gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig= gorm.io/gen v0.3.24 h1:yL1RrCySwTWTQpkUkt2FCe42Xub2eaZP2tM5EQoFBNU= gorm.io/gen v0.3.24/go.mod h1:G9uxGfkfNFxPoOrV5P6KQxRMgZsQSCyp9vJP8xiKTGg= gorm.io/gorm v1.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= diff --git a/param/database.go b/param/database.go new file mode 100644 index 00000000..3eadeae5 --- /dev/null +++ b/param/database.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 param + +type CreateDatabaseParam struct { + DbName string `json:"db_name"` + Collation string `json:"collation"` + ReadOnly string `json:"read_only"` +} + +type ModifyDatabaseParam struct { + Collation string `json:"collation"` + ReadOnly string `json:"read_only"` +} diff --git a/param/tenant_user.go b/param/tenant_user.go new file mode 100644 index 00000000..a47a3fb0 --- /dev/null +++ b/param/tenant_user.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 param + +type ModifyUserGlobalPrivilegeParam struct { + GlobalPrivileges []string `json:"global_privileges"` +} + +type ModifyUserDbPrivilegeParam struct { + DbPrivileges []DbPrivilegeParam `json:"db_privileges"` +} + +type ChangeUserPasswordParam struct { + NewPassword string `json:"new_password"` +} From f52556b2084416dbc5f6b8af67d8ea7ae21045a2 Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Tue, 15 Apr 2025 10:00:32 +0000 Subject: [PATCH 027/113] PullRequest: 379 chore: add read_only in TenantInfo --- agent/constant/tenant.go | 1 + agent/executor/tenant/info.go | 14 ++++++++++++++ agent/repository/model/bo/tenant.go | 1 + agent/repository/model/oceanbase/tenant.go | 1 + client/cmd/tenant/show.go | 8 ++++++-- 5 files changed, 23 insertions(+), 2 deletions(-) diff --git a/agent/constant/tenant.go b/agent/constant/tenant.go index 58d615e0..9e5e328b 100644 --- a/agent/constant/tenant.go +++ b/agent/constant/tenant.go @@ -49,6 +49,7 @@ const ( VARIABLE_TIME_ZONE = "time_zone" VARIABLE_OB_TCP_INVITED_NODES = "ob_tcp_invited_nodes" + VARIABLE_READ_ONLY = "read_only" PARAMETER_ENABLE_REBALANCE = "enable_rebalance" diff --git a/agent/executor/tenant/info.go b/agent/executor/tenant/info.go index 37165a7c..96770b2e 100644 --- a/agent/executor/tenant/info.go +++ b/agent/executor/tenant/info.go @@ -17,6 +17,7 @@ package tenant import ( + "github.com/oceanbase/obshell/agent/constant" "github.com/oceanbase/obshell/agent/errors" "github.com/oceanbase/obshell/agent/repository/model/bo" "github.com/oceanbase/obshell/agent/repository/model/oceanbase" @@ -27,6 +28,13 @@ func GetTenantsOverView() ([]oceanbase.DbaObTenant, *errors.OcsAgentError) { if err != nil { return nil, errors.Occur(errors.ErrUnexpected, err.Error()) } + for i := range tenants { + readOnly, err := tenantService.GetTenantVariable(tenants[i].TenantName, constant.VARIABLE_READ_ONLY) + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + tenants[i].ReadOnly = (readOnly.Value == "1") + } return tenants, nil } @@ -65,6 +73,11 @@ func GetTenantInfo(tenantName string) (*bo.TenantInfo, *errors.OcsAgentError) { pools = append(pools, &poolWithUnit) } + readOnly, err := tenantService.GetTenantVariable(tenantName, constant.VARIABLE_READ_ONLY) + if err != nil { + return nil, errors.Occur(errors.ErrUnexpected, err.Error()) + } + return &bo.TenantInfo{ Name: tenant.TenantName, Id: tenant.TenantID, @@ -77,5 +90,6 @@ func GetTenantInfo(tenantName string) (*bo.TenantInfo, *errors.OcsAgentError) { InRecyclebin: tenant.InRecyclebin, Whitelist: whitelist.Value, Pools: pools, + ReadOnly: readOnly.Value == "1", }, nil } diff --git a/agent/repository/model/bo/tenant.go b/agent/repository/model/bo/tenant.go index b20a2c45..e6a03f29 100644 --- a/agent/repository/model/bo/tenant.go +++ b/agent/repository/model/bo/tenant.go @@ -122,4 +122,5 @@ type TenantInfo struct { Collation string `json:"collation"` // Only for ORACLE tenant Whitelist string `json:"whitelist"` Pools []*ResourcePoolWithUnit `json:"pools"` + ReadOnly bool `json:"read_only"` // Default to false. } diff --git a/agent/repository/model/oceanbase/tenant.go b/agent/repository/model/oceanbase/tenant.go index 04fba6d5..c0c3b6ff 100644 --- a/agent/repository/model/oceanbase/tenant.go +++ b/agent/repository/model/oceanbase/tenant.go @@ -30,6 +30,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 { 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)}) } } } From ee46dca35e088022b74c65283de8175d12104d4d Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Thu, 17 Apr 2025 04:00:31 +0000 Subject: [PATCH 028/113] PullRequest: 384 feat: add API([GET] /api/v1/obcluster/charsets) to get cluster charsets --- agent/api/agent_route.go | 1 + agent/api/obcluster_handler.go | 20 +++++++ agent/constant/uri.go | 1 + agent/executor/ob/charset.go | 65 +++++++++++++++++++++ agent/repository/model/bo/charset.go | 29 +++++++++ agent/repository/model/oceanbase/charset.go | 31 ++++++++++ agent/repository/model/oceanbase/tenant.go | 6 -- agent/service/obcluster/obcluster.go | 22 ++++++- 8 files changed, 167 insertions(+), 8 deletions(-) create mode 100644 agent/executor/ob/charset.go create mode 100644 agent/repository/model/bo/charset.go create mode 100644 agent/repository/model/oceanbase/charset.go diff --git a/agent/api/agent_route.go b/agent/api/agent_route.go index 1cc30679..f703ee17 100644 --- a/agent/api/agent_route.go +++ b/agent/api/agent_route.go @@ -157,6 +157,7 @@ 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_CHARSETS, getObclusterCharsets) // observer routes observer.PUT(constant.URI_CONFIG, obServerConfigHandler(true)) diff --git a/agent/api/obcluster_handler.go b/agent/api/obcluster_handler.go index a101ee16..f1752bf6 100644 --- a/agent/api/obcluster_handler.go +++ b/agent/api/obcluster_handler.go @@ -556,3 +556,23 @@ 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) +} diff --git a/agent/constant/uri.go b/agent/constant/uri.go index 43480349..c35b9b70 100644 --- a/agent/constant/uri.go +++ b/agent/constant/uri.go @@ -69,6 +69,7 @@ const ( URI_SCALE_OUT = "/scale_out" URI_SCALE_IN = "/scale_in" URI_AGENTS = "/agents" + URI_CHARSETS = "/charsets" // Used for upgrade URI_UPGRADE = "/upgrade" 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/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/oceanbase/charset.go b/agent/repository/model/oceanbase/charset.go new file mode 100644 index 00000000..55d5d9c8 --- /dev/null +++ b/agent/repository/model/oceanbase/charset.go @@ -0,0 +1,31 @@ +/* + * 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"` + 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/tenant.go b/agent/repository/model/oceanbase/tenant.go index c0c3b6ff..4b55062a 100644 --- a/agent/repository/model/oceanbase/tenant.go +++ b/agent/repository/model/oceanbase/tenant.go @@ -67,12 +67,6 @@ 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"` diff --git a/agent/service/obcluster/obcluster.go b/agent/service/obcluster/obcluster.go index 15e1756b..c6633e93 100644 --- a/agent/service/obcluster/obcluster.go +++ b/agent/service/obcluster/obcluster.go @@ -687,13 +687,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 +706,24 @@ 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).Select(("*")).Scan(&collations).Error + return +} + func (ObclusterService *ObclusterService) GetObUnitsOnServer(svrIp string, svrPort int) (units []oceanbase.DbaObUnit, err error) { oceanbaseDb, err := oceanbasedb.GetInstance() if err != nil { From 80886dd0fb2171b23cd7f19e7d38e20bcaeadd3c Mon Sep 17 00:00:00 2001 From: Junkrat77 <2367392933@qq.com> Date: Thu, 17 Apr 2025 06:00:33 +0000 Subject: [PATCH 029/113] PullRequest: 381 feat: add API for uploading package which won't request encryted body --- agent/api/agent_route.go | 8 +++- agent/api/common/middleware.go | 79 +++++++++++++++++++++++++++++++++- agent/api/obcluster_handler.go | 28 ++++++++++++ agent/secure/header.go | 1 + 4 files changed, 112 insertions(+), 4 deletions(-) diff --git a/agent/api/agent_route.go b/agent/api/agent_route.go index f703ee17..98026d7f 100644 --- a/agent/api/agent_route.go +++ b/agent/api/agent_route.go @@ -42,8 +42,9 @@ 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.PaddingBody(), // if the response body is empty, the response body is padded with "{}" + 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, @@ -103,6 +104,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()) @@ -172,6 +174,8 @@ func InitOcsAgentRoutes(s *http2.State, r *gin.Engine, isLocalRoute bool) { 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) diff --git a/agent/api/common/middleware.go b/agent/api/common/middleware.go index 9e6976b2..63189521 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" @@ -299,7 +301,7 @@ func SetContentType(c *gin.Context) { 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() { @@ -338,13 +340,42 @@ func BodyDecrypt(skipRoutes ...string) func(*gin.Context) { } 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) @@ -516,6 +547,50 @@ func VerifyTaskRoutes(c *gin.Context, curTs int64, header *secure.HttpHeader, pa } } +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.Occur(errors.ErrKnown, "get file failed.", 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 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, "file sha256 not match")) + return + } + c.Next() + } +} + func Verify(routeType ...secure.RouteType) func(*gin.Context) { return func(c *gin.Context) { if config.IsEncryptionDisabled() { diff --git a/agent/api/obcluster_handler.go b/agent/api/obcluster_handler.go index f1752bf6..409967da 100644 --- a/agent/api/obcluster_handler.go +++ b/agent/api/obcluster_handler.go @@ -463,6 +463,34 @@ func pkgUploadHandler(c *gin.Context) { 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=oceanbase.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.Occur(errors.ErrKnown, "get file failed.", err)) + return + } + defer file.Close() + data, agentErr := ob.UpgradePkgUpload(file) + common.SendResponse(c, &data, agentErr) +} + // @ID ParamsBackup // @Summary backup params // @Description backup params diff --git a/agent/secure/header.go b/agent/secure/header.go index 94aaa296..7e4c35fe 100644 --- a/agent/secure/header.go +++ b/agent/secure/header.go @@ -41,6 +41,7 @@ type HttpHeader struct { Token string Uri string Keys []byte + Sha256 string ForwardType int ForwardAgent meta.AgentInfo } From 7956bc65e6fd9c37d6e7eccc2030745361217362 Mon Sep 17 00:00:00 2001 From: obdev Date: Fri, 18 Apr 2025 03:02:38 +0000 Subject: [PATCH 030/113] =?UTF-8?q?PullRequest:=20386=20chore():=20?= =?UTF-8?q?=E5=89=8D=E7=AB=AF=E4=BB=A3=E7=A0=81/1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 18 + frontend/config/config.ts | 90 + frontend/config/plugin.must.ts | 256 + frontend/config/routes.ts | 223 + frontend/jest.config.js | 24 + frontend/openapi2ts.config.ts | 8 + frontend/package.json | 115 + frontend/pnpm-lock.yaml | 21853 ++++++++++++++++ frontend/public/assets/badge/default.svg | 27 + frontend/public/assets/badge/error.svg | 27 + frontend/public/assets/badge/processing.svg | 27 + frontend/public/assets/badge/success.svg | 27 + frontend/public/assets/badge/warning.svg | 27 + frontend/public/assets/cluster/abandoned.svg | 73 + frontend/public/assets/cluster/cluster.svg | 30 + frontend/public/assets/cluster/creating.svg | 74 + frontend/public/assets/cluster/deleted.svg | 79 + frontend/public/assets/cluster/deleting.svg | 81 + frontend/public/assets/cluster/error.svg | 73 + frontend/public/assets/cluster/failover.svg | 73 + frontend/public/assets/cluster/movingout.svg | 73 + frontend/public/assets/cluster/operating.svg | 73 + frontend/public/assets/cluster/restarting.svg | 81 + frontend/public/assets/cluster/running.svg | 55 + frontend/public/assets/cluster/starting.svg | 81 + frontend/public/assets/cluster/stopped.svg | 79 + frontend/public/assets/cluster/stopping.svg | 81 + frontend/public/assets/cluster/switchover.svg | 73 + frontend/public/assets/cluster/takingover.svg | 74 + .../public/assets/cluster/unavailable.svg | 73 + frontend/public/assets/cluster/upgrading.svg | 73 + frontend/public/assets/common/403.svg | 517 + frontend/public/assets/common/404.svg | 323 + frontend/public/assets/common/500.svg | 217 + frontend/public/assets/common/crash.svg | 52 + frontend/public/assets/common/empty.svg | 91 + frontend/public/assets/common/guide.svg | 59 + frontend/public/assets/common/no_auth.svg | 140 + frontend/public/assets/icon/client.svg | 25 + frontend/public/assets/icon/close.svg | 26 + frontend/public/assets/icon/ellipsis.svg | 34 + frontend/public/assets/icon/fit_canvas.svg | 26 + frontend/public/assets/icon/more.svg | 36 + frontend/public/assets/icon/obproxy.svg | 26 + frontend/public/assets/icon/reset.svg | 26 + frontend/public/assets/icon/settings.svg | 41 + frontend/public/assets/icon/success.svg | 55 + frontend/public/assets/icon/warning.svg | 84 + .../public/assets/login/background_img.svg | 42 + .../assets/login/background_img_dark.svg | 42 + .../public/assets/logo/oceanbase_logo.svg | 37 + .../assets/logo/ocp_express_favicon.svg | 34 + .../public/assets/logo/ocp_express_icon.svg | 26 + .../assets/logo/ocp_express_logo_en.svg | 51 + .../assets/logo/ocp_express_logo_en_dark.svg | 35 + .../assets/logo/ocp_express_logo_zh.svg | 49 + .../assets/logo/ocp_express_logo_zh_dark.svg | 33 + .../logo/ocp_express_simple_logo_en.svg | 50 + .../logo/ocp_express_simple_logo_en_dark.svg | 36 + .../logo/ocp_express_simple_logo_zh.svg | 68 + .../logo/ocp_express_simple_logo_zh_dark.svg | 68 + frontend/public/assets/overview/obproxy.svg | 40 + frontend/public/assets/overview/tenant.svg | 89 + frontend/public/assets/server/creating.svg | 88 + frontend/public/assets/server/deleted.svg | 70 + frontend/public/assets/server/deleting.svg | 88 + frontend/public/assets/server/disabled.svg | 70 + frontend/public/assets/server/error.svg | 82 + .../public/assets/server/process_stopped.svg | 70 + .../public/assets/server/process_stopping.svg | 88 + frontend/public/assets/server/restarting.svg | 88 + frontend/public/assets/server/running.svg | 72 + frontend/public/assets/server/server.svg | 24 + .../public/assets/server/service_stopped.svg | 70 + .../public/assets/server/service_stopping.svg | 88 + frontend/public/assets/server/starting.svg | 88 + frontend/public/assets/server/stopped.svg | 70 + frontend/public/assets/server/stopping.svg | 88 + frontend/public/assets/server/unavailable.svg | 82 + frontend/public/assets/server/warning.svg | 82 + .../public/assets/task/subtask_failed.svg | 27 + .../public/assets/task/subtask_pending.svg | 27 + frontend/public/assets/task/subtask_ready.svg | 27 + .../public/assets/task/subtask_running.svg | 35 + .../public/assets/task/subtask_successful.svg | 27 + frontend/public/assets/tenant/deadlock.svg | 28 + frontend/public/assets/tenant/no_deadlock.svg | 129 + .../public/assets/tenant/no_deadlock_data.svg | 77 + frontend/public/assets/tenant/polyline.svg | 24 + frontend/public/assets/tenant/tenant.svg | 24 + frontend/public/assets/unit/cpu.svg | 22 + frontend/public/assets/unit/disk.svg | 22 + frontend/public/assets/unit/memory.svg | 24 + frontend/public/assets/unit/region.svg | 22 + frontend/public/assets/unit/replica.svg | 21 + frontend/public/assets/unit/server.svg | 24 + frontend/public/assets/unit/tenant.svg | 22 + frontend/public/assets/unit/unit.svg | 22 + frontend/public/assets/unit/zone.svg | 22 + frontend/public/assets/zone/creating.svg | 61 + frontend/public/assets/zone/deleted.svg | 45 + frontend/public/assets/zone/deleting.svg | 73 + frontend/public/assets/zone/disabled.svg | 45 + frontend/public/assets/zone/error.svg | 61 + frontend/public/assets/zone/operating.svg | 61 + frontend/public/assets/zone/restarting.svg | 73 + frontend/public/assets/zone/running.svg | 45 + .../public/assets/zone/service_stopped.svg | 45 + frontend/public/assets/zone/starting.svg | 73 + frontend/public/assets/zone/stopped.svg | 45 + frontend/public/assets/zone/stopping.svg | 73 + frontend/public/assets/zone/unavailable.svg | 61 + frontend/public/js/iconfont.js | 1 + frontend/public/lottie/backup.json | 1 + frontend/public/lottie/diagnosis.json | 1 + frontend/public/lottie/log.json | 1 + frontend/public/lottie/monitor.json | 1 + frontend/public/lottie/overview.json | 1 + frontend/public/lottie/property.json | 1 + frontend/public/lottie/tenant.json | 1 + frontend/tsconfig.json | 26 + frontend/tslint.json | 25 + frontend/typings.d.ts | 97 + 123 files changed, 29350 insertions(+) create mode 100755 frontend/config/config.ts create mode 100644 frontend/config/plugin.must.ts create mode 100644 frontend/config/routes.ts create mode 100644 frontend/jest.config.js create mode 100644 frontend/openapi2ts.config.ts create mode 100644 frontend/package.json create mode 100644 frontend/pnpm-lock.yaml create mode 100644 frontend/public/assets/badge/default.svg create mode 100644 frontend/public/assets/badge/error.svg create mode 100644 frontend/public/assets/badge/processing.svg create mode 100644 frontend/public/assets/badge/success.svg create mode 100644 frontend/public/assets/badge/warning.svg create mode 100644 frontend/public/assets/cluster/abandoned.svg create mode 100644 frontend/public/assets/cluster/cluster.svg create mode 100644 frontend/public/assets/cluster/creating.svg create mode 100644 frontend/public/assets/cluster/deleted.svg create mode 100644 frontend/public/assets/cluster/deleting.svg create mode 100644 frontend/public/assets/cluster/error.svg create mode 100644 frontend/public/assets/cluster/failover.svg create mode 100644 frontend/public/assets/cluster/movingout.svg create mode 100644 frontend/public/assets/cluster/operating.svg create mode 100644 frontend/public/assets/cluster/restarting.svg create mode 100644 frontend/public/assets/cluster/running.svg create mode 100644 frontend/public/assets/cluster/starting.svg create mode 100644 frontend/public/assets/cluster/stopped.svg create mode 100644 frontend/public/assets/cluster/stopping.svg create mode 100644 frontend/public/assets/cluster/switchover.svg create mode 100644 frontend/public/assets/cluster/takingover.svg create mode 100644 frontend/public/assets/cluster/unavailable.svg create mode 100644 frontend/public/assets/cluster/upgrading.svg create mode 100644 frontend/public/assets/common/403.svg create mode 100644 frontend/public/assets/common/404.svg create mode 100644 frontend/public/assets/common/500.svg create mode 100644 frontend/public/assets/common/crash.svg create mode 100644 frontend/public/assets/common/empty.svg create mode 100644 frontend/public/assets/common/guide.svg create mode 100644 frontend/public/assets/common/no_auth.svg create mode 100644 frontend/public/assets/icon/client.svg create mode 100644 frontend/public/assets/icon/close.svg create mode 100644 frontend/public/assets/icon/ellipsis.svg create mode 100644 frontend/public/assets/icon/fit_canvas.svg create mode 100644 frontend/public/assets/icon/more.svg create mode 100644 frontend/public/assets/icon/obproxy.svg create mode 100644 frontend/public/assets/icon/reset.svg create mode 100644 frontend/public/assets/icon/settings.svg create mode 100644 frontend/public/assets/icon/success.svg create mode 100644 frontend/public/assets/icon/warning.svg create mode 100644 frontend/public/assets/login/background_img.svg create mode 100644 frontend/public/assets/login/background_img_dark.svg create mode 100644 frontend/public/assets/logo/oceanbase_logo.svg create mode 100644 frontend/public/assets/logo/ocp_express_favicon.svg create mode 100644 frontend/public/assets/logo/ocp_express_icon.svg create mode 100644 frontend/public/assets/logo/ocp_express_logo_en.svg create mode 100644 frontend/public/assets/logo/ocp_express_logo_en_dark.svg create mode 100644 frontend/public/assets/logo/ocp_express_logo_zh.svg create mode 100644 frontend/public/assets/logo/ocp_express_logo_zh_dark.svg create mode 100644 frontend/public/assets/logo/ocp_express_simple_logo_en.svg create mode 100644 frontend/public/assets/logo/ocp_express_simple_logo_en_dark.svg create mode 100644 frontend/public/assets/logo/ocp_express_simple_logo_zh.svg create mode 100644 frontend/public/assets/logo/ocp_express_simple_logo_zh_dark.svg create mode 100644 frontend/public/assets/overview/obproxy.svg create mode 100644 frontend/public/assets/overview/tenant.svg create mode 100644 frontend/public/assets/server/creating.svg create mode 100644 frontend/public/assets/server/deleted.svg create mode 100644 frontend/public/assets/server/deleting.svg create mode 100644 frontend/public/assets/server/disabled.svg create mode 100644 frontend/public/assets/server/error.svg create mode 100644 frontend/public/assets/server/process_stopped.svg create mode 100644 frontend/public/assets/server/process_stopping.svg create mode 100644 frontend/public/assets/server/restarting.svg create mode 100644 frontend/public/assets/server/running.svg create mode 100644 frontend/public/assets/server/server.svg create mode 100644 frontend/public/assets/server/service_stopped.svg create mode 100644 frontend/public/assets/server/service_stopping.svg create mode 100644 frontend/public/assets/server/starting.svg create mode 100644 frontend/public/assets/server/stopped.svg create mode 100644 frontend/public/assets/server/stopping.svg create mode 100644 frontend/public/assets/server/unavailable.svg create mode 100644 frontend/public/assets/server/warning.svg create mode 100644 frontend/public/assets/task/subtask_failed.svg create mode 100644 frontend/public/assets/task/subtask_pending.svg create mode 100644 frontend/public/assets/task/subtask_ready.svg create mode 100644 frontend/public/assets/task/subtask_running.svg create mode 100644 frontend/public/assets/task/subtask_successful.svg create mode 100644 frontend/public/assets/tenant/deadlock.svg create mode 100644 frontend/public/assets/tenant/no_deadlock.svg create mode 100644 frontend/public/assets/tenant/no_deadlock_data.svg create mode 100644 frontend/public/assets/tenant/polyline.svg create mode 100644 frontend/public/assets/tenant/tenant.svg create mode 100644 frontend/public/assets/unit/cpu.svg create mode 100644 frontend/public/assets/unit/disk.svg create mode 100644 frontend/public/assets/unit/memory.svg create mode 100644 frontend/public/assets/unit/region.svg create mode 100644 frontend/public/assets/unit/replica.svg create mode 100644 frontend/public/assets/unit/server.svg create mode 100644 frontend/public/assets/unit/tenant.svg create mode 100644 frontend/public/assets/unit/unit.svg create mode 100644 frontend/public/assets/unit/zone.svg create mode 100644 frontend/public/assets/zone/creating.svg create mode 100644 frontend/public/assets/zone/deleted.svg create mode 100644 frontend/public/assets/zone/deleting.svg create mode 100644 frontend/public/assets/zone/disabled.svg create mode 100644 frontend/public/assets/zone/error.svg create mode 100644 frontend/public/assets/zone/operating.svg create mode 100644 frontend/public/assets/zone/restarting.svg create mode 100644 frontend/public/assets/zone/running.svg create mode 100644 frontend/public/assets/zone/service_stopped.svg create mode 100644 frontend/public/assets/zone/starting.svg create mode 100644 frontend/public/assets/zone/stopped.svg create mode 100644 frontend/public/assets/zone/stopping.svg create mode 100644 frontend/public/assets/zone/unavailable.svg create mode 100644 frontend/public/js/iconfont.js create mode 100644 frontend/public/lottie/backup.json create mode 100644 frontend/public/lottie/diagnosis.json create mode 100644 frontend/public/lottie/log.json create mode 100644 frontend/public/lottie/monitor.json create mode 100644 frontend/public/lottie/overview.json create mode 100644 frontend/public/lottie/property.json create mode 100644 frontend/public/lottie/tenant.json create mode 100644 frontend/tsconfig.json create mode 100644 frontend/tslint.json create mode 100644 frontend/typings.d.ts diff --git a/.gitignore b/.gitignore index 9e85344c..be055a54 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,24 @@ 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 diff --git a/frontend/config/config.ts b/frontend/config/config.ts new file mode 100755 index 00000000..d48b30fc --- /dev/null +++ b/frontend/config/config.ts @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +import { defineConfig } from 'umi'; +import AntdMomentWebpackPlugin from '@ant-design/moment-webpack-plugin'; +import routes from './routes'; + +const ocp = { + 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..4e54c76b --- /dev/null +++ b/frontend/config/routes.ts @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +export default [ + { + path: '/', + component: 'Layout', + name: '系统布局', + spmb: 'b55539', + routes: [ + { + path: 'login', + component: 'Login', + name: '登录页', + spmb: 'b55540', + }, + { + 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: 'tenant/result/:taskId', + component: 'Tenant/Result/Success', + name: '新建租户任务提交成功', + spmb: 'b55555', + }, + { + 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/jest.config.js b/frontend/jest.config.js new file mode 100644 index 00000000..fd81e71f --- /dev/null +++ b/frontend/jest.config.js @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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..5e7015b9 --- /dev/null +++ b/frontend/openapi2ts.config.ts @@ -0,0 +1,8 @@ +const path = require('path'); + +export default { + 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..276246f3 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,115 @@ +{ + "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", + "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", + "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.6", + "@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.9", + "@oceanbase/icons": "^0.4.5", + "@oceanbase/ui": "^0.4.10", + "@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.4", + "antd-style": "^3.7.1", + "bignumber.js": "^9.1.2", + "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.12.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.21.4", + "babel-cli": "^6.26.0", + "babel-preset-es2015": "^6.24.1", + "dotenv": "^16.4.7", + "eslint": "^9.22.0", + "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..aff5d854 --- /dev/null +++ b/frontend/pnpm-lock.yaml @@ -0,0 +1,21853 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: false + excludeLinksFromLockfile: false + +dependencies: + '@ahooksjs/use-url-state': + specifier: ^3.5.1 + version: 3.5.1 + '@ant-design/compatible': + specifier: ^1.1.2 + version: 1.1.2(antd@5.24.4) + '@ant-design/pro-components': + specifier: ^2.8.6 + version: 2.8.6(antd@5.24.4) + '@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(antd@5.24.4) + '@oceanbase/design': + specifier: ^0.4.9 + version: 0.4.9(moment@2.30.1) + '@oceanbase/icons': + specifier: ^0.4.5 + version: 0.4.5 + '@oceanbase/ui': + specifier: ^0.4.10 + version: 0.4.10(@types/react@17.0.52)(antd@5.24.4) + '@oceanbase/util': + specifier: ^0.4.2 + version: 0.4.2 + '@sentry/react': + specifier: ^7.120.3 + version: 7.120.3 + '@sentry/tracing': + specifier: ^7.120.3 + version: 7.120.3 + '@umijs/plugin-openapi': + specifier: ^1.3.3 + version: 1.3.3(typescript@4.9.5)(umi@3.5.43) + '@umijs/preset-react': + specifier: ~1.8.32 + version: 1.8.32(umi@3.5.43) + ahooks: + specifier: ^3.8.4 + version: 3.8.4 + antd: + specifier: ^5.24.4 + version: 5.24.4(moment@2.30.1) + antd-style: + specifier: ^3.7.1 + version: 3.7.1(@types/react@17.0.52)(antd@5.24.4) + bignumber.js: + specifier: ^9.1.2 + version: 9.1.2 + 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 + prism-react-renderer: + specifier: ^1.3.5 + version: 1.3.5 + query-string: + specifier: ^8.2.0 + version: 8.2.0 + react-beautiful-dnd: + specifier: ^12.2.0 + version: 12.2.0 + react-intl: + specifier: 3.12.1 + version: 3.12.1 + react-scripts: + specifier: ^5.0.1 + version: 5.0.1(eslint@9.22.0)(typescript@4.9.5) + react-split-pane: + specifier: ^0.1.92 + version: 0.1.92 + react-sticky-mouse-tooltip: + specifier: 0.0.1 + version: 0.0.1 + 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 + umi-request: + specifier: ^1.4.0 + version: 1.4.0 + use-deep-compare-effect: + specifier: ^1.8.1 + version: 1.8.1 + validator: + specifier: ^13.12.0 + version: 13.12.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(typescript@4.9.5) + '@umijs/test': + specifier: ^3.5.43 + version: 3.5.43 + axios: + specifier: ^0.21.4 + version: 0.21.4 + babel-cli: + specifier: ^6.26.0 + version: 6.26.0 + babel-preset-es2015: + specifier: ^6.24.1 + version: 6.24.1 + dotenv: + specifier: ^16.4.7 + version: 16.4.7 + eslint: + specifier: ^9.22.0 + version: 9.22.0 + eslint-plugin-react-hooks: + specifier: ^4.6.2 + version: 4.6.2(eslint@9.22.0) + fs-extra: + specifier: ^10.1.0 + version: 10.1.0 + html-webpack-plugin: + specifier: ^4.5.2 + version: 4.5.2 + lint-staged: + specifier: ^10.5.4 + version: 10.5.4 + mini-css-extract-plugin: + specifier: ^1.6.2 + version: 1.6.2 + 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) + 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 + dependencies: + lodash.debounce: 4.0.8 + lodash.throttle: 4.1.1 + dev: false + + /@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 + dependencies: + ahooks: 3.8.4 + query-string: 6.14.1 + tslib: 2.8.1 + dev: false + + /@alloc/quick-lru@5.2.0: + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + dev: false + + /@amap/amap-jsapi-loader@1.0.1: + resolution: {integrity: sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw==} + dev: false + + /@ampproject/remapping@2.3.0: + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + + /@ant-design/charts@1.4.3(antd@5.24.4)(classnames@2.5.1)(lodash@4.17.21): + 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' + dependencies: + '@ant-design/flowchart': 1.2.2(antd@5.24.4)(classnames@2.5.1)(lodash@4.17.21) + '@ant-design/graphs': 1.4.1 + '@ant-design/maps': 1.0.8 + '@ant-design/plots': 1.2.6 + antd: 5.24.4(moment@2.30.1) + lodash: 4.17.21 + transitivePeerDependencies: + - classnames + dev: false + + /@ant-design/colors@4.0.5: + resolution: {integrity: sha512-3mnuX2prnWOWvpFTS2WH2LoouWlOgtnIpc6IarWN6GOzzLF8dW/U8UctuvIPhoboETehZfJ61XP+CGakBEPJ3Q==} + dependencies: + tinycolor2: 1.6.0 + dev: false + + /@ant-design/colors@6.0.0: + resolution: {integrity: sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==} + dependencies: + '@ctrl/tinycolor': 3.6.1 + dev: false + + /@ant-design/colors@7.2.0: + resolution: {integrity: sha512-bjTObSnZ9C/O8MB/B4OUtd/q9COomuJAR2SYfhxLyHvCKn4EKwCN3e+fWGMo7H5InAyV0wL17jdE9ALrdOW/6A==} + dependencies: + '@ant-design/fast-color': 2.0.6 + dev: false + + /@ant-design/compatible@1.1.2(antd@5.24.4): + resolution: {integrity: sha512-Qsx5Qw97eiSgcxyQDlY45QSbvGn0gUdpX8XFImPvzZpKwabqQ2HnXXuUlb8RbrkURswaPIoyLEGKDPeogIaURA==} + peerDependencies: + antd: 3.x + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + '@ant-design/icons': 4.8.3 + antd: 5.24.4(moment@2.30.1) + classnames: 2.5.1 + lodash.camelcase: 4.3.0 + lodash.upperfirst: 4.3.1 + omit.js: 1.0.2 + rc-animate: 2.11.1 + rc-editor-mention: 1.1.13 + rc-form: 2.4.12 + rc-util: 4.21.1 + transitivePeerDependencies: + - prop-types + dev: false + + /@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' + dependencies: + '@ant-design/cssinjs': 1.23.0 + '@babel/runtime': 7.26.10 + rc-util: 5.44.4 + dev: false + + /@ant-design/cssinjs@1.23.0: + resolution: {integrity: sha512-7GAg9bD/iC9ikWatU9ym+P9ugJhi/WbsTWzcKN6T4gU0aehsprtke1UAaaSxxkjjmkJb3llet/rbUSLPgwlY4w==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + '@babel/runtime': 7.26.10 + '@emotion/hash': 0.8.0 + '@emotion/unitless': 0.7.5 + classnames: 2.5.1 + csstype: 3.1.3 + rc-util: 5.44.4 + stylis: 4.3.6 + dev: false + + /@ant-design/fast-color@2.0.6: + resolution: {integrity: sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==} + engines: {node: '>=8.x'} + dependencies: + '@babel/runtime': 7.26.10 + dev: false + + /@ant-design/flowchart@1.2.2(antd@5.24.4)(classnames@2.5.1)(lodash@4.17.21): + 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' + dependencies: + '@antv/layout': 0.1.31 + '@antv/x6': 1.35.1 + '@antv/x6-react-components': 1.1.20(antd@5.24.4) + '@antv/x6-react-shape': 1.6.6(@antv/x6@1.35.1) + '@antv/xflow': 1.1.52(antd@5.24.4)(classnames@2.5.1)(lodash@4.17.21) + antd: 5.24.4(moment@2.30.1) + lodash: 4.17.21 + react-color: 2.17.3 + react-use: 17.3.1 + transitivePeerDependencies: + - classnames + dev: false + + /@ant-design/graphs@1.4.1: + resolution: {integrity: sha512-Qyj7Lnfo0gmbaMzm+9AdrS3fjkg2sFU/ZKaFl7xhgEf5LnX+N/KffIvoT8FsBmrZ9ni3onwlHs1dtYa5QdVhtQ==} + peerDependencies: + react: '>=16.8.4' + react-dom: '>=16.8.4' + dependencies: + '@antv/dom-util': 2.0.4 + '@antv/g6': 4.8.24 + '@antv/layout': 0.1.31 + '@antv/util': 2.0.17 + insert-css: 2.0.0 + react-content-loader: 5.1.4 + dev: false + + /@ant-design/icons-svg@4.4.2: + resolution: {integrity: sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==} + dev: false + + /@ant-design/icons@4.8.3: + resolution: {integrity: sha512-HGlIQZzrEbAhpJR6+IGdzfbPym94Owr6JZkJ2QCCnOkPVIWMO2xgIVcOKnl8YcpijIo39V7l2qQL5fmtw56cMw==} + engines: {node: '>=8'} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + '@ant-design/colors': 6.0.0 + '@ant-design/icons-svg': 4.4.2 + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + lodash: 4.17.21 + rc-util: 5.44.4 + dev: false + + /@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' + dependencies: + '@ant-design/colors': 7.2.0 + '@ant-design/icons-svg': 4.4.2 + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /@ant-design/maps@1.0.8: + resolution: {integrity: sha512-q9Lv14Ekp7j24R9agrTXIINKc1/zslLXfTIWNuoZ0hUq7w1doyEhtLTsuF0n1wcgdKGjAX3wBKQRaVlgz+u8lw==} + peerDependencies: + react: '>=16.8.4' + react-dom: '>=16.8.4' + dependencies: + '@antv/l7': 2.22.5 + '@antv/l7plot': 0.5.11(@antv/l7@2.22.5) + '@antv/util': 2.0.17 + react-content-loader: 5.1.4 + dev: false + + /@ant-design/moment-webpack-plugin@0.0.3: + resolution: {integrity: sha512-MLm1FUpg02fP615ShQnCUN9la2E4RylDxKyolkGqAWTIHO4HyGM0A5x71AMALEyP/bC+UEEWBGSQ+D4/8hQ+ww==} + dev: true + + /@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' + dependencies: + '@antv/g2plot': 2.4.32 + '@antv/util': 2.0.17 + react-content-loader: 5.1.4 + dev: false + + /@ant-design/pro-card@2.9.6(antd@5.24.4): + resolution: {integrity: sha512-boUvowODMhc1l55ZZj/08YwnaggL50fAio2NaA7uXsgpbLduSPL2OE0RyiI24NCqFhPRZMZQHbPOmcHw4Bf3yQ==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + react: '>=17.0.0' + dependencies: + '@ant-design/cssinjs': 1.23.0 + '@ant-design/icons': 5.6.1 + '@ant-design/pro-provider': 2.15.3(antd@5.24.4) + '@ant-design/pro-utils': 2.16.4(antd@5.24.4) + '@babel/runtime': 7.26.10 + antd: 5.24.4(moment@2.30.1) + classnames: 2.5.1 + rc-resize-observer: 1.4.3 + rc-util: 5.44.4 + transitivePeerDependencies: + - react-dom + dev: false + + /@ant-design/pro-components@2.8.6(antd@5.24.4): + resolution: {integrity: sha512-iNd9kTLI0vAYGiyVrpDRflmee+h7486OLXIgIb89g3G+5YS9xSnRuCYt6UBRAEGsB1GRUPznRUGUd6Gsg33V+g==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + react: '>=17.0.0' + react-dom: '>=17.0.0' + dependencies: + '@ant-design/pro-card': 2.9.6(antd@5.24.4) + '@ant-design/pro-descriptions': 2.6.6(antd@5.24.4) + '@ant-design/pro-field': 3.0.3(antd@5.24.4) + '@ant-design/pro-form': 2.31.6(antd@5.24.4) + '@ant-design/pro-layout': 7.22.3(antd@5.24.4) + '@ant-design/pro-list': 2.6.6(antd@5.24.4) + '@ant-design/pro-provider': 2.15.3(antd@5.24.4) + '@ant-design/pro-skeleton': 2.2.1(antd@5.24.4) + '@ant-design/pro-table': 3.18.6(antd@5.24.4) + '@ant-design/pro-utils': 2.16.4(antd@5.24.4) + '@babel/runtime': 7.26.10 + antd: 5.24.4(moment@2.30.1) + transitivePeerDependencies: + - rc-field-form + dev: false + + /@ant-design/pro-descriptions@2.6.6(antd@5.24.4): + resolution: {integrity: sha512-Onwn79P5wNcFNHQmXVdTDgewXt4MCW5snEFctZuCY6T5KwpH7Y9UA8GWtFNIL2KfF5+uu83es20N0E2hg73G0w==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + react: '>=17.0.0' + dependencies: + '@ant-design/pro-field': 3.0.3(antd@5.24.4) + '@ant-design/pro-form': 2.31.6(antd@5.24.4) + '@ant-design/pro-provider': 2.15.3(antd@5.24.4) + '@ant-design/pro-skeleton': 2.2.1(antd@5.24.4) + '@ant-design/pro-utils': 2.16.4(antd@5.24.4) + '@babel/runtime': 7.26.10 + antd: 5.24.4(moment@2.30.1) + rc-resize-observer: 0.2.6 + rc-util: 5.44.4 + transitivePeerDependencies: + - rc-field-form + - react-dom + dev: false + + /@ant-design/pro-field@3.0.3(antd@5.24.4): + resolution: {integrity: sha512-MrDZcx1kP4vpmnSJyHuxeool2o5hDRiJ8aRFloM2M7yW+Tw9ilABMlHFkKz1FLIt4esO9Zc4vd8Iv2ndlkB4/Q==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + react: '>=17.0.0' + dependencies: + '@ant-design/icons': 5.6.1 + '@ant-design/pro-provider': 2.15.3(antd@5.24.4) + '@ant-design/pro-utils': 2.16.4(antd@5.24.4) + '@babel/runtime': 7.26.10 + '@chenshuai2144/sketch-color': 1.0.9 + antd: 5.24.4(moment@2.30.1) + classnames: 2.5.1 + dayjs: 1.11.13 + lodash: 4.17.21 + lodash-es: 4.17.21 + rc-util: 5.44.4 + swr: 2.3.3 + transitivePeerDependencies: + - react-dom + dev: false + + /@ant-design/pro-form@2.31.6(antd@5.24.4): + resolution: {integrity: sha512-pDthX9AjLiryFrtPFY+Ep1z/CfEbhg++K25p7jA6tyl1gVeOIcHVkLTEFMNKmWrc9ZSCA35D/UeSz3bn102GLg==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + rc-field-form: '>=1.22.0' + react: '>=17.0.0' + react-dom: '>=17.0.0' + dependencies: + '@ant-design/icons': 5.6.1 + '@ant-design/pro-field': 3.0.3(antd@5.24.4) + '@ant-design/pro-provider': 2.15.3(antd@5.24.4) + '@ant-design/pro-utils': 2.16.4(antd@5.24.4) + '@babel/runtime': 7.26.10 + '@chenshuai2144/sketch-color': 1.0.9 + '@umijs/use-params': 1.0.9 + antd: 5.24.4(moment@2.30.1) + classnames: 2.5.1 + dayjs: 1.11.13 + lodash: 4.17.21 + lodash-es: 4.17.21 + rc-resize-observer: 1.4.3 + rc-util: 5.44.4 + dev: false + + /@ant-design/pro-layout@7.22.3(antd@5.24.4): + resolution: {integrity: sha512-di/EOMDuoMDRjBweqesYyCxEYr2LCmO82y6A4bSwmmJ6ehxN7HGC73Wx4RuBkzDR7kHLTOXt7WxI6875ENT8mg==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + react: '>=17.0.0' + react-dom: '>=17.0.0' + dependencies: + '@ant-design/cssinjs': 1.23.0 + '@ant-design/icons': 5.6.1 + '@ant-design/pro-provider': 2.15.3(antd@5.24.4) + '@ant-design/pro-utils': 2.16.4(antd@5.24.4) + '@babel/runtime': 7.26.10 + '@umijs/route-utils': 4.0.1 + '@umijs/use-params': 1.0.9 + antd: 5.24.4(moment@2.30.1) + 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 + rc-util: 5.44.4 + swr: 2.3.3 + warning: 4.0.3 + dev: false + + /@ant-design/pro-list@2.6.6(antd@5.24.4): + resolution: {integrity: sha512-Yea/KDd3kjOKklz1AHs66JGvtguvPYYFSaZFXW4m4VBjABHoaF6seo7ySW9UUWgwuoegdGtiglvleYv/rQoEcw==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + react: '>=17.0.0' + react-dom: '>=17.0.0' + dependencies: + '@ant-design/cssinjs': 1.23.0 + '@ant-design/icons': 5.6.1 + '@ant-design/pro-card': 2.9.6(antd@5.24.4) + '@ant-design/pro-field': 3.0.3(antd@5.24.4) + '@ant-design/pro-table': 3.18.6(antd@5.24.4) + '@ant-design/pro-utils': 2.16.4(antd@5.24.4) + '@babel/runtime': 7.26.10 + antd: 5.24.4(moment@2.30.1) + classnames: 2.5.1 + dayjs: 1.11.13 + rc-resize-observer: 1.4.3 + rc-util: 4.21.1 + transitivePeerDependencies: + - rc-field-form + dev: false + + /@ant-design/pro-provider@2.15.3(antd@5.24.4): + resolution: {integrity: sha512-jUBCuRrhAXNMumSZ++704/zEg/7U1k2N3jMVBgtirvVaCAk5O9iZQKK4W3O3LRFc+D8yO16sXjsxhawvdGL4cA==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + react: '>=17.0.0' + react-dom: '>=17.0.0' + dependencies: + '@ant-design/cssinjs': 1.23.0 + '@babel/runtime': 7.26.10 + '@ctrl/tinycolor': 3.6.1 + antd: 5.24.4(moment@2.30.1) + dayjs: 1.11.13 + rc-util: 5.44.4 + swr: 2.3.3 + dev: false + + /@ant-design/pro-skeleton@2.2.1(antd@5.24.4): + resolution: {integrity: sha512-3M2jNOZQZWEDR8pheY00OkHREfb0rquvFZLCa6DypGmiksiuuYuR9Y4iA82ZF+mva2FmpHekdwbje/GpbxqBeg==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + react: '>=17.0.0' + react-dom: '>=17.0.0' + dependencies: + '@babel/runtime': 7.26.10 + antd: 5.24.4(moment@2.30.1) + dev: false + + /@ant-design/pro-table@3.18.6(antd@5.24.4): + resolution: {integrity: sha512-ABXavpJWUOGGcer/WLBpRtzWCbfwZX3T8vAwMbLUQAl1xz3TTgkYzDDTcIdwUmtVdkgJUdWc8GdHWangWW30iQ==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + rc-field-form: '>=1.22.0' + react: '>=17.0.0' + react-dom: '>=17.0.0' + dependencies: + '@ant-design/cssinjs': 1.23.0 + '@ant-design/icons': 5.6.1 + '@ant-design/pro-card': 2.9.6(antd@5.24.4) + '@ant-design/pro-field': 3.0.3(antd@5.24.4) + '@ant-design/pro-form': 2.31.6(antd@5.24.4) + '@ant-design/pro-provider': 2.15.3(antd@5.24.4) + '@ant-design/pro-utils': 2.16.4(antd@5.24.4) + '@babel/runtime': 7.26.10 + '@dnd-kit/core': 6.3.1 + '@dnd-kit/modifiers': 6.0.1(@dnd-kit/core@6.3.1) + '@dnd-kit/sortable': 7.0.2(@dnd-kit/core@6.3.1) + '@dnd-kit/utilities': 3.2.2 + antd: 5.24.4(moment@2.30.1) + classnames: 2.5.1 + dayjs: 1.11.13 + lodash: 4.17.21 + lodash-es: 4.17.21 + rc-resize-observer: 1.4.3 + rc-util: 5.44.4 + dev: false + + /@ant-design/pro-utils@2.16.4(antd@5.24.4): + resolution: {integrity: sha512-PFxqF0fsUsLj8ORvJSuMgVv9NDHwAxZaglzPN/u3jZX7rWYcrHD04EMJEXooZaSyT6Q4+j7SqXDx6oBsdb9zNw==} + peerDependencies: + antd: ^4.24.15 || ^5.11.2 + react: '>=17.0.0' + react-dom: '>=17.0.0' + dependencies: + '@ant-design/icons': 5.6.1 + '@ant-design/pro-provider': 2.15.3(antd@5.24.4) + '@babel/runtime': 7.26.10 + antd: 5.24.4(moment@2.30.1) + classnames: 2.5.1 + dayjs: 1.11.13 + lodash: 4.17.21 + lodash-es: 4.17.21 + rc-util: 5.44.4 + safe-stable-stringify: 2.5.0 + swr: 2.3.3 + dev: false + + /@ant-design/react-slick@1.0.2: + resolution: {integrity: sha512-Wj8onxL/T8KQLFFiCA4t8eIRGpRR+UPgOdac2sYzonv+i0n3kXHmvHLLiOYL655DQx2Umii9Y9nNgL7ssu5haQ==} + peerDependencies: + react: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + json2mq: 0.2.0 + resize-observer-polyfill: 1.5.1 + throttle-debounce: 5.0.2 + dev: false + + /@ant-design/react-slick@1.1.2: + resolution: {integrity: sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==} + peerDependencies: + react: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + json2mq: 0.2.0 + resize-observer-polyfill: 1.5.1 + throttle-debounce: 5.0.2 + dev: false + + /@antv/adjust@0.2.5: + resolution: {integrity: sha512-MfWZOkD9CqXRES6MBGRNe27Q577a72EIwyMnE29wIlPliFvJfWwsrONddpGU7lilMpVKecS3WAzOoip3RfPTRQ==} + dependencies: + '@antv/util': 2.0.17 + tslib: 1.14.1 + dev: false + + /@antv/algorithm@0.1.26: + resolution: {integrity: sha512-DVhcFSQ8YQnMNW34Mk8BSsfc61iC1sAnmcfYoXTAshYHuU50p/6b7x3QYaGctDNKWGvi1ub7mPcSY0bK+aN0qg==} + dependencies: + '@antv/util': 2.0.17 + tslib: 2.8.1 + dev: false + + /@antv/async-hook@2.2.9: + resolution: {integrity: sha512-4BUp2ZUaTi2fYL67Ltkf6eV912rYJeSBokGhd5fhhnpUkMA1LEI1mg97Pqmx3yC50VEQ+LKXZxj9ePZs80ECfw==} + dependencies: + async: 3.2.6 + dev: false + + /@antv/attr@0.3.5: + resolution: {integrity: sha512-wuj2gUo6C8Q2ASSMrVBuTcb5LcV+Tc0Egiy6bC42D0vxcQ+ta13CLxgMmHz8mjD0FxTPJDXSciyszRSC5TdLsg==} + dependencies: + '@antv/color-util': 2.0.6 + '@antv/scale': 0.3.18 + '@antv/util': 2.0.17 + tslib: 2.8.1 + dev: false + + /@antv/color-util@2.0.6: + resolution: {integrity: sha512-KnPEaAH+XNJMjax9U35W67nzPI+QQ2x27pYlzmSIWrbj4/k8PGrARXfzDTjwoozHJY8qG62Z+Ww6Alhu2FctXQ==} + dependencies: + '@antv/util': 2.0.17 + tslib: 2.8.1 + dev: false + + /@antv/component@0.8.35: + resolution: {integrity: sha512-VnRa5X77nBPI952o2xePEEMSNZ6g2mcUDrQY8mVL2kino/8TFhqDq5fTRmDXZyWyIYd4ulJTz5zgeSwAnX/INQ==} + 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 + dev: false + + /@antv/coord@0.3.1: + resolution: {integrity: sha512-rFE94C8Xzbx4xmZnHh2AnlB3Qm1n5x0VT3OROy257IH6Rm4cuzv1+tZaUBATviwZd99S+rOY9telw/+6C9GbRw==} + dependencies: + '@antv/matrix-util': 3.1.0-beta.3 + '@antv/util': 2.0.17 + tslib: 2.8.1 + dev: false + + /@antv/dom-util@2.0.4: + resolution: {integrity: sha512-2shXUl504fKwt82T3GkuT4Uoc6p9qjCKnJ8gXGLSW4T1W37dqf9AV28aCfoVPHp2BUXpSsB+PAJX2rG/jLHsLQ==} + dependencies: + tslib: 2.8.1 + dev: false + + /@antv/event-emitter@0.1.3: + resolution: {integrity: sha512-4ddpsiHN9Pd4UIlWuKVK1C4IiZIdbwQvy9i7DUSI3xNJ89FPUFt8lxDYj8GzzfdllV0NkJTRxnG+FvLk0llidg==} + dev: false + + /@antv/g-base@0.4.7: + resolution: {integrity: sha512-wKSpS3/M1slU92iOgi2QV4MCd82J1d2PyPcQArqSFRUZU0KnVMIl95v79dG0Be4YvFaZ3bVrT6Ns1Czr8oplhA==} + 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 + dev: false + + /@antv/g-base@0.5.16: + resolution: {integrity: sha512-jP06wggTubDPHXoKwFg3/f1lyxBX9ywwN3E/HG74Nd7DXqOXQis8tsIWW+O6dS/h9vyuXLd1/wDWkMMm3ZzXdg==} + 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 + dev: false + + /@antv/g-canvas@0.4.15: + resolution: {integrity: sha512-+Du37T7dhU1F8GiaWu+EMtBDHoYOg8UzCoVBFD+cUEs/joLaOVkup3drvGC/6MSyLiI32y/ZHuuc08pZIP7PzA==} + 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 + dev: false + + /@antv/g-canvas@0.5.17: + resolution: {integrity: sha512-sXYJMWTOlb/Ycb6sTKu00LcJqInXJY4t99+kSM40u2OfqrXYmaXDjHR7D2V0roMkbK/QWiWS9UnEidCR1VtMOA==} + 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 + dev: false + + /@antv/g-device-api@1.6.13: + resolution: {integrity: sha512-lTvlSHYDZyWJnAR1W8DOQLwUo32VpRopbS/BPQqStcOV6FqaC+u5YjT50KbJ+oBWcorpzfknhICRwEA3Xm8t9Q==} + dependencies: + '@antv/util': 3.3.10 + '@webgpu/types': 0.1.56 + eventemitter3: 5.0.1 + gl-matrix: 3.4.3 + tslib: 2.8.1 + dev: false + + /@antv/g-math@0.1.9: + resolution: {integrity: sha512-KHMSfPfZ5XHM1PZnG42Q2gxXfOitYveNTA7L61lR6mhZ8Y/aExsYmHqaKBsSarU0z+6WLrl9C07PQJZaw0uljQ==} + dependencies: + '@antv/util': 2.0.17 + gl-matrix: 3.4.3 + dev: false + + /@antv/g-svg@0.4.7: + resolution: {integrity: sha512-+lqlBK+qylP4t/vyUgEaPthp1XmTiImfkPl/ZmRp3L1knH64OI9XTfOGGuBUFAt3JBt7VHKf6t0L/MCf0BR88Q==} + dependencies: + '@antv/g-base': 0.4.7 + '@antv/g-math': 0.1.9 + '@antv/util': 2.0.17 + detect-browser: 4.8.0 + dev: false + + /@antv/g-svg@0.5.7: + resolution: {integrity: sha512-jUbWoPgr4YNsOat2Y/rGAouNQYGpw4R0cvlN0YafwOyacFFYy2zC8RslNd6KkPhhR3XHNSqJOuCYZj/YmLUwYw==} + 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 + dev: false + + /@antv/g-webgpu-core@0.5.6: + resolution: {integrity: sha512-DPiH3GkAUiT0Q+LAKeImpI+IOQ/gP2w6HstYKivpFIpBPIvZ/9equM3icVrn1iDfDkZANVXQ1PppcO3xBv1ZTw==} + 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 + dev: false + + /@antv/g-webgpu-core@0.7.2: + resolution: {integrity: sha512-xUMmop7f3Rs34zFYKXLqHhDR1CQTeDl/7vI7Sn3X/73BqJc3X3HIIRvm83Fg2CjVACaOzw4WeLRXNaOCp9fz9w==} + dependencies: + eventemitter3: 4.0.7 + gl-matrix: 3.4.3 + lodash: 4.17.21 + probe.gl: 3.6.0 + dev: false + + /@antv/g-webgpu-engine@0.5.6: + resolution: {integrity: sha512-D311qYUefdEFwLayutIHqucrAY3cAGH3BdnXS37nq+0nsglrHcNP0Ab1YTinn9RihLoY3yXFTLzrYkJHJbZXDg==} + 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 + dev: false + + /@antv/g-webgpu-engine@0.7.2: + resolution: {integrity: sha512-lx8Y93IW2cnJvdoDRKyMmTdYqSC1pOmF0nyG3PGGyA0NI9vBYVgO0KTF6hkyWjdTWVq7XDZyf/h8CJridLh3lg==} + dependencies: + '@antv/g-webgpu-core': 0.7.2 + gl-matrix: 3.4.3 + lodash: 4.17.21 + regl: 1.7.0 + dev: false + + /@antv/g-webgpu@0.5.5: + resolution: {integrity: sha512-TxtBniINFq1jFGEPo46xjJfrbJbUqkFd5wmsRs3tcg/7J7xoldOP1kEadpI3AJG9knMYdE92VpILw1VPd6DgzQ==} + 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 + dev: false + + /@antv/g-webgpu@0.7.2: + resolution: {integrity: sha512-kw+oYGsdvj5qeUfy5DPb/jztZBV+2fmqBd3Vv8NlKatfBmv8AirYX/CCW74AUSdWm99rEiLyxFB1VdRZ6b/wnQ==} + 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 + dev: false + + /@antv/g2@4.2.11: + resolution: {integrity: sha512-QiqxLLYDWkv9c4oTcXscs6NMxBuWZ1JCarHPZ27J43IN2BV+qUKw8yce0A8CBR8fCILEFqQAfS00Szqpye036Q==} + 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 + dev: false + + /@antv/g2plot@2.4.32: + resolution: {integrity: sha512-HTBuAMa+PJ6DqY1XCX1GBNTGz/IBmn9lx2xu18NQSHtgXAIHWSF+WYs7Aj8iaujcapM8g+IPgjS6ObO1u9CbFg==} + 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 + dev: false + + /@antv/g6-core@0.8.24: + resolution: {integrity: sha512-rgI3dArAD8uoSz2+skS4ctN4x/Of33ivTIKaEYYvClxgkLZWVz9zvocy+5AWcVPBHZsAXkZcdh9zndIoWY/33A==} + 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 + dev: false + + /@antv/g6-element@0.8.24(@antv/g6@4.8.24): + resolution: {integrity: sha512-61FXkt9LY+6EOUtSam1iFTOW2AM59sPVcV1BuPj4dXiD0dluLE+R7d8B/94g1tKDw9tsjhfUQGC7hTXscJRJFw==} + peerDependencies: + '@antv/g6': 4.8.24 + dependencies: + '@antv/g-base': 0.5.16 + '@antv/g6': 4.8.24 + '@antv/g6-core': 0.8.24 + '@antv/util': 2.0.17 + tslib: 2.8.1 + dev: false + + /@antv/g6-pc@0.8.24(@antv/g6@4.8.24): + resolution: {integrity: sha512-nf0y1lrp8J5DotqRryXd2S/J30COW8spVcLF9gUqywGqQAHfE00Ywkqr+PZBnsfCZXsXCi9o0+CE9NrkWs4SBQ==} + 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.24(@antv/g6@4.8.24) + '@antv/g6-plugin': 0.8.24(@antv/g6@4.8.24) + '@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' + dev: false + + /@antv/g6-plugin@0.8.24(@antv/g6@4.8.24): + resolution: {integrity: sha512-ZIOnwLTC7SM2bFiJZ3vYFWnkyOCWKqnU96i/fBh1qAoY5slDS3hatenZWEXUtOcqaKw1h+5A5f72MRXqBBVn0g==} + peerDependencies: + '@antv/g6': 4.8.24 + 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.24 + '@antv/g6-core': 0.8.24 + '@antv/g6-element': 0.8.24(@antv/g6@4.8.24) + '@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 + dev: false + + /@antv/g6@3.4.10: + resolution: {integrity: sha512-SsPffvyFpPQ1764XOCkadlIFT7DlX7Y6EBLPD4obU8tXV3udk+yFf+qw4OzgZjN+3/eEYQOZgzVSPRpr8TTkyw==} + 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 + dev: false + + /@antv/g6@4.8.24: + resolution: {integrity: sha512-bgj7sZ+z45JmOngIpYpwmSIg7SboMLZBoAlX0+RoAETZB3/xvZO0MXT3lCSyAhIgm5Sb68pekKi7OStuo04NyQ==} + dependencies: + '@antv/g6-pc': 0.8.24(@antv/g6@4.8.24) + dev: false + + /@antv/gl-matrix@2.7.1: + resolution: {integrity: sha512-oOWcVNlpELIKi9x+Mm1Vwbz8pXfkbJKykoCIOJ/dNK79hSIANbpXJ5d3Rra9/wZqK6MC961B7sybFhPlLraT3Q==} + dev: false + + /@antv/graphlib@1.2.0: + resolution: {integrity: sha512-hhJOMThec51nU4Fe5p/viLlNIL71uDEgYFzKPajWjr2715SFG1HAgiP6AVylIeqBcAZ04u3Lw7usjl/TuI5RuQ==} + dev: false + + /@antv/hierarchy@0.6.14: + resolution: {integrity: sha512-V3uknf7bhynOqQDw2sg+9r9DwZ9pc6k/EcqyTFdfXB1+ydr7urisP0MipIuimucvQKN+Qkd+d6w601r1UIroqQ==} + dev: false + + /@antv/l7-component@2.22.5: + resolution: {integrity: sha512-rkvz17V2os7VTwD8qP1ooxtiTglTA+KvQq3XTlCKbNujdTH3KQ5hXzJtuZm8ZVE2iRczJVSMeM8FKSKoZM4SQQ==} + dependencies: + '@antv/l7-core': 2.22.5 + '@antv/l7-layers': 2.22.5 + '@antv/l7-utils': 2.22.5 + '@babel/runtime': 7.26.10 + eventemitter3: 4.0.7 + supercluster: 7.1.5 + dev: false + + /@antv/l7-core@2.22.5: + resolution: {integrity: sha512-L3iRkjFTmQ4AIQQylhAbV81p9shZyZ4w+3vzDmqm7+vHdFFVprn8eRrUH+o2/li7nYGE5cL8w/GeYvzZhHMlFg==} + dependencies: + '@antv/async-hook': 2.2.9 + '@antv/l7-utils': 2.22.5 + '@babel/runtime': 7.26.10 + '@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 + dev: false + + /@antv/l7-layers@2.22.5: + resolution: {integrity: sha512-k++HXple1PmpusUkuEmUAMfxfyARSloMOIqDY7nKfxJBd9rCxkvcsJS+ypHt9Zj29sSvBKvSfLNMOF0yFP+7fQ==} + 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.26.10 + '@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 + dev: false + + /@antv/l7-map@2.22.5: + resolution: {integrity: sha512-EAVZRNHy7zWWLXNnshllqRMIywAgaXIbIDw1VGqVC236VsAqvRaCx8Moy88RG+hU7SPET0+RnQrWK4WYGbR2+A==} + dependencies: + '@antv/l7-utils': 2.22.5 + '@babel/runtime': 7.26.10 + '@mapbox/point-geometry': 0.1.0 + '@mapbox/unitbezier': 0.0.1 + eventemitter3: 4.0.7 + gl-matrix: 3.4.3 + dev: false + + /@antv/l7-maps@2.22.5: + resolution: {integrity: sha512-HzCRvArZg5u00jDs2H7xQmJxnWDCDrG9dIVHxI2DQBGUr22CtMnY/T4g7plb7uwTzzqtvfferDAF8i4ik/GtuA==} + 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.26.10 + 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 + dev: false + + /@antv/l7-renderer@2.22.5: + resolution: {integrity: sha512-AEyNC6cq3cPARcOgbrSyQOcobvrm3ibEoBAqpuRsvg2/fc3kp4wsmgESQcfq1efaoS2HElYGUJbIFSWHCWB07Q==} + dependencies: + '@antv/g-device-api': 1.6.13 + '@antv/l7-core': 2.22.5 + '@antv/l7-utils': 2.22.5 + '@babel/runtime': 7.26.10 + regl: 1.6.1 + dev: false + + /@antv/l7-scene@2.22.5: + resolution: {integrity: sha512-Qd+Ls37Hu68oz9/IFELmq//EXJvHiqef54rp2agwCt/+qsHLheeuLdc5AnL3LcVRGtJ5adrFb/9Hz+3I7FAtnQ==} + 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.26.10 + eventemitter3: 4.0.7 + dev: false + + /@antv/l7-source@2.22.5: + resolution: {integrity: sha512-AxplpwJztCJxpulJz8cuiG2zXUvD5fQb97rLNfTcOpCck7gKdSx19QuonYWjyiJC/gHz7EeyYvMjrneFWW5fIw==} + dependencies: + '@antv/async-hook': 2.2.9 + '@antv/l7-core': 2.22.5 + '@antv/l7-utils': 2.22.5 + '@babel/runtime': 7.26.10 + '@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 + dev: false + + /@antv/l7-utils@2.22.5: + resolution: {integrity: sha512-A7jItppeAcKOfuizqOf3iXRGePEZCrjw/BlwULgLbgj/dzh03CA2sfAgVWkSce4Jkv6xdCNE/fYOsT8oWw3o5g==} + dependencies: + '@babel/runtime': 7.26.10 + '@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 + dev: false + + /@antv/l7@2.22.5: + resolution: {integrity: sha512-J3paaGznerwSarr88DXJDWwI8zJz8H/nB9kgZJPAm/uu5rj6oPYCtXHlwa+sdGiYImRU60CcS+qc/8HC833NzA==} + 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.26.10 + dev: false + + /@antv/l7plot-component@0.0.11: + resolution: {integrity: sha512-aIl9K6I5MwMIU+Xxq/oOKXn0roAg5c73RjCXNmbTu8kxFEUUvCqU/35EDtfhWY7JKJeKnWRcl0fgDmTrD0t4iA==} + dependencies: + '@antv/dom-util': 2.0.4 + '@antv/util': 2.0.17 + dev: false + + /@antv/l7plot@0.5.11(@antv/l7@2.22.5): + resolution: {integrity: sha512-nSHyTzmbvQ8bq4eiD8L5hAPSZxZhmXRZ+j2Zi59iFy8hcR/XxV0N5RN8BkewiL1Zj7IPYXFtkAvBieEznae2UQ==} + peerDependencies: + '@antv/l7': ^2.21.0 + 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 + dev: false + + /@antv/layout@0.1.31: + resolution: {integrity: sha512-iz9i19dOJGiZr5xBWI5sfG+2K3QVMNAGOBrbjWKH2RGLvGpf2TSFySidhz0siDrcQA46cDsjLmGstezQdgeGzA==} + dependencies: + '@antv/g-webgpu': 0.5.5 + '@dagrejs/graphlib': 2.1.4 + d3-force: 2.1.1 + ml-matrix: 6.12.1 + dev: false + + /@antv/layout@0.3.25(dagre@0.8.5): + resolution: {integrity: sha512-d29Aw1PXoAavMRZy7iTB9L5rMBeChFEX0BJ9ELP4TI35ySdCu07YbmPo9ju9OH/6sG2/NB3o85Ayxrre3iwX/g==} + 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 + dev: false + + /@antv/matrix-util@2.0.7: + resolution: {integrity: sha512-bogifQY8jplWtSTZsPqBOdBlDdkM7IwDqYL8eMYL8OaSyOPCS7l9bnEQjQ9qTAwfCd7wHTuPoCnCpbiR8BYFvQ==} + dependencies: + '@antv/gl-matrix': 2.7.1 + '@antv/util': 2.0.17 + tslib: 1.14.1 + dev: false + + /@antv/matrix-util@3.0.4: + resolution: {integrity: sha512-BAPyu6dUliHcQ7fm9hZSGKqkwcjEDVLVAstlHULLvcMZvANHeLXgHEgV7JqcAV/GIhIz8aZChIlzM1ZboiXpYQ==} + dependencies: + '@antv/util': 2.0.17 + gl-matrix: 3.4.3 + tslib: 2.8.1 + dev: false + + /@antv/matrix-util@3.1.0-beta.3: + resolution: {integrity: sha512-W2R6Za3A6CmG51Y/4jZUM/tFgYSq7vTqJL1VD9dKrvwxS4sE0ZcXINtkp55CdyBwJ6Cwm8pfoRpnD4FnHahN0A==} + dependencies: + '@antv/util': 2.0.17 + gl-matrix: 3.4.3 + tslib: 2.8.1 + dev: false + + /@antv/path-util@2.0.15: + resolution: {integrity: sha512-R2VLZ5C8PLPtr3VciNyxtjKqJ0XlANzpFb5sE9GE61UQqSRuSVSzIakMxjEPrpqbgc+s+y8i+fmc89Snu7qbNw==} + dependencies: + '@antv/matrix-util': 3.0.4 + '@antv/util': 2.0.17 + tslib: 2.8.1 + dev: false + + /@antv/path-util@3.0.1: + resolution: {integrity: sha512-tpvAzMpF9Qm6ik2YSMqICNU5tco5POOW7S4XoxZAI/B0L26adU+Md/SmO0BBo2SpuywKvzPH3hPT3xmoyhr04Q==} + dependencies: + gl-matrix: 3.4.3 + lodash-es: 4.17.21 + tslib: 2.8.1 + dev: false + + /@antv/scale@0.3.18: + resolution: {integrity: sha512-GHwE6Lo7S/Q5fgaLPaCsW+CH+3zl4aXpnN1skOiEY0Ue9/u+s2EySv6aDXYkAqs//i0uilMDD/0/4n8caX9U9w==} + dependencies: + '@antv/util': 2.0.17 + fecha: 4.2.3 + tslib: 2.8.1 + dev: false + + /@antv/util@2.0.17: + resolution: {integrity: sha512-o6I9hi5CIUvLGDhth0RxNSFDRwXeywmt6ExR4+RmVAzIi48ps6HUy+svxOCayvrPBN37uE6TAc2KDofRo0nK9Q==} + dependencies: + csstype: 3.1.3 + tslib: 2.8.1 + dev: false + + /@antv/util@3.3.10: + resolution: {integrity: sha512-basGML3DFA3O87INnzvDStjzS+n0JLEhRnRsDzP9keiXz8gT1z/fTdmJAZFOzMMWxy+HKbi7NbSt0+8vz/OsBQ==} + dependencies: + fast-deep-equal: 3.1.3 + gl-matrix: 3.4.3 + tslib: 2.8.1 + dev: false + + /@antv/x6-react-components@1.1.20(antd@5.24.4): + 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' + dependencies: + antd: 5.24.4(moment@2.30.1) + clamp: 1.0.1 + classnames: 2.5.1 + rc-dropdown: 3.6.2 + rc-util: 4.21.1 + react-color: 2.17.1 + react-resize-detector: 7.1.2 + ua-parser-js: 0.7.40 + dev: false + + /@antv/x6-react-shape@1.6.6(@antv/x6@1.35.1): + 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' + dependencies: + '@antv/x6': 1.35.1 + dev: false + + /@antv/x6@1.35.1: + resolution: {integrity: sha512-XLFSGbcT/MOI883YKql9J/CqHUCPZxgwfel+sNN1eQbHA+JXYsGt0t9+IJ1qieaYAlxjgio5up+S9I0n+8QL/A==} + dependencies: + csstype: 3.1.3 + jquery: 3.7.1 + jquery-mousewheel: 3.1.13 + lodash-es: 4.17.21 + mousetrap: 1.6.5 + utility-types: 3.11.0 + dev: false + + /@antv/xflow-core@1.1.52(@antv/x6-react-components@1.1.20)(@antv/x6-react-shape@1.6.6)(@antv/x6@1.35.1)(antd@5.24.4)(lodash@4.17.21): + 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 + dependencies: + '@antv/x6': 1.35.1 + '@antv/x6-react-components': 1.1.20(antd@5.24.4) + '@antv/x6-react-shape': 1.6.6(@antv/x6@1.35.1) + '@antv/xflow-hook': 1.0.52 + antd: 5.24.4(moment@2.30.1) + classnames: 2.5.1 + immer: 9.0.21 + lodash: 4.17.21 + mana-common: 0.3.2 + mana-syringe: 0.2.2 + reflect-metadata: 0.1.14 + rxjs: 6.6.7 + dev: false + + /@antv/xflow-extension@1.1.52(@antv/x6-react-components@1.1.20)(@antv/x6-react-shape@1.6.6)(@antv/x6@1.35.1)(antd@5.24.4)(classnames@2.5.1)(lodash@4.17.21): + 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 + dependencies: + '@antv/x6': 1.35.1 + '@antv/x6-react-components': 1.1.20(antd@5.24.4) + '@antv/x6-react-shape': 1.6.6(@antv/x6@1.35.1) + '@antv/xflow-core': 1.1.52(@antv/x6-react-components@1.1.20)(@antv/x6-react-shape@1.6.6)(@antv/x6@1.35.1)(antd@5.24.4)(lodash@4.17.21) + '@antv/xflow-hook': 1.0.52 + antd: 5.24.4(moment@2.30.1) + classnames: 2.5.1 + mana-syringe: 0.2.2 + moment: 2.30.1 + rc-field-form: 1.44.0 + react-color: 2.17.1 + reflect-metadata: 0.1.14 + transitivePeerDependencies: + - lodash + dev: false + + /@antv/xflow-hook@1.0.52: + resolution: {integrity: sha512-qyheVO5bwhDjKGSldf3pkneowf8ZCydIIrX4n8LRTFpvVhVF9cPoXG9e6+1LhIFvSEaLAJcYBH4gNqAjRrbUYw==} + dependencies: + toposort: 2.0.2 + dev: false + + /@antv/xflow-hook@1.1.52: + resolution: {integrity: sha512-wQfJgCxZG/PYH4DhpcfOi8Js0gHlVmTMHYVJ4DZMvGPcuhEhic0vOtyd9cie0YPzWPufw6lBKtn3/0FY3yHapg==} + dependencies: + toposort: 2.0.2 + dev: false + + /@antv/xflow@1.1.52(antd@5.24.4)(classnames@2.5.1)(lodash@4.17.21): + 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 + dependencies: + '@antv/layout': 0.1.31 + '@antv/x6': 1.35.1 + '@antv/x6-react-components': 1.1.20(antd@5.24.4) + '@antv/x6-react-shape': 1.6.6(@antv/x6@1.35.1) + '@antv/xflow-core': 1.1.52(@antv/x6-react-components@1.1.20)(@antv/x6-react-shape@1.6.6)(@antv/x6@1.35.1)(antd@5.24.4)(lodash@4.17.21) + '@antv/xflow-extension': 1.1.52(@antv/x6-react-components@1.1.20)(@antv/x6-react-shape@1.6.6)(@antv/x6@1.35.1)(antd@5.24.4)(classnames@2.5.1)(lodash@4.17.21) + '@antv/xflow-hook': 1.1.52 + antd: 5.24.4(moment@2.30.1) + lodash: 4.17.21 + transitivePeerDependencies: + - classnames + dev: false + + /@apideck/better-ajv-errors@0.3.6(ajv@8.17.1): + resolution: {integrity: sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==} + engines: {node: '>=10'} + peerDependencies: + ajv: '>=8' + dependencies: + ajv: 8.17.1 + json-schema: 0.4.0 + jsonpointer: 5.0.1 + leven: 3.1.0 + dev: false + + /@babel/code-frame@7.26.2: + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + /@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'} + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.10 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.18.6) + '@babel/helpers': 7.26.10 + '@babel/parser': 7.26.10 + '@babel/template': 7.26.9 + '@babel/traverse': 7.26.10 + '@babel/types': 7.26.10 + 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: + resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.10 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) + '@babel/helpers': 7.26.10 + '@babel/parser': 7.26.10 + '@babel/template': 7.26.9 + '@babel/traverse': 7.26.10 + '@babel/types': 7.26.10 + 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 + dev: false + + /@babel/eslint-parser@7.26.10(@babel/core@7.26.10)(eslint@9.22.0): + resolution: {integrity: sha512-QsfQZr4AiLpKqn7fz+j7SN+f43z2DZCgGyYbNJ2vJOqKfG4E6MZer1+jqGZqKJaxq/gdO2DC/nUu45+pOL5p2Q==} + 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 + dependencies: + '@babel/core': 7.26.10 + '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 + eslint: 9.22.0 + eslint-visitor-keys: 2.1.0 + semver: 6.3.1 + dev: false + + /@babel/generator@7.26.10: + resolution: {integrity: sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/parser': 7.26.10 + '@babel/types': 7.26.10 + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.1.0 + + /@babel/helper-annotate-as-pure@7.25.9: + resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.26.10 + dev: false + + /@babel/helper-compilation-targets@7.26.5: + resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} + engines: {node: '>=6.9.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.26.9(@babel/core@7.26.10): + resolution: {integrity: sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + 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.26.10 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/helper-create-regexp-features-plugin@7.26.3(@babel/core@7.26.10): + resolution: {integrity: sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-annotate-as-pure': 7.25.9 + regexpu-core: 6.2.0 + semver: 6.3.1 + dev: false + + /@babel/helper-define-polyfill-provider@0.6.3(@babel/core@7.26.10): + resolution: {integrity: sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + debug: 4.4.0 + lodash.debounce: 4.0.8 + resolve: 1.22.10 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/helper-member-expression-to-functions@7.25.9: + resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/traverse': 7.26.10 + '@babel/types': 7.26.10 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/helper-module-imports@7.25.9: + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/traverse': 7.26.10 + '@babel/types': 7.26.10 + transitivePeerDependencies: + - supports-color + + /@babel/helper-module-transforms@7.26.0(@babel/core@7.18.6): + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.18.6 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.26.10 + transitivePeerDependencies: + - supports-color + + /@babel/helper-module-transforms@7.26.0(@babel/core@7.26.10): + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.26.10 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/helper-optimise-call-expression@7.25.9: + resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.26.10 + dev: false + + /@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(@babel/core@7.26.10): + resolution: {integrity: sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-wrap-function': 7.25.9 + '@babel/traverse': 7.26.10 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/helper-replace-supers@7.26.5(@babel/core@7.26.10): + resolution: {integrity: sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + 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.26.10 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/helper-skip-transparent-expression-wrappers@7.25.9: + resolution: {integrity: sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/traverse': 7.26.10 + '@babel/types': 7.26.10 + transitivePeerDependencies: + - supports-color + dev: false + + /@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'} + dependencies: + '@babel/template': 7.26.9 + '@babel/traverse': 7.26.10 + '@babel/types': 7.26.10 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/helpers@7.26.10: + resolution: {integrity: sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.26.9 + '@babel/types': 7.26.10 + + /@babel/parser@7.26.10: + resolution: {integrity: sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.26.10 + + /@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.26.10 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + 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 + dev: false + + /@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.26.10 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.26.10): + 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 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-proposal-decorators@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.26.9(@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 + dev: false + + /@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.26.10): + 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 + 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) + dev: false + + /@babel/plugin-proposal-numeric-separator@7.18.6(@babel/core@7.26.10): + 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 + 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) + dev: false + + /@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.26.10): + 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 + 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 + dev: false + + /@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.26.10): + 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 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.10): + resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + dev: false + + /@babel/plugin-proposal-private-property-in-object@7.21.11(@babel/core@7.26.10): + 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 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@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 + dev: false + + /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.18.6): + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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): + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.18.6): + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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): + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.18.6): + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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): + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.18.6): + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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): + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-decorators@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-flow@7.26.0(@babel/core@7.26.10): + resolution: {integrity: sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-import-assertions@7.26.0(@babel/core@7.26.10): + resolution: {integrity: sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.18.6): + resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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): + resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.18.6): + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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): + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.18.6): + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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): + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.18.6): + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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): + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.18.6): + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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): + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.18.6): + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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): + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.18.6): + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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): + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.18.6): + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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): + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.18.6): + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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): + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.18.6): + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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): + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.18.6): + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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): + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.26.10): + resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-arrow-functions@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-async-generator-functions@7.26.8(@babel/core@7.26.10): + resolution: {integrity: sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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.26.10 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-transform-async-to-generator@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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 + dev: false + + /@babel/plugin-transform-block-scoped-functions@7.26.5(@babel/core@7.26.10): + resolution: {integrity: sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-block-scoping@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-class-properties@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-transform-class-static-block@7.26.0(@babel/core@7.26.10): + resolution: {integrity: sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-transform-classes@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.10) + '@babel/traverse': 7.26.10 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-transform-computed-properties@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/template': 7.26.9 + dev: false + + /@babel/plugin-transform-destructuring@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-dotall-regex@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-duplicate-keys@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-dynamic-import@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-exponentiation-operator@7.26.3(@babel/core@7.26.10): + resolution: {integrity: sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-export-namespace-from@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-flow-strip-types@7.26.5(@babel/core@7.26.10): + resolution: {integrity: sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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) + dev: false + + /@babel/plugin-transform-for-of@7.26.9(@babel/core@7.26.10): + resolution: {integrity: sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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 + dev: false + + /@babel/plugin-transform-function-name@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.26.10 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-transform-json-strings@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-literals@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-logical-assignment-operators@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-member-expression-literals@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-modules-amd@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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 + dev: false + + /@babel/plugin-transform-modules-commonjs@7.26.3(@babel/core@7.26.10): + resolution: {integrity: sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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 + dev: false + + /@babel/plugin-transform-modules-systemjs@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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.26.10 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-transform-modules-umd@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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 + dev: false + + /@babel/plugin-transform-named-capturing-groups-regex@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-new-target@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-nullish-coalescing-operator@7.26.6(@babel/core@7.26.10): + resolution: {integrity: sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-numeric-separator@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-object-rest-spread@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.10) + dev: false + + /@babel/plugin-transform-object-super@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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 + dev: false + + /@babel/plugin-transform-optional-catch-binding@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-optional-chaining@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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 + dev: false + + /@babel/plugin-transform-parameters@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-private-methods@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-transform-private-property-in-object@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-transform-property-literals@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-react-constant-elements@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-Ncw2JFsJVuvfRsa2lSHiC55kETQVLSnsYGQ1JDDwkUeWGTL/8Tom8aLTnlqgoeuopWrbbGndrc9AlLYrIosrow==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-react-display-name@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-react-jsx-development@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.10) + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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.26.10 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-transform-react-pure-annotations@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-regenerator@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + regenerator-transform: 0.15.2 + dev: false + + /@babel/plugin-transform-regexp-modifiers@7.26.0(@babel/core@7.26.10): + resolution: {integrity: sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-reserved-words@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-runtime@7.26.10(@babel/core@7.26.10): + resolution: {integrity: sha512-NWaL2qG6HRpONTnj4JvDU6th4jYeZOJgu3QhmFTCihib0ermtOJqktA5BduGm3suhhVe9EMP9c9+mfJ/I9slqw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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.12(@babel/core@7.26.10) + babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.26.10) + babel-plugin-polyfill-regenerator: 0.6.3(@babel/core@7.26.10) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/plugin-transform-shorthand-properties@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-spread@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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 + dev: false + + /@babel/plugin-transform-sticky-regex@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-template-literals@7.26.8(@babel/core@7.26.10): + resolution: {integrity: sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-typeof-symbol@7.26.7(@babel/core@7.26.10): + resolution: {integrity: sha512-jfoTXXZTgGg36BmhqT3cAYK5qkmqvJpvNrPhaK/52Vgjhw4Rq29s9UqpWWV0D6yuRmgiFH/BUVlkl96zJWqnaw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-typescript@7.26.8(@babel/core@7.26.10): + resolution: {integrity: sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@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 + dev: false + + /@babel/plugin-transform-unicode-escapes@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-unicode-property-regex@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-unicode-regex@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/plugin-transform-unicode-sets-regex@7.25.9(@babel/core@7.26.10): + resolution: {integrity: sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + dev: false + + /@babel/preset-env@7.26.9(@babel/core@7.26.10): + resolution: {integrity: sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/core': 7.26.10 + '@babel/helper-compilation-targets': 7.26.5 + '@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.25.9(@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.25.9(@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.26.7(@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.12(@babel/core@7.26.10) + babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.26.10) + babel-plugin-polyfill-regenerator: 0.6.3(@babel/core@7.26.10) + core-js-compat: 3.41.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.26.10): + 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 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/types': 7.26.10 + esutils: 2.0.3 + dev: false + + /@babel/preset-react@7.26.3(@babel/core@7.26.10): + resolution: {integrity: sha512-Nl03d6T9ky516DGK2YMxrTqvnpUW63TnJMOMonj+Zae0JiPC5BC9xPMSL6L8fiSpA5vP88qfygavVQvnLp+6Cw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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 + dev: false + + /@babel/preset-typescript@7.26.0(@babel/core@7.26.10): + resolution: {integrity: sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + 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.26.8(@babel/core@7.26.10) + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/runtime-corejs2@7.26.10: + resolution: {integrity: sha512-JfoPiD7f/vvd/PaOfu5cr9CyzwDMPg4T0nX3MQr6IgTq49DhjvUcmjmjA7j6+xih1Evq+QKZnge1SoIlYozv/Q==} + engines: {node: '>=6.9.0'} + dependencies: + core-js: 2.6.12 + regenerator-runtime: 0.14.1 + dev: false + + /@babel/runtime@7.18.6: + resolution: {integrity: sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.11 + + /@babel/runtime@7.26.10: + resolution: {integrity: sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.1 + + /@babel/template@7.26.9: + resolution: {integrity: sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/parser': 7.26.10 + '@babel/types': 7.26.10 + + /@babel/traverse@7.26.10: + resolution: {integrity: sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.10 + '@babel/parser': 7.26.10 + '@babel/template': 7.26.9 + '@babel/types': 7.26.10 + debug: 4.4.0 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + /@babel/types@7.26.10: + resolution: {integrity: sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + + /@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(typescript@4.9.5): + resolution: {integrity: sha512-D8uyoEBp964Wi4DIbp6UmZmjdKsX/WlDyJY0YhEnl66VVRSZsIY16FBGAxTOixafgXBBBvaNdbIrJ82xP7FzfQ==} + hasBin: true + dependencies: + '@babel/generator': 7.26.10 + '@babel/parser': 7.26.10 + '@babel/runtime': 7.26.10 + '@babel/traverse': 7.26.10 + '@babel/types': 7.26.10 + '@types/node': 18.19.80 + 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.80)(typescript@4.9.5) + transitivePeerDependencies: + - '@swc/core' + - '@swc/wasm' + - supports-color + - typescript + dev: true + + /@chenshuai2144/sketch-color@1.0.9: + resolution: {integrity: sha512-obzSy26cb7Pm7OprWyVpgMpIlrZpZ0B7vbrU0RMbvRg0YAI890S5Xy02Aj1Nhl4+KTbi1lVYHt6HQP8Hm9s+1w==} + peerDependencies: + react: '>=16.12.0' + dependencies: + reactcss: 1.2.3 + tinycolor2: 1.6.0 + dev: false + + /@cnakazawa/watch@1.0.4: + resolution: {integrity: sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==} + engines: {node: '>=0.1.95'} + hasBin: true + dependencies: + exec-sh: 0.3.6 + minimist: 1.2.8 + + /@cspotcode/source-map-support@0.8.1: + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + dev: true + + /@csstools/convert-colors@1.4.0: + resolution: {integrity: sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==} + engines: {node: '>=4.0.0'} + dev: false + + /@csstools/normalize.css@12.1.1: + resolution: {integrity: sha512-YAYeJ+Xqh7fUou1d1j9XHl44BmsuThiTr4iNrgCQ3J27IbhXsxXDGZ1cXv8Qvs99d4rBbLiSKy3+WZiet32PcQ==} + dev: false + + /@csstools/postcss-cascade-layers@1.1.1(postcss@8.5.3): + resolution: {integrity: sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + '@csstools/selector-specificity': 2.2.0(postcss-selector-parser@6.1.2) + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + dev: false + + /@csstools/postcss-color-function@1.1.1(postcss@8.5.3): + resolution: {integrity: sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + '@csstools/postcss-progressive-custom-properties': 1.3.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /@csstools/postcss-font-format-keywords@1.0.1(postcss@8.5.3): + resolution: {integrity: sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /@csstools/postcss-hwb-function@1.0.2(postcss@8.5.3): + resolution: {integrity: sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /@csstools/postcss-ic-unit@1.0.1(postcss@8.5.3): + resolution: {integrity: sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + '@csstools/postcss-progressive-custom-properties': 1.3.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /@csstools/postcss-is-pseudo-class@2.0.7(postcss@8.5.3): + resolution: {integrity: sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + '@csstools/selector-specificity': 2.2.0(postcss-selector-parser@6.1.2) + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + dev: false + + /@csstools/postcss-nested-calc@1.0.0(postcss@8.5.3): + resolution: {integrity: sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /@csstools/postcss-normalize-display-values@1.0.1(postcss@8.5.3): + resolution: {integrity: sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /@csstools/postcss-oklab-function@1.1.1(postcss@8.5.3): + resolution: {integrity: sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + '@csstools/postcss-progressive-custom-properties': 1.3.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /@csstools/postcss-progressive-custom-properties@1.3.0(postcss@8.5.3): + resolution: {integrity: sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.3 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /@csstools/postcss-stepped-value-functions@1.0.1(postcss@8.5.3): + resolution: {integrity: sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /@csstools/postcss-text-decoration-shorthand@1.0.0(postcss@8.5.3): + resolution: {integrity: sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /@csstools/postcss-trigonometric-functions@1.0.2(postcss@8.5.3): + resolution: {integrity: sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==} + engines: {node: ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /@csstools/postcss-unset-value@1.0.2(postcss@8.5.3): + resolution: {integrity: sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + dev: false + + /@csstools/selector-specificity@2.2.0(postcss-selector-parser@6.1.2): + resolution: {integrity: sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss-selector-parser: ^6.0.10 + dependencies: + postcss-selector-parser: 6.1.2 + dev: false + + /@ctrl/tinycolor@3.6.1: + resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} + engines: {node: '>=10'} + dev: false + + /@ctrl/tinycolor@4.1.0: + resolution: {integrity: sha512-WyOx8cJQ+FQus4Mm4uPIZA64gbk3Wxh0so5Lcii0aJifqwoVOlfFtorjLE0Hen4OYyHZMXDWqMmaQemBhgxFRQ==} + engines: {node: '>=14'} + dev: false + + /@dagrejs/graphlib@2.1.4: + resolution: {integrity: sha512-QCg9sL4uhjn468FDEsb/S9hS2xUZSrv/+dApb1Ze5VKO96pTXKNJZ6MGhIpgWkc1TVhbVGH9/7rq/Mf8/jWicw==} + dependencies: + lodash: 4.17.21 + dev: false + + /@dnd-kit/accessibility@3.1.1: + resolution: {integrity: sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==} + peerDependencies: + react: '>=16.8.0' + dependencies: + tslib: 2.8.1 + dev: false + + /@dnd-kit/core@6.3.1: + resolution: {integrity: sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@dnd-kit/accessibility': 3.1.1 + '@dnd-kit/utilities': 3.2.2 + tslib: 2.8.1 + dev: false + + /@dnd-kit/modifiers@6.0.1(@dnd-kit/core@6.3.1): + resolution: {integrity: sha512-rbxcsg3HhzlcMHVHWDuh9LCjpOVAgqbV78wLGI8tziXY3+qcMQ61qVXIvNKQFuhj75dSfD+o+PYZQ/NUk2A23A==} + peerDependencies: + '@dnd-kit/core': ^6.0.6 + react: '>=16.8.0' + dependencies: + '@dnd-kit/core': 6.3.1 + '@dnd-kit/utilities': 3.2.2 + tslib: 2.8.1 + dev: false + + /@dnd-kit/sortable@7.0.2(@dnd-kit/core@6.3.1): + resolution: {integrity: sha512-wDkBHHf9iCi1veM834Gbk1429bd4lHX4RpAwT0y2cHLf246GAvU2sVw/oxWNpPKQNQRQaeGXhAVgrOl1IT+iyA==} + peerDependencies: + '@dnd-kit/core': ^6.0.7 + react: '>=16.8.0' + dependencies: + '@dnd-kit/core': 6.3.1 + '@dnd-kit/utilities': 3.2.2 + tslib: 2.8.1 + dev: false + + /@dnd-kit/utilities@3.2.2: + resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==} + peerDependencies: + react: '>=16.8.0' + dependencies: + tslib: 2.8.1 + dev: false + + /@emotion/babel-plugin@11.13.5: + resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} + dependencies: + '@babel/helper-module-imports': 7.25.9 + '@babel/runtime': 7.26.10 + '@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 + dev: false + + /@emotion/cache@11.14.0: + resolution: {integrity: sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==} + 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 + dev: false + + /@emotion/css@11.13.5: + resolution: {integrity: sha512-wQdD0Xhkn3Qy2VNcIzbLP9MR8TafI0MJb7BEAXKp+w4+XqErksWR4OXomuDzPsN4InLdGhVe6EYcn2ZIUCpB8w==} + 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 + dev: false + + /@emotion/hash@0.8.0: + resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==} + dev: false + + /@emotion/hash@0.9.2: + resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} + dev: false + + /@emotion/memoize@0.9.0: + resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} + dev: false + + /@emotion/react@11.14.0(@types/react@17.0.52): + resolution: {integrity: sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==} + peerDependencies: + '@types/react': '*' + react: '>=16.8.0' + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.26.10 + '@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 + '@emotion/utils': 1.4.2 + '@emotion/weak-memoize': 0.4.0 + '@types/react': 17.0.52 + hoist-non-react-statics: 3.3.2 + transitivePeerDependencies: + - supports-color + dev: false + + /@emotion/serialize@1.3.3: + resolution: {integrity: sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==} + 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 + dev: false + + /@emotion/sheet@1.4.0: + resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==} + dev: false + + /@emotion/unitless@0.10.0: + resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==} + dev: false + + /@emotion/unitless@0.7.5: + resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} + dev: false + + /@emotion/use-insertion-effect-with-fallbacks@1.2.0: + resolution: {integrity: sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==} + peerDependencies: + react: '>=16.8.0' + dev: false + + /@emotion/utils@1.4.2: + resolution: {integrity: sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==} + dev: false + + /@emotion/weak-memoize@0.4.0: + resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} + dev: false + + /@eslint-community/eslint-utils@4.5.1(eslint@9.22.0): + resolution: {integrity: sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 9.22.0 + eslint-visitor-keys: 3.4.3 + + /@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.19.2: + resolution: {integrity: sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.0 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + /@eslint/config-helpers@0.1.0: + resolution: {integrity: sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + /@eslint/core@0.12.0: + resolution: {integrity: sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dependencies: + '@types/json-schema': 7.0.15 + + /@eslint/eslintrc@3.3.0: + resolution: {integrity: sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + 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.22.0: + resolution: {integrity: sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==} + 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.7: + resolution: {integrity: sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dependencies: + '@eslint/core': 0.12.0 + levn: 0.4.1 + + /@exodus/schemasafe@1.3.0: + resolution: {integrity: sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==} + + /@formatjs/intl-displaynames@1.2.10: + resolution: {integrity: sha512-GROA2RP6+7Ouu0WnHFF78O5XIU7pBfI19WM1qm93l6MFWibUk67nCfVCK3VAYJkLy8L8ZxjkYT11VIAfvSz8wg==} + dependencies: + '@formatjs/intl-utils': 2.3.0 + dev: false + + /@formatjs/intl-listformat@1.4.8: + resolution: {integrity: sha512-WNMQlEg0e50VZrGIkgD5n7+DAMGt3boKi1GJALfhFMymslJb5i+5WzWxyj/3a929Z6MAFsmzRIJjKuv+BxKAOQ==} + dependencies: + '@formatjs/intl-utils': 2.3.0 + dev: false + + /@formatjs/intl-pluralrules@1.5.9: + resolution: {integrity: sha512-37E1ZG+Oqo3qrpUfumzNcFTV+V+NCExmTkkQ9Zw4FSlvJ4WhbbeYdieVapUVz9M0cLy8XrhCkfuM/Kn03iKReg==} + dependencies: + '@formatjs/intl-utils': 2.3.0 + dev: false + + /@formatjs/intl-relativetimeformat@4.5.16: + resolution: {integrity: sha512-IQ0haY97oHAH5OYUdykNiepdyEWj3SAT+Fp9ZpR85ov2JNiFx+12WWlxlVS8ehdyncC2ZMt/SwFIy2huK2+6/A==} + dependencies: + '@formatjs/intl-utils': 2.3.0 + dev: false + + /@formatjs/intl-unified-numberformat@3.3.7: + resolution: {integrity: sha512-KnWgLRHzCAgT9eyt3OS34RHoyD7dPDYhRcuKn+/6Kv2knDF8Im43J6vlSW6Hm1w63fNq3ZIT1cFk7RuVO3Psag==} + deprecated: We have renamed the package to @formatjs/intl-numberformat + dependencies: + '@formatjs/intl-utils': 2.3.0 + dev: false + + /@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 + dev: false + + /@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'} + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + + /@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: '*' + dev: false + + /@isaacs/cliui@8.0.2: + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + 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 + dev: false + + /@istanbuljs/load-nyc-config@1.1.0: + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + 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: + 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'} + dependencies: + '@jest/types': 26.6.2 + '@types/node': 22.13.10 + chalk: 4.1.2 + jest-message-util: 26.6.2 + jest-util: 26.6.2 + slash: 3.0.0 + + /@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} + dependencies: + '@jest/types': 27.5.1 + '@types/node': 22.13.10 + chalk: 4.1.2 + jest-message-util: 27.5.1 + jest-util: 27.5.1 + slash: 3.0.0 + dev: false + + /@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} + dependencies: + '@jest/types': 28.1.3 + '@types/node': 22.13.10 + chalk: 4.1.2 + jest-message-util: 28.1.3 + jest-util: 28.1.3 + slash: 3.0.0 + dev: false + + /@jest/core@26.6.3: + resolution: {integrity: sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw==} + engines: {node: '>= 10.14.2'} + 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.13.10 + 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 + 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 + jest-runtime: 26.6.3 + 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: + 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 + dependencies: + '@jest/console': 27.5.1 + '@jest/reporters': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.13.10 + 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 + 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 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + dev: false + + /@jest/environment@26.6.2: + resolution: {integrity: sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/fake-timers': 26.6.2 + '@jest/types': 26.6.2 + '@types/node': 22.13.10 + jest-mock: 26.6.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} + dependencies: + '@jest/fake-timers': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.13.10 + jest-mock: 27.5.1 + dev: false + + /@jest/fake-timers@26.6.2: + resolution: {integrity: sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/types': 26.6.2 + '@sinonjs/fake-timers': 6.0.1 + '@types/node': 22.13.10 + jest-message-util: 26.6.2 + jest-mock: 26.6.2 + jest-util: 26.6.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} + dependencies: + '@jest/types': 27.5.1 + '@sinonjs/fake-timers': 8.1.0 + '@types/node': 22.13.10 + jest-message-util: 27.5.1 + jest-mock: 27.5.1 + jest-util: 27.5.1 + dev: false + + /@jest/globals@26.6.2: + resolution: {integrity: sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/environment': 26.6.2 + '@jest/types': 26.6.2 + expect: 26.6.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} + dependencies: + '@jest/environment': 27.5.1 + '@jest/types': 27.5.1 + expect: 27.5.1 + dev: false + + /@jest/reporters@26.6.2: + resolution: {integrity: sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw==} + engines: {node: '>= 10.14.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: + 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 + 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.13.10 + 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 + transitivePeerDependencies: + - supports-color + dev: false + + /@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} + dependencies: + '@sinclair/typebox': 0.24.51 + dev: false + + /@jest/source-map@26.6.2: + resolution: {integrity: sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA==} + engines: {node: '>= 10.14.2'} + dependencies: + callsites: 3.1.0 + graceful-fs: 4.2.11 + source-map: 0.6.1 + + /@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} + dependencies: + callsites: 3.1.0 + graceful-fs: 4.2.11 + source-map: 0.6.1 + dev: false + + /@jest/test-result@26.6.2: + resolution: {integrity: sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==} + engines: {node: '>= 10.14.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: + resolution: {integrity: sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + '@jest/console': 27.5.1 + '@jest/types': 27.5.1 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 + dev: false + + /@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} + dependencies: + '@jest/console': 28.1.3 + '@jest/types': 28.1.3 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 + dev: false + + /@jest/test-sequencer@26.6.3: + resolution: {integrity: sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/test-result': 26.6.2 + graceful-fs: 4.2.11 + jest-haste-map: 26.6.2 + jest-runner: 26.6.3 + jest-runtime: 26.6.3 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + /@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} + 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 + dev: false + + /@jest/transform@26.6.2: + resolution: {integrity: sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==} + engines: {node: '>= 10.14.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.6 + slash: 3.0.0 + source-map: 0.6.1 + write-file-atomic: 3.0.3 + transitivePeerDependencies: + - supports-color + + /@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} + 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.6 + slash: 3.0.0 + source-map: 0.6.1 + write-file-atomic: 3.0.3 + transitivePeerDependencies: + - supports-color + dev: false + + /@jest/types@26.6.2: + resolution: {integrity: sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==} + engines: {node: '>= 10.14.2'} + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.13.10 + '@types/yargs': 15.0.19 + chalk: 4.1.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} + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.13.10 + '@types/yargs': 16.0.9 + chalk: 4.1.2 + dev: false + + /@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} + dependencies: + '@jest/schemas': 28.1.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.13.10 + '@types/yargs': 17.0.33 + chalk: 4.1.2 + dev: false + + /@jridgewell/gen-mapping@0.3.8: + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} + engines: {node: '>=6.0.0'} + 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: + 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==} + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + dev: false + + /@jridgewell/sourcemap-codec@1.5.0: + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + /@jridgewell/trace-mapping@0.3.25: + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + /@jridgewell/trace-mapping@0.3.9: + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + dev: true + + /@juggle/resize-observer@3.4.0: + resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==} + dev: false + + /@leichtgewicht/ip-codec@2.0.5: + resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} + dev: false + + /@ljharb/resumer@0.0.1: + resolution: {integrity: sha512-skQiAOrCfO7vRTq53cxznMpks7wS1va95UCidALlOVWqvBAzwPVErwizDwoMqNVMEn1mDq0utxZd02eIrvF1lw==} + engines: {node: '>= 0.4'} + dependencies: + '@ljharb/through': 2.3.14 + dev: false + + /@ljharb/through@2.3.14: + resolution: {integrity: sha512-ajBvlKpWucBB17FuQYUShqpqy8GRgYEpJW0vWJbUu1CV9lWyrDCapy0lScU8T8Z6qn49sSwJB3+M+evYIdGg+A==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + dev: false + + /@mapbox/geojson-rewind@0.5.2: + resolution: {integrity: sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA==} + hasBin: true + dependencies: + get-stream: 6.0.1 + minimist: 1.2.8 + dev: false + + /@mapbox/geojson-types@1.0.2: + resolution: {integrity: sha512-e9EBqHHv3EORHrSfbR9DqecPNn+AmuAoQxV6aL8Xu30bJMJR1o8PZLZzpk1Wq7/NfCbuhmakHTPYRhoqLsXRnw==} + dev: false + + /@mapbox/jsonlint-lines-primitives@2.0.2: + resolution: {integrity: sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==} + engines: {node: '>= 0.6'} + dev: false + + /@mapbox/mapbox-gl-supported@1.5.0(mapbox-gl@1.13.3): + resolution: {integrity: sha512-/PT1P6DNf7vjEEiPkVIRJkvibbqWtqnyGaBz3nfRdcxclNSnSdaLU5tfAgcD7I8Yt5i+L19s406YLl1koLnLbg==} + peerDependencies: + mapbox-gl: '>=0.32.1 <2.0.0' + dependencies: + mapbox-gl: 1.13.3 + dev: false + + /@mapbox/martini@0.2.0: + resolution: {integrity: sha512-7hFhtkb0KTLEls+TRw/rWayq5EeHtTaErgm/NskVoXmtgAQu/9D299aeyj6mzAR/6XUnYRp2lU+4IcrYRFjVsQ==} + dev: false + + /@mapbox/point-geometry@0.1.0: + resolution: {integrity: sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==} + dev: false + + /@mapbox/tiny-sdf@1.2.5: + resolution: {integrity: sha512-cD8A/zJlm6fdJOk6DqPUV8mcpyJkRz2x2R+/fYcWDYG3oWbG7/L7Yl/WqQ1VZCjnL9OTIMAn6c+BC5Eru4sQEw==} + dev: false + + /@mapbox/tiny-sdf@2.0.6: + resolution: {integrity: sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA==} + dev: false + + /@mapbox/unitbezier@0.0.0: + resolution: {integrity: sha512-HPnRdYO0WjFjRTSwO3frz1wKaU649OBFPX3Zo/2WZvuRi6zMiRGui8SnPQiQABgqCf8YikDe5t3HViTVw1WUzA==} + dev: false + + /@mapbox/unitbezier@0.0.1: + resolution: {integrity: sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==} + dev: false + + /@mapbox/vector-tile@1.3.1: + resolution: {integrity: sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==} + dependencies: + '@mapbox/point-geometry': 0.1.0 + dev: false + + /@mapbox/whoots-js@3.1.0: + resolution: {integrity: sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==} + engines: {node: '>=6.0.0'} + dev: false + + /@maplibre/maplibre-gl-style-spec@19.3.3: + resolution: {integrity: sha512-cOZZOVhDSulgK0meTsTkmNXb1ahVvmTmWmfx9gRBwc6hq98wS9JP35ESIoNq3xqEan+UN+gn8187Z6E4NKhLsw==} + hasBin: true + 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 + dev: false + + /@mrmlnc/readdir-enhanced@2.2.1: + resolution: {integrity: sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==} + engines: {node: '>=4'} + dependencies: + call-me-maybe: 1.0.2 + glob-to-regexp: 0.3.0 + dev: false + + /@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1: + resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} + dependencies: + eslint-scope: 5.1.1 + dev: false + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: false + + /@nodelib/fs.stat@1.1.3: + resolution: {integrity: sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==} + engines: {node: '>= 6'} + dev: false + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: false + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 + dev: false + + /@oceanbase/aliyun-theme@0.1.6: + resolution: {integrity: sha512-4IRij4j1Cw2NbnBpbg3Cb6aoYjG2E2FzSk11uDKY8IBrAMV+2lByMoM8j2gJZ1shqIyiYYorw/UawYW8BljILw==} + dev: false + + /@oceanbase/charts@0.4.5(antd@5.24.4): + resolution: {integrity: sha512-zLxVAicamclSlVGrjg4IELscenDe8mHyZW/NfZbkP8mbRpDDXjPdnW/ajSyD1jOi/nbYTyZj5rrnBkC9E8S6DA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@ant-design/charts': 1.4.3(antd@5.24.4)(classnames@2.5.1)(lodash@4.17.21) + '@oceanbase/util': 0.4.2 + classnames: 2.5.1 + lodash: 4.17.21 + rc-util: 5.44.4 + tinycolor2: 1.6.0 + use-resize-observer: 9.1.0 + transitivePeerDependencies: + - '@ant-design/icons' + - antd + dev: false + + /@oceanbase/design@0.4.9(moment@2.30.1): + resolution: {integrity: sha512-xQ/mFwnGt1PAHNV3x8fBucLql+fyoM8mv2PoFElgw66AjdfBXn1gvaynHaaWQB8SGnrMRGPG9Ca1IXLf6J/H5g==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@ant-design/cssinjs': 1.23.0 + '@ctrl/tinycolor': 4.1.0 + '@oceanbase/aliyun-theme': 0.1.6 + '@oceanbase/icons': 0.4.5 + '@oceanbase/util': 0.4.2 + ahooks: 2.10.14 + antd: 5.24.4(moment@2.30.1) + classnames: 2.5.1 + lodash: 4.17.21 + lottie-web: 5.12.2 + prop-types: 15.8.1 + rc-util: 5.44.4 + transitivePeerDependencies: + - date-fns + - luxon + - moment + - supports-color + dev: false + + /@oceanbase/icons-svg@1.0.10: + resolution: {integrity: sha512-oMaynh08/RoTVKK4Us6GISIog0iLViLBs6jYh7Jyu0CnTml1hSOhnga/qQWmnLr/MaHWhdgaXqF9L4UZW4hPSw==} + 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 + dev: false + + /@oceanbase/icons@0.4.5: + resolution: {integrity: sha512-34h65S+f72vjyUytu9jfGNE0L+OTEqQdrHKBHsJbr20ner1kriij4fFWNDgyJdrtsWVk/CUrosNYIFYgiGZ+rQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@ant-design/colors': 7.2.0 + '@ant-design/icons': 5.6.1 + '@oceanbase/icons-svg': 1.0.10 + lodash.camelcase: 4.3.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@oceanbase/ui@0.4.10(@types/react@17.0.52)(antd@5.24.4): + resolution: {integrity: sha512-KcuGy2HcCXpIzAz7m5oYfo6QnjSJeTaMTERvOgpZTAGMUlP81tr1a8FuNwxGlf3VeO+lBZHZXEzW+AdbdQnf5A==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@ant-design/cssinjs': 1.23.0 + '@ant-design/pro-components': 2.8.6(antd@5.24.4) + '@antv/g6': 3.4.10 + '@oceanbase/design': 0.4.9(moment@2.30.1) + '@oceanbase/icons': 0.4.5 + '@oceanbase/util': 0.4.2 + ahooks: 2.10.14 + 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(dayjs@1.11.13)(moment@2.30.1) + rc-util: 5.44.4 + react-copy-to-clipboard: 5.1.0 + react-json-view: 1.21.3(@types/react@17.0.52) + react-split-pane: 0.1.92 + screenfull: 6.0.2 + transitivePeerDependencies: + - '@types/react' + - antd + - date-fns + - encoding + - luxon + - rc-field-form + - supports-color + dev: false + + /@oceanbase/util@0.4.2: + resolution: {integrity: sha512-YvGD6TBVO66sfO/qw+/hNs0PMo9Pjowc7xR50UxRTktChUl2BlDTfmWzmnxFuyAg7U+HRMOKxkpXzjQo5yhtFQ==} + peerDependencies: + react: '>=16.9.0' + dependencies: + ahooks: 2.10.14 + filesize: 10.1.6 + is-url: 1.2.4 + lodash: 4.17.21 + moment: 2.30.1 + query-string: 9.1.1 + dev: false + + /@pkgjs/parseargs@0.11.0: + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + requiresBuild: true + dev: false + optional: true + + /@pmmmwh/react-refresh-webpack-plugin@0.5.15(react-refresh@0.11.0)(webpack-dev-server@4.15.2)(webpack@5.98.0): + resolution: {integrity: sha512-LFWllMA55pzB9D34w/wXUCf8+c+IYKuJDgxiZ3qMhl64KRMBHYM1I3VdGaD2BV5FNPV2/S2596bppxHbv2ZydQ==} + 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 + dependencies: + ansi-html: 0.0.9 + core-js-pure: 3.41.0 + error-stack-parser: 2.1.4 + html-entities: 2.5.2 + loader-utils: 2.0.4 + react-refresh: 0.11.0 + schema-utils: 4.3.0 + source-map: 0.7.4 + webpack: 5.98.0 + webpack-dev-server: 4.15.2(webpack@5.98.0) + dev: false + + /@probe.gl/env@3.6.0: + resolution: {integrity: sha512-4tTZYUg/8BICC3Yyb9rOeoKeijKbZHRXBEKObrfPmX4sQmYB15ZOUpoVBhAyJkOYVAM8EkPci6Uw5dLCwx2BEQ==} + dependencies: + '@babel/runtime': 7.26.10 + dev: false + + /@probe.gl/log@3.6.0: + resolution: {integrity: sha512-hjpyenpEvOdowgZ1qMeCJxfRD4JkKdlXz0RC14m42Un62NtOT+GpWyKA4LssT0+xyLULCByRAtG2fzZorpIAcA==} + dependencies: + '@babel/runtime': 7.26.10 + '@probe.gl/env': 3.6.0 + dev: false + + /@probe.gl/stats@3.6.0: + resolution: {integrity: sha512-JdALQXB44OP4kUBN/UrQgzbJe4qokbVF4Y8lkIA8iVCFnjVowWIgkD/z/0QO65yELT54tTrtepw1jScjKB+rhQ==} + dependencies: + '@babel/runtime': 7.26.10 + dev: false + + /@qixian.cs/path-to-regexp@6.1.0: + resolution: {integrity: sha512-2jIiLiVZB1jnY7IIRQKtoV8Gnr7XIhk4mC88ONGunZE3hYt5IHUG4BE/6+JiTBjjEWQLBeWnZB8hGpppkufiVw==} + dev: false + + /@rc-component/async-validator@5.0.4: + resolution: {integrity: sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==} + engines: {node: '>=14.x'} + dependencies: + '@babel/runtime': 7.26.10 + dev: false + + /@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' + dependencies: + '@ant-design/fast-color': 2.0.6 + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /@rc-component/context@1.4.0: + resolution: {integrity: sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + rc-util: 5.44.4 + dev: false + + /@rc-component/mini-decimal@1.1.0: + resolution: {integrity: sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==} + engines: {node: '>=8.x'} + dependencies: + '@babel/runtime': 7.26.10 + dev: false + + /@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' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /@rc-component/portal@1.1.2: + resolution: {integrity: sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /@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' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /@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' + dependencies: + '@babel/runtime': 7.26.10 + '@rc-component/portal': 1.1.2 + '@rc-component/trigger': 2.2.6 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /@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' + dependencies: + '@babel/runtime': 7.26.10 + '@rc-component/portal': 1.1.2 + classnames: 2.5.1 + rc-motion: 2.9.5 + rc-resize-observer: 1.4.3 + rc-util: 5.44.4 + dev: false + + /@rgrove/parse-xml@2.0.4: + resolution: {integrity: sha512-344bRXnUMu1tWqq1GJO2nCSqJRGTzcNLErcG2HZbVhUo90R5xQ6YdsCqtuT0KaFyN/mlxWqt2SdHSRNzwDvT5g==} + engines: {node: '>=6.0.0'} + dev: false + + /@rollup/plugin-babel@5.3.1(@babel/core@7.26.10)(rollup@2.79.2): + 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 + 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 + transitivePeerDependencies: + - supports-color + dev: false + + /@rollup/plugin-node-resolve@11.2.1(rollup@2.79.2): + resolution: {integrity: sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==} + engines: {node: '>= 10.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0 + 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 + dev: false + + /@rollup/plugin-replace@2.4.2(rollup@2.79.2): + resolution: {integrity: sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==} + peerDependencies: + rollup: ^1.20.0 || ^2.0.0 + dependencies: + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) + magic-string: 0.25.9 + rollup: 2.79.2 + dev: false + + /@rollup/pluginutils@3.1.0(rollup@2.79.2): + resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} + engines: {node: '>= 8.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0 + dependencies: + '@types/estree': 0.0.39 + estree-walker: 1.0.1 + picomatch: 2.3.1 + rollup: 2.79.2 + dev: false + + /@rtsao/scc@1.1.0: + resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + dev: false + + /@rushstack/eslint-patch@1.11.0: + resolution: {integrity: sha512-zxnHvoMQVqewTJr/W4pKjF0bMGiKJv1WX7bSrkl46Hg0QjESbzBROWK0Wg4RphzSOS5Jiy7eFimmM3UgMrMZbQ==} + dev: false + + /@sentry-internal/feedback@7.120.3: + resolution: {integrity: sha512-ewJJIQ0mbsOX6jfiVFvqMjokxNtgP3dNwUv+4nenN+iJJPQsM6a0ocro3iscxwVdbkjw5hY3BUV2ICI5Q0UWoA==} + engines: {node: '>=12'} + dependencies: + '@sentry/core': 7.120.3 + '@sentry/types': 7.120.3 + '@sentry/utils': 7.120.3 + dev: false + + /@sentry-internal/replay-canvas@7.120.3: + resolution: {integrity: sha512-s5xy+bVL1eDZchM6gmaOiXvTqpAsUfO7122DxVdEDMtwVq3e22bS2aiGa8CUgOiJkulZ+09q73nufM77kOmT/A==} + engines: {node: '>=12'} + dependencies: + '@sentry/core': 7.120.3 + '@sentry/replay': 7.120.3 + '@sentry/types': 7.120.3 + '@sentry/utils': 7.120.3 + dev: false + + /@sentry-internal/tracing@7.120.3: + resolution: {integrity: sha512-Ausx+Jw1pAMbIBHStoQ6ZqDZR60PsCByvHdw/jdH9AqPrNE9xlBSf9EwcycvmrzwyKspSLaB52grlje2cRIUMg==} + engines: {node: '>=8'} + dependencies: + '@sentry/core': 7.120.3 + '@sentry/types': 7.120.3 + '@sentry/utils': 7.120.3 + dev: false + + /@sentry/browser@7.120.3: + resolution: {integrity: sha512-i9vGcK9N8zZ/JQo1TCEfHHYZ2miidOvgOABRUc9zQKhYdcYQB2/LU1kqlj77Pxdxf4wOa9137d6rPrSn9iiBxg==} + engines: {node: '>=8'} + 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 + dev: false + + /@sentry/core@7.120.3: + resolution: {integrity: sha512-vyy11fCGpkGK3qI5DSXOjgIboBZTriw0YDx/0KyX5CjIjDDNgp5AGgpgFkfZyiYiaU2Ww3iFuKo4wHmBusz1uA==} + engines: {node: '>=8'} + dependencies: + '@sentry/types': 7.120.3 + '@sentry/utils': 7.120.3 + dev: false + + /@sentry/integrations@7.120.3: + resolution: {integrity: sha512-6i/lYp0BubHPDTg91/uxHvNui427df9r17SsIEXa2eKDwQ9gW2qRx5IWgvnxs2GV/GfSbwcx4swUB3RfEWrXrQ==} + engines: {node: '>=8'} + dependencies: + '@sentry/core': 7.120.3 + '@sentry/types': 7.120.3 + '@sentry/utils': 7.120.3 + localforage: 1.10.0 + dev: false + + /@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 + 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 + dev: false + + /@sentry/replay@7.120.3: + resolution: {integrity: sha512-CjVq1fP6bpDiX8VQxudD5MPWwatfXk8EJ2jQhJTcWu/4bCSOQmHxnnmBM+GVn5acKUBCodWHBN+IUZgnJheZSg==} + engines: {node: '>=12'} + dependencies: + '@sentry-internal/tracing': 7.120.3 + '@sentry/core': 7.120.3 + '@sentry/types': 7.120.3 + '@sentry/utils': 7.120.3 + dev: false + + /@sentry/tracing@7.120.3: + resolution: {integrity: sha512-B7bqyYFgHuab1Pn7w5KXsZP/nfFo4VDBDdSXDSWYk5+TYJ3IDruO3eJFhOrircfsz4YwazWm9kbeZhkpsHDyHg==} + engines: {node: '>=8'} + dependencies: + '@sentry-internal/tracing': 7.120.3 + dev: false + + /@sentry/types@7.120.3: + resolution: {integrity: sha512-C4z+3kGWNFJ303FC+FxAd4KkHvxpNFYAFN8iMIgBwJdpIl25KZ8Q/VdGn0MLLUEHNLvjob0+wvwlcRBBNLXOow==} + engines: {node: '>=8'} + dev: false + + /@sentry/utils@7.120.3: + resolution: {integrity: sha512-UDAOQJtJDxZHQ5Nm1olycBIsz2wdGX8SdzyGVHmD8EOQYAeDZQyIlQYohDe9nazdIOQLZCIc3fU0G9gqVLkaGQ==} + engines: {node: '>=8'} + dependencies: + '@sentry/types': 7.120.3 + dev: false + + /@sinclair/typebox@0.24.51: + resolution: {integrity: sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==} + dev: false + + /@sinonjs/commons@1.8.6: + resolution: {integrity: sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==} + dependencies: + type-detect: 4.0.8 + + /@sinonjs/fake-timers@6.0.1: + resolution: {integrity: sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==} + dependencies: + '@sinonjs/commons': 1.8.6 + + /@sinonjs/fake-timers@8.1.0: + resolution: {integrity: sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==} + dependencies: + '@sinonjs/commons': 1.8.6 + dev: false + + /@surma/rollup-plugin-off-main-thread@2.2.3: + resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==} + dependencies: + ejs: 3.1.10 + json5: 2.2.3 + magic-string: 0.25.9 + string.prototype.matchall: 4.0.12 + dev: false + + /@svgr/babel-plugin-add-jsx-attribute@5.4.0: + resolution: {integrity: sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==} + engines: {node: '>=10'} + dev: false + + /@svgr/babel-plugin-remove-jsx-attribute@5.4.0: + resolution: {integrity: sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==} + engines: {node: '>=10'} + dev: false + + /@svgr/babel-plugin-remove-jsx-empty-expression@5.0.1: + resolution: {integrity: sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==} + engines: {node: '>=10'} + dev: false + + /@svgr/babel-plugin-replace-jsx-attribute-value@5.0.1: + resolution: {integrity: sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==} + engines: {node: '>=10'} + dev: false + + /@svgr/babel-plugin-svg-dynamic-title@5.4.0: + resolution: {integrity: sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==} + engines: {node: '>=10'} + dev: false + + /@svgr/babel-plugin-svg-em-dimensions@5.4.0: + resolution: {integrity: sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==} + engines: {node: '>=10'} + dev: false + + /@svgr/babel-plugin-transform-react-native-svg@5.4.0: + resolution: {integrity: sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==} + engines: {node: '>=10'} + dev: false + + /@svgr/babel-plugin-transform-svg-component@5.5.0: + resolution: {integrity: sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==} + engines: {node: '>=10'} + dev: false + + /@svgr/babel-preset@5.5.0: + resolution: {integrity: sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==} + engines: {node: '>=10'} + 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 + dev: false + + /@svgr/core@5.5.0: + resolution: {integrity: sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==} + engines: {node: '>=10'} + dependencies: + '@svgr/plugin-jsx': 5.5.0 + camelcase: 6.3.0 + cosmiconfig: 7.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@svgr/hast-util-to-babel-ast@5.5.0: + resolution: {integrity: sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==} + engines: {node: '>=10'} + dependencies: + '@babel/types': 7.26.10 + dev: false + + /@svgr/plugin-jsx@5.5.0: + resolution: {integrity: sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==} + engines: {node: '>=10'} + 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 + dev: false + + /@svgr/plugin-svgo@5.5.0: + resolution: {integrity: sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==} + engines: {node: '>=10'} + dependencies: + cosmiconfig: 7.1.0 + deepmerge: 4.3.1 + svgo: 1.3.2 + dev: false + + /@svgr/webpack@5.5.0: + resolution: {integrity: sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==} + engines: {node: '>=10'} + 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 + dev: false + + /@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'} + dev: false + + /@tsconfig/node10@1.0.11: + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + dev: true + + /@tsconfig/node12@1.0.11: + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + dev: true + + /@tsconfig/node14@1.0.3: + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + dev: true + + /@tsconfig/node16@1.0.4: + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + dev: true + + /@turf/bbox-polygon@6.5.0: + resolution: {integrity: sha512-+/r0NyL1lOG3zKZmmf6L8ommU07HliP4dgYToMoTxqzsWzyLjaj/OzgQ8rBmv703WJX+aS6yCmLuIhYqyufyuw==} + dependencies: + '@turf/helpers': 6.5.0 + dev: false + + /@turf/bbox@6.5.0: + resolution: {integrity: sha512-RBbLaao5hXTYyyg577iuMtDB8ehxMlUqHEJiMs8jT1GHkFhr6sYre3lmLsPeYEi/ZKj5TP5tt7fkzNdJ4GIVyw==} + dependencies: + '@turf/helpers': 6.5.0 + '@turf/meta': 6.5.0 + dev: false + + /@turf/clone@6.5.0: + resolution: {integrity: sha512-mzVtTFj/QycXOn6ig+annKrM6ZlimreKYz6f/GSERytOpgzodbQyOgkfwru100O1KQhhjSudKK4DsQ0oyi9cTw==} + dependencies: + '@turf/helpers': 6.5.0 + dev: false + + /@turf/helpers@6.5.0: + resolution: {integrity: sha512-VbI1dV5bLFzohYYdgqwikdMVpe7pJ9X3E+dlr425wa2/sMJqYDhTO++ec38/pcPvPE6oD9WEEeU3Xu3gza+VPw==} + dev: false + + /@turf/invariant@6.5.0: + resolution: {integrity: sha512-Wv8PRNCtPD31UVbdJE/KVAWKe7l6US+lJItRR/HOEW3eh+U/JwRCSUl/KZ7bmjM/C+zLNoreM2TU6OoLACs4eg==} + dependencies: + '@turf/helpers': 6.5.0 + dev: false + + /@turf/meta@6.5.0: + resolution: {integrity: sha512-RrArvtsV0vdsCBegoBtOalgdSOfkBrTJ07VkpiCnq/491W67hnMWmDu7e6Ztw0C3WldRYTXkg3SumfdzZxLBHA==} + dependencies: + '@turf/helpers': 6.5.0 + dev: false + + /@turf/polygon-to-line@6.5.0: + resolution: {integrity: sha512-5p4n/ij97EIttAq+ewSnKt0ruvuM+LIDzuczSzuHTpq4oS7Oq8yqg5TQ4nzMVuK41r/tALCk7nAoBuw3Su4Gcw==} + dependencies: + '@turf/helpers': 6.5.0 + '@turf/invariant': 6.5.0 + dev: false + + /@turf/union@6.5.0: + resolution: {integrity: sha512-igYWCwP/f0RFHIlC2c0SKDuM/ObBaqSljI3IdV/x71805QbIvY/BYGcJdyNcgEA6cylIGl/0VSlIbpJHZ9ldhw==} + dependencies: + '@turf/helpers': 6.5.0 + '@turf/invariant': 6.5.0 + polygon-clipping: 0.15.7 + dev: false + + /@types/babel__core@7.20.5: + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + dependencies: + '@babel/parser': 7.26.10 + '@babel/types': 7.26.10 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.6 + + /@types/babel__generator@7.6.8: + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + dependencies: + '@babel/types': 7.26.10 + + /@types/babel__template@7.4.4: + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + dependencies: + '@babel/parser': 7.26.10 + '@babel/types': 7.26.10 + + /@types/babel__traverse@7.20.6: + resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + dependencies: + '@babel/types': 7.26.10 + + /@types/body-parser@1.19.5: + resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + dependencies: + '@types/connect': 3.4.38 + '@types/node': 22.13.10 + dev: false + + /@types/bonjour@3.5.13: + resolution: {integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==} + dependencies: + '@types/node': 22.13.10 + dev: false + + /@types/connect-history-api-fallback@1.5.4: + resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==} + dependencies: + '@types/express-serve-static-core': 5.0.6 + '@types/node': 22.13.10 + dev: false + + /@types/connect@3.4.38: + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + dependencies: + '@types/node': 22.13.10 + dev: false + + /@types/crypto-js@4.2.2: + resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==} + dev: true + + /@types/d3-timer@1.0.12: + resolution: {integrity: sha512-Tv9tkA4y3UvGQnrHyYAQhf5x/297FuYwotS4UW2TpwLblvRahbyL8r9HFYTJLPfPRqS63hwlqRItjKGmKtJxNg==} + dev: false + + /@types/d3-timer@2.0.3: + resolution: {integrity: sha512-jhAJzaanK5LqyLQ50jJNIrB8fjL9gwWZTgYjevPvkDLMU+kTAZkYsobI59nYoeSrH1PucuyJEi247Pb90t6XUg==} + dev: false + + /@types/eslint-scope@3.7.7: + resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} + dependencies: + '@types/eslint': 9.6.1 + '@types/estree': 1.0.6 + dev: false + + /@types/eslint@8.56.12: + resolution: {integrity: sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==} + dependencies: + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 + dev: false + + /@types/eslint@9.6.1: + resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} + dependencies: + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 + dev: false + + /@types/estree@0.0.39: + resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} + dev: false + + /@types/estree@1.0.6: + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + + /@types/express-serve-static-core@4.19.6: + resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} + dependencies: + '@types/node': 22.13.10 + '@types/qs': 6.9.18 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + dev: false + + /@types/express-serve-static-core@5.0.6: + resolution: {integrity: sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==} + dependencies: + '@types/node': 22.13.10 + '@types/qs': 6.9.18 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + dev: false + + /@types/express@4.17.21: + resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + 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 + dev: false + + /@types/geojson@7946.0.16: + resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} + dev: false + + /@types/glob@7.2.0: + resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} + dependencies: + '@types/minimatch': 5.1.2 + '@types/node': 22.13.10 + dev: false + + /@types/graceful-fs@4.1.9: + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + dependencies: + '@types/node': 22.13.10 + + /@types/history@4.7.11: + resolution: {integrity: sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==} + dev: false + + /@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. + dependencies: + history: 5.3.0 + dev: false + + /@types/hoist-non-react-statics@3.3.6: + resolution: {integrity: sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==} + dependencies: + '@types/react': 17.0.52 + hoist-non-react-statics: 3.3.2 + dev: false + + /@types/html-minifier-terser@5.1.2: + resolution: {integrity: sha512-h4lTMgMJctJybDp8CQrxTUiiYmedihHWkjnF/8Pxseu2S6Nlfcy8kwboQ8yejh456rP2yWoEVm1sS/FVsfM48w==} + dev: true + + /@types/html-minifier-terser@6.1.0: + resolution: {integrity: sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==} + dev: false + + /@types/http-errors@2.0.4: + resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + dev: false + + /@types/http-proxy@1.17.16: + resolution: {integrity: sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==} + dependencies: + '@types/node': 22.13.10 + dev: false + + /@types/invariant@2.2.37: + resolution: {integrity: sha512-IwpIMieE55oGWiXkQPSBY1nw1nFs6bsKXTFskNY8sdS17K24vyEBRQZEwlRS7ZmXCWnJcQtbxWzly+cODWGs2A==} + dev: false + + /@types/isomorphic-fetch@0.0.35: + resolution: {integrity: sha512-DaZNUvLDCAnCTjgwxgiL1eQdxIKEpNLOlTNtAgnZc50bG2copGhRrFN9/PxPBuJe+tZVLCbQ7ls0xveXVRPkvw==} + dev: false + + /@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==} + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + /@types/istanbul-reports@3.0.4: + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + /@types/js-cookie@2.2.7: + resolution: {integrity: sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==} + dev: false + + /@types/json-schema@7.0.15: + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + /@types/json5@0.0.29: + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + dev: false + + /@types/lodash@4.17.16: + resolution: {integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==} + dev: true + + /@types/mapbox__point-geometry@0.1.4: + resolution: {integrity: sha512-mUWlSxAmYLfwnRBmgYV86tgYmMIICX4kza8YnE/eIlywGe2XoOxlpVnXWwir92xRLjwyarqwpu2EJKD2pk0IUA==} + dev: false + + /@types/mapbox__vector-tile@1.3.4: + resolution: {integrity: sha512-bpd8dRn9pr6xKvuEBQup8pwQfD4VUyqO/2deGjfpe6AwC8YRlyEipvefyRJUSiCJTZuCb8Pl1ciVV5ekqJ96Bg==} + dependencies: + '@types/geojson': 7946.0.16 + '@types/mapbox__point-geometry': 0.1.4 + '@types/pbf': 3.0.5 + dev: false + + /@types/mime@1.3.5: + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + dev: false + + /@types/minimatch@5.1.2: + resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + dev: false + + /@types/node-forge@1.3.11: + resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} + dependencies: + '@types/node': 22.13.10 + dev: false + + /@types/node@18.19.80: + resolution: {integrity: sha512-kEWeMwMeIvxYkeg1gTc01awpwLbfMRZXdIhwRcakd/KlK53jmRC26LqcbIt7fnAQTu5GzlnWmzA3H6+l1u6xxQ==} + dependencies: + undici-types: 5.26.5 + dev: true + + /@types/node@22.13.10: + resolution: {integrity: sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==} + dependencies: + undici-types: 6.20.0 + + /@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==} + dev: false + + /@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==} + dev: false + + /@types/qs@6.9.18: + resolution: {integrity: sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==} + dev: false + + /@types/range-parser@1.2.7: + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + dev: false + + /@types/react-dom@16.9.25(@types/react@16.14.62): + resolution: {integrity: sha512-ZK//eAPhwft9Ul2/Zj+6O11YR6L4JX0J2sVeBC9Ft7x7HFN7xk7yUV/zDxqV6rjvqgl6r8Dq7oQImxtyf/Mzcw==} + peerDependencies: + '@types/react': ^16.0.0 + dependencies: + '@types/react': 16.14.62 + dev: false + + /@types/react-dom@17.0.2: + resolution: {integrity: sha512-Icd9KEgdnFfJs39KyRyr0jQ7EKhq8U6CcHRMGAS45fp5qgUvxL3ujUCfWFttUK2UErqZNj97t9gsVPNAqcwoCg==} + dependencies: + '@types/react': 17.0.52 + dev: true + + /@types/react-helmet@6.1.11: + resolution: {integrity: sha512-0QcdGLddTERotCXo3VFlUSWO3ztraw8nZ6e3zJSgG7apwV5xt+pJUS8ewPBqT4NYB1optGLprNQzFleIY84u/g==} + dependencies: + '@types/react': 17.0.52 + dev: false + + /@types/react-redux@7.1.34: + resolution: {integrity: sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==} + 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 + dev: false + + /@types/react-router-config@5.0.2: + resolution: {integrity: sha512-WOSetDV3YPxbkVJAdv/bqExJjmcdCi/vpCJh3NfQOy1X15vHMSiMioXIcGekXDJJYhqGUMDo9e337mh508foAA==} + dependencies: + '@types/history': 5.0.0 + '@types/react': 17.0.52 + '@types/react-router': 5.1.20 + dev: false + + /@types/react-router-dom@5.1.7: + resolution: {integrity: sha512-D5mHD6TbdV/DNHYsnwBTv+y73ei+mMjrkGrla86HthE4/PVvL1J94Bu3qABU+COXzpL23T1EZapVVpwHuBXiUg==} + dependencies: + '@types/history': 5.0.0 + '@types/react': 17.0.52 + '@types/react-router': 5.1.12 + dev: false + + /@types/react-router-dom@5.3.3: + resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==} + dependencies: + '@types/history': 4.7.11 + '@types/react': 17.0.52 + '@types/react-router': 5.1.20 + dev: false + + /@types/react-router@5.1.12: + resolution: {integrity: sha512-0bhXQwHYfMeJlCh7mGhc0VJTRm0Gk+Z8T00aiP4702mDUuLs9SMhnd2DitpjWFjdOecx2UXtICK14H9iMnziGA==} + dependencies: + '@types/history': 5.0.0 + '@types/react': 17.0.52 + dev: false + + /@types/react-router@5.1.20: + resolution: {integrity: sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==} + dependencies: + '@types/history': 4.7.11 + '@types/react': 17.0.52 + dev: false + + /@types/react@16.14.62: + resolution: {integrity: sha512-BWf7hqninZav6nerxXj+NeZT/mTpDeG6Lk2zREHAy63CrnXoOGPGtNqTFYFN/sqpSaREDP5otVV88axIXmKfGA==} + dependencies: + '@types/prop-types': 15.7.14 + '@types/scheduler': 0.16.8 + csstype: 3.1.3 + dev: false + + /@types/react@17.0.52: + resolution: {integrity: sha512-vwk8QqVODi0VaZZpDXQCmEmiOuyjEFPY7Ttaw5vjM112LOq37yz1CDJGrRJwA1fYEq4Iitd5rnjd1yWAc/bT+A==} + dependencies: + '@types/prop-types': 15.7.14 + '@types/scheduler': 0.23.0 + csstype: 3.1.3 + + /@types/resolve@1.17.1: + resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} + dependencies: + '@types/node': 22.13.10 + dev: false + + /@types/retry@0.12.0: + resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + dev: false + + /@types/scheduler@0.16.8: + resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==} + dev: false + + /@types/scheduler@0.23.0: + resolution: {integrity: sha512-YIoDCTH3Af6XM5VuwGG/QL/CJqga1Zm3NkU3HZ4ZHK2fRMPYP1VczsTUqtsf43PH/iJNVlPHAo2oWX7BSdB2Hw==} + + /@types/scroll-into-view@1.16.4: + resolution: {integrity: sha512-f2Rw8aA9gj7+M6uWhNx/mRAWyC4tYsvG2uA/cMEkXUyfMXYgTRJCM8CD8kTkoQlX8STQVgTQL0SmmM1VPZQmsg==} + dev: true + + /@types/semver@7.5.8: + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + dev: false + + /@types/send@0.17.4: + resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + dependencies: + '@types/mime': 1.3.5 + '@types/node': 22.13.10 + dev: false + + /@types/serve-index@1.9.4: + resolution: {integrity: sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==} + dependencies: + '@types/express': 4.17.21 + dev: false + + /@types/serve-static@1.15.7: + resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} + dependencies: + '@types/http-errors': 2.0.4 + '@types/node': 22.13.10 + '@types/send': 0.17.4 + dev: false + + /@types/sockjs@0.3.36: + resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} + dependencies: + '@types/node': 22.13.10 + dev: false + + /@types/source-list-map@0.1.6: + resolution: {integrity: sha512-5JcVt1u5HDmlXkwOD2nslZVllBBc7HDuOICfiZah2Z0is8M8g+ddAEawbmd3VjedfDHBzxCaXLs07QEmb7y54g==} + dev: true + + /@types/sql-formatter@2.3.0: + resolution: {integrity: sha512-Xh9kEOaKWhm3vYD5lUjYFFiSfpN4y3/iQCJUAVwFaQ1rVvHs4WXTa5C8E7gyF3kxwsMS8KgttW7WBAPtFlsvAg==} + dev: true + + /@types/stack-utils@2.0.3: + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + + /@types/supercluster@7.1.3: + resolution: {integrity: sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==} + dependencies: + '@types/geojson': 7946.0.16 + dev: false + + /@types/tapable@1.0.12: + resolution: {integrity: sha512-bTHG8fcxEqv1M9+TD14P8ok8hjxoOCkfKc8XXLaaD05kI7ohpeI956jtDOD3XHKBQrlyPughUtzm1jtVhHpA5Q==} + dev: true + + /@types/trusted-types@2.0.7: + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + dev: false + + /@types/uglify-js@3.17.5: + resolution: {integrity: sha512-TU+fZFBTBcXj/GpDpDaBmgWk/gn96kMZ+uocaFUlV2f8a6WdMzzI44QBCmGcCiYR0Y6ZlNRiyUyKKt5nl/lbzQ==} + dependencies: + source-map: 0.6.1 + dev: true + + /@types/validator@12.0.1: + resolution: {integrity: sha512-l57fIANZLMe8DArz+SDb+7ATXnDm15P7u2wHBw5mb0aSMd+UuvmvhouBF2hdLgQPDMJ39sh9g2MJO4GkZ0VAdQ==} + dev: true + + /@types/webpack-sources@3.2.3: + resolution: {integrity: sha512-4nZOdMwSPHZ4pTEZzSp0AsTM4K7Qmu40UKW4tJDiOVs20UzYF9l+qUe4s0ftfN0pin06n+5cWWDJXH+sbhAiDw==} + dependencies: + '@types/node': 22.13.10 + '@types/source-list-map': 0.1.6 + source-map: 0.7.4 + dev: true + + /@types/webpack@4.41.40: + resolution: {integrity: sha512-u6kMFSBM9HcoTpUXnL6mt2HSzftqb3JgYV6oxIgL2dl6sX6aCa5k6SOkzv5DuZjBTPUE/dJltKtwwuqrkZHpfw==} + dependencies: + '@types/node': 22.13.10 + '@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 + dev: true + + /@types/ws@8.18.0: + resolution: {integrity: sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw==} + dependencies: + '@types/node': 22.13.10 + dev: false + + /@types/yargs-parser@21.0.3: + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + /@types/yargs@15.0.19: + resolution: {integrity: sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==} + dependencies: + '@types/yargs-parser': 21.0.3 + + /@types/yargs@16.0.9: + resolution: {integrity: sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==} + dependencies: + '@types/yargs-parser': 21.0.3 + dev: false + + /@types/yargs@17.0.33: + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} + dependencies: + '@types/yargs-parser': 21.0.3 + dev: false + + /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@9.22.0)(typescript@4.9.5): + 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 + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 5.62.0(eslint@9.22.0)(typescript@4.9.5) + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/type-utils': 5.62.0(eslint@9.22.0)(typescript@4.9.5) + '@typescript-eslint/utils': 5.62.0(eslint@9.22.0)(typescript@4.9.5) + debug: 4.4.0 + eslint: 9.22.0 + 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) + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + dev: false + + /@typescript-eslint/experimental-utils@5.62.0(eslint@9.22.0)(typescript@4.9.5): + 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 + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@9.22.0)(typescript@4.9.5) + eslint: 9.22.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: false + + /@typescript-eslint/parser@5.62.0(eslint@9.22.0)(typescript@4.9.5): + 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 + 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.22.0 + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + dev: false + + /@typescript-eslint/scope-manager@5.62.0: + resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + dev: false + + /@typescript-eslint/type-utils@5.62.0(eslint@9.22.0)(typescript@4.9.5): + resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 5.62.0(typescript@4.9.5) + '@typescript-eslint/utils': 5.62.0(eslint@9.22.0)(typescript@4.9.5) + debug: 4.4.0 + eslint: 9.22.0 + tsutils: 3.21.0(typescript@4.9.5) + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + dev: false + + /@typescript-eslint/types@5.62.0: + resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: false + + /@typescript-eslint/typescript-estree@5.62.0(typescript@4.9.5): + 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 + 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) + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + dev: false + + /@typescript-eslint/utils@5.62.0(eslint@9.22.0)(typescript@4.9.5): + 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 + dependencies: + '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 + '@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.22.0 + eslint-scope: 5.1.1 + semver: 7.7.1 + transitivePeerDependencies: + - supports-color + - typescript + dev: false + + /@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} + dependencies: + '@typescript-eslint/types': 5.62.0 + eslint-visitor-keys: 3.4.3 + dev: false + + /@umijs/ast@3.5.43: + resolution: {integrity: sha512-P+yperHXuPCewEhgzKRXOxhpQmcK06J2PuLs7XaeQatpUTP//omJeIAcSHV8Rr9ynuvYnz9lS1qKqjgfjmZ8bA==} + dependencies: + '@umijs/utils': 3.5.43 + dev: false + + /@umijs/babel-plugin-auto-css-modules@3.5.43: + resolution: {integrity: sha512-u1JTVqgABY3cSCWsaRumnPINZzgUE5WDTsm7BYXf5a+mdZQiv87pCU2jC6S4OabMqm3mR75gJc5wLR4sFnlkrA==} + dependencies: + '@umijs/utils': 3.5.43 + + /@umijs/babel-plugin-import-to-await-require@3.5.43: + resolution: {integrity: sha512-PhPTS/i2yBEdZbsSp6Cj3cEcxwLOcacjzUgkH+g9vvVwMSAgMqkI1Tx57Y70LZorE4PeUNl5yeS9hGm24JAMQA==} + dependencies: + '@umijs/utils': 3.5.43 + + /@umijs/babel-plugin-lock-core-js-3@3.5.43: + resolution: {integrity: sha512-hOb6cyCrn/4SQ2qGc6RBOG7aPtMHqyuy2iJonzFobdbkOW5nOnYfK/F3oeSJqn/amynFr3W6cUdflyg3Mn5lRQ==} + dependencies: + '@umijs/utils': 3.5.43 + core-js: 3.6.5 + + /@umijs/babel-plugin-no-anonymous-default-export@3.5.43: + resolution: {integrity: sha512-itH+IV96AChX7zKDLEKNi6IEHL+RT8DsP8BSH3oDGWRE0OM4VlpM42N195bsMtOtdl7kCb9HUP1Bg1J/+hHwsw==} + dependencies: + '@umijs/utils': 3.5.43 + + /@umijs/babel-preset-umi@3.5.43: + resolution: {integrity: sha512-raFsiPYy70QNKM4jSo+qdO3wkZr9PCsSSz/+CGTUPkpre5sk6ISDcuXdvEJ92viMe1Xk1+LaPcnbJqIdu7EClA==} + 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-router@5.2.0)(react@16.14.0): + resolution: {integrity: sha512-Vw1qR+4KBQx/M1NwlDrMPydyBoA/qLT+nxZKAeIwCjkJT42QSJn38OMDqsRKRPkuoL5tLN4Ss+PbXoJ5evLWoA==} + dependencies: + '@umijs/babel-preset-umi': 3.5.43 + '@umijs/types': 3.5.43(react-dom@16.14.0)(react-router@5.2.0)(react@16.14.0) + '@umijs/utils': 3.5.43 + transitivePeerDependencies: + - react + - react-dom + - react-router + dev: false + + /@umijs/bundler-utils@3.5.43(react-dom@16.14.0)(react@16.14.0): + resolution: {integrity: sha512-Vw1qR+4KBQx/M1NwlDrMPydyBoA/qLT+nxZKAeIwCjkJT42QSJn38OMDqsRKRPkuoL5tLN4Ss+PbXoJ5evLWoA==} + dependencies: + '@umijs/babel-preset-umi': 3.5.43 + '@umijs/types': 3.5.43(react-dom@16.14.0)(react@16.14.0) + '@umijs/utils': 3.5.43 + transitivePeerDependencies: + - react + - react-dom + - react-router + dev: false + + /@umijs/bundler-webpack@3.5.43(react-dom@16.14.0)(react-router@5.2.0)(react@16.14.0): + resolution: {integrity: sha512-Sf15PCMSbt0QMnRcNGIU+Nd6dha5aBZPdOE7IdlWLXJ9rSICNuhblD2P5L8MscwomOXYvsPKzNGI92MUyfjq5w==} + hasBin: true + dependencies: + '@umijs/bundler-utils': 3.5.43(react-dom@16.14.0)(react-router@5.2.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-router@5.2.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 + dev: false + + /@umijs/bundler-webpack@3.5.43(react-dom@16.14.0)(react@16.14.0): + resolution: {integrity: sha512-Sf15PCMSbt0QMnRcNGIU+Nd6dha5aBZPdOE7IdlWLXJ9rSICNuhblD2P5L8MscwomOXYvsPKzNGI92MUyfjq5w==} + hasBin: true + dependencies: + '@umijs/bundler-utils': 3.5.43(react-dom@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) + '@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 + dev: false + + /@umijs/case-sensitive-paths-webpack-plugin@1.0.1: + resolution: {integrity: sha512-kDKJ8yTarxwxGJDInG33hOpaQRZ//XpNuuznQ/1Mscypw6kappzFmrBr2dOYave++K7JHouoANF354UpbEQw0Q==} + dev: false + + /@umijs/core@3.5.43: + resolution: {integrity: sha512-YT/ZrYZl5xrffW3WyDzsrec0FMhebjDoJSA7A2X2WX8lmsIhjzrVEDeR265+t5J+OH7joB8pMMiV/tvhVPHb7w==} + dependencies: + '@umijs/ast': 3.5.43 + '@umijs/babel-preset-umi': 3.5.43 + '@umijs/deps': 3.5.43 + '@umijs/utils': 3.5.43 + dev: false + + /@umijs/deps@3.5.43: + resolution: {integrity: sha512-1UugbYw+Emcq1AngzLgCvpMDdIVjpBVGwdrWDcxt3zjSR/2teRbaMdzUEqaMaqMWYVMbZKorARuyit5hZorrXQ==} + 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(typescript@4.9.5): + resolution: {integrity: sha512-hIilb15A8Md0aUBsuvX2nH24oVjue9OIBETapKbtanWqYCqUBcOvNZ5SBAtzVD1kVx80Q6oNlCRYKBsS80W31w==} + hasBin: true + 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 + nunjucks: 3.2.4 + openapi3-ts: 2.0.2 + prettier: 2.8.8 + reserved-words: 0.1.2 + rimraf: 3.0.2 + swagger2openapi: 7.0.8 + tiny-pinyin: 1.3.2 + transitivePeerDependencies: + - chokidar + - encoding + - typescript + + /@umijs/plugin-access@2.4.3(@umijs/plugin-initial-state@2.4.0)(@umijs/plugin-model@2.6.2)(umi@3.5.43): + resolution: {integrity: sha512-6FON4aHzVFs/vtFK5Sdnw+FBolfoYi8wV8V9Q8x2T19NwjZtjXSPjt0gtrG4jdx4LRsSV2DKLaMGoJYbNr94aA==} + peerDependencies: + '@umijs/plugin-initial-state': 2.x + '@umijs/plugin-model': 2.x + umi: 3.x + dependencies: + '@umijs/plugin-initial-state': 2.4.0(umi@3.5.43) + '@umijs/plugin-model': 2.6.2(umi@3.5.43) + umi: 3.5.43 + dev: false + + /@umijs/plugin-analytics@0.2.2(umi@3.5.43): + resolution: {integrity: sha512-dVDzUfgIdEwdCC6a5IsMYpIPI+bEZjBEqIhAvw9dic6Vk77w9RxQxyRfW11dDmdXLAwWphp22NntQNt1ejZPtg==} + peerDependencies: + umi: 3.x + dependencies: + umi: 3.5.43 + dev: false + + /@umijs/plugin-antd@0.13.0(umi@3.5.43): + resolution: {integrity: sha512-7tooYtOylVatrzMWCJtk8JFQL90i94OD0FgZYpKBbM7keThH8prYkSkDJFIDkuGfZ6pl6BJT8ESnYLxf2OiQUw==} + peerDependencies: + umi: 3.x + dependencies: + antd: 4.24.16 + antd-mobile: 2.3.4 + semver: 7.7.1 + umi: 3.5.43 + transitivePeerDependencies: + - react + - react-dom + dev: false + + /@umijs/plugin-crossorigin@1.2.1(umi@3.5.43): + resolution: {integrity: sha512-4oXNFBLOCH1FHTgFi7EDmlcjjYMthOQlrTT+mSbNeMzvl0P/WKldSJsYAUXUTg+I7vlbb5bNby4dpHKK37JcbQ==} + peerDependencies: + umi: 3.x + dependencies: + umi: 3.5.43 + dev: false + + /@umijs/plugin-dva@0.13.0(umi@3.5.43): + resolution: {integrity: sha512-cpGq8vzN8AmyWxexWLQ+WGqfT0WMCiryvU5EcNGbx1/Ub9aICUfPBpB46cxJrxjDCjUzuVslRNb2pdgI0xXUXg==} + peerDependencies: + umi: 3.x + dependencies: + babel-plugin-dva-hmr: 0.4.2 + dva: 2.6.0-beta.23 + dva-immer: 0.5.2(dva@2.6.0-beta.23) + dva-loading: 3.0.25 + umi: 3.5.43 + transitivePeerDependencies: + - dva-core + - react + - react-dom + - react-native + - react-router + - redbox-react + dev: false + + /@umijs/plugin-helmet@1.1.3(umi@3.5.43): + resolution: {integrity: sha512-X4GRFlvOb8DxMDm1vExfpWOvxl6bp0oZz114DyhwnMSriJ8RcHAigTjtVJHYxJpKv7P6KayN3n13J4w/XZGWMg==} + peerDependencies: + umi: 3.x + dependencies: + '@types/react-helmet': 6.1.11 + react-helmet: 6.1.0 + umi: 3.5.43 + transitivePeerDependencies: + - react + dev: false + + /@umijs/plugin-initial-state@2.4.0(umi@3.5.43): + resolution: {integrity: sha512-UHH5fTL9skm4771R3xvWCrjd5xiQ7OdJ83G0P1YZLhuNbh0cAFVT8SPTU8dA9o8TTAZ66IEq7axhWl1cGxVsXw==} + peerDependencies: + umi: 3.x + dependencies: + umi: 3.5.43 + dev: false + + /@umijs/plugin-layout@0.18.1(@umijs/plugin-initial-state@2.4.0)(@umijs/plugin-locale@0.15.2)(@umijs/plugin-model@2.6.2)(umi@3.5.43): + 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 + dependencies: + '@umijs/plugin-initial-state': 2.4.0(umi@3.5.43) + '@umijs/plugin-locale': 0.15.2(umi@3.5.43) + '@umijs/plugin-model': 2.6.2(umi@3.5.43) + '@umijs/route-utils': 2.2.2 + antd: 4.24.16 + lodash: 4.17.21 + path-to-regexp: 1.9.0 + umi: 3.5.43 + transitivePeerDependencies: + - react + - react-dom + dev: false + + /@umijs/plugin-locale@0.15.2(umi@3.5.43): + resolution: {integrity: sha512-/m3ik0NKbE/PHFPKPqSBEwGi5RUB6Dz2T7jepDXhU8ycV0zUPGbDbChUx1r/3t5zveZIND1s/7A49Apb+ujUmg==} + peerDependencies: + umi: 3.x + dependencies: + '@ant-design/icons': 4.8.3 + '@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 + umi: 3.5.43 + warning: 4.0.3 + transitivePeerDependencies: + - react + - react-dom + dev: false + + /@umijs/plugin-model@2.6.2(umi@3.5.43): + resolution: {integrity: sha512-MKLAgYIoBkciavxTqJY6VOhvnNQv7jp+olNmXqqZ3I3WsLg7jo33NCOAA3ej103kmo9ZvD9R1aakl7e9WKsdAw==} + peerDependencies: + umi: 3.x + dependencies: + fast-deep-equal: 3.1.1 + umi: 3.5.43 + dev: false + + /@umijs/plugin-openapi@1.3.3(typescript@4.9.5)(umi@3.5.43): + resolution: {integrity: sha512-z1gJpX1MDAO5YlJH+zsQ4bq0jgmIoy89k5lyTylVvP22M31h7sC9cAwNHmQeJMzGatYooGJu//rnThsSlRdIUg==} + peerDependencies: + umi: 3.x + dependencies: + '@umijs/openapi': 1.13.0(typescript@4.9.5) + serve-static: 1.16.2 + swagger-ui-dist: 4.19.1 + umi: 3.5.43 + transitivePeerDependencies: + - chokidar + - encoding + - supports-color + - typescript + dev: false + + /@umijs/plugin-request@2.8.0(umi@3.5.43): + resolution: {integrity: sha512-bwJg0rFbMZcizO+fHbSNz6X/U6suR84ciLIo9zLtRMuradx/yanMnz+ckh2dlZvTlGYrckkJwWgoSFxWlU8yyA==} + peerDependencies: + umi: 3.x + dependencies: + '@ahooksjs/use-request': 2.8.15 + umi: 3.5.43 + umi-request: 1.4.0 + transitivePeerDependencies: + - react + dev: false + + /@umijs/plugin-test@1.0.2(umi@3.5.43): + resolution: {integrity: sha512-EIV86Xmw/Cn8vRLXha+ct0PfY6gRRKov5lanvt1B2L5t6xAqnTd03AxmB7i1Go9vDcFxDBheuDf/nyGiT/xTFw==} + peerDependencies: + umi: 3.x + dependencies: + '@umijs/test': 3.5.43 + umi: 3.5.43 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + dev: false + + /@umijs/preset-built-in@3.5.43(react-dom@16.14.0)(react@16.14.0): + resolution: {integrity: sha512-h9DVc5MjdUON7/xH3bxq76AHDPBTLjntDWBrW6xn+OhDT4j8/YFXrDQwaCwihCJe1eNUBLoVUjWIEIthw7g1Gg==} + peerDependencies: + react: 16.x || 17.x + 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-router@5.2.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) + '@umijs/renderer-react': 3.5.43(react-dom@16.14.0)(react-router@5.2.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-router@5.2.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.5.2 + 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-router-dom: 5.2.0(react@16.14.0) + regenerator-runtime: 0.13.5 + schema-utils: 3.3.0 + transitivePeerDependencies: + - react-dom + dev: false + + /@umijs/preset-react@1.8.32(umi@3.5.43): + resolution: {integrity: sha512-f/jJRxIRzRrZ040GMdBuV3byvtbx35oWymDT5A/q/e+QmjCrs6c9XCRktGInKIhZycqI/GuA6eLaxXIKvu6b9A==} + peerDependencies: + umi: 3.x + dependencies: + '@umijs/plugin-access': 2.4.3(@umijs/plugin-initial-state@2.4.0)(@umijs/plugin-model@2.6.2)(umi@3.5.43) + '@umijs/plugin-analytics': 0.2.2(umi@3.5.43) + '@umijs/plugin-antd': 0.13.0(umi@3.5.43) + '@umijs/plugin-crossorigin': 1.2.1(umi@3.5.43) + '@umijs/plugin-dva': 0.13.0(umi@3.5.43) + '@umijs/plugin-helmet': 1.1.3(umi@3.5.43) + '@umijs/plugin-initial-state': 2.4.0(umi@3.5.43) + '@umijs/plugin-layout': 0.18.1(@umijs/plugin-initial-state@2.4.0)(@umijs/plugin-locale@0.15.2)(@umijs/plugin-model@2.6.2)(umi@3.5.43) + '@umijs/plugin-locale': 0.15.2(umi@3.5.43) + '@umijs/plugin-model': 2.6.2(umi@3.5.43) + '@umijs/plugin-request': 2.8.0(umi@3.5.43) + '@umijs/plugin-test': 1.0.2(umi@3.5.43) + umi: 3.5.43 + 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 + dev: false + + /@umijs/renderer-mpa@3.5.43(react-dom@16.14.0)(react@16.14.0): + resolution: {integrity: sha512-posQsrkFru/Q9Jft42w4pr/MEFsImd9DlKOV9zYil1ZM6JBS3/hKMmCeSd2Uku7+KgSS/8HSfc4qX/GyeRTzwA==} + peerDependencies: + react: 16.x || 17.x + react-dom: 16.x || 17.x + dependencies: + '@types/react': 16.14.62 + '@types/react-dom': 16.9.25(@types/react@16.14.62) + '@umijs/runtime': 3.5.43(react@16.14.0) + react: 16.14.0 + react-dom: 16.14.0(react@16.14.0) + dev: false + + /@umijs/renderer-react@3.5.43(react-dom@16.14.0)(react-router@5.2.0)(react@16.14.0): + resolution: {integrity: sha512-nadGLVbc6qrEX5pd+qY4nr9Mzl7x2hhxec2JeAd2Bg0JkZYNC8H4crTfe844uLm3MvqAtAhomGhN5c0ejDEBhA==} + peerDependencies: + react: 16.x || 17.x + react-dom: 16.x || 17.x + dependencies: + '@types/react': 16.14.62 + '@types/react-dom': 16.9.25(@types/react@16.14.62) + '@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) + transitivePeerDependencies: + - react-router + dev: false + + /@umijs/renderer-react@3.5.43(react-dom@16.14.0)(react@16.14.0): + resolution: {integrity: sha512-nadGLVbc6qrEX5pd+qY4nr9Mzl7x2hhxec2JeAd2Bg0JkZYNC8H4crTfe844uLm3MvqAtAhomGhN5c0ejDEBhA==} + peerDependencies: + react: 16.x || 17.x + react-dom: 16.x || 17.x + dependencies: + '@types/react': 16.14.62 + '@types/react-dom': 16.9.25(@types/react@16.14.62) + '@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@16.14.0) + transitivePeerDependencies: + - react-router + dev: false + + /@umijs/route-utils@2.2.2: + resolution: {integrity: sha512-cMk6qizy0pfpiwpVCvNQB0BKBUJEH33pDv5q5k2tSleSDw2abkJkTu2Kd5hKzoESLuFK43oGeOfcplZqm2bRxw==} + 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 + dev: false + + /@umijs/route-utils@4.0.1: + resolution: {integrity: sha512-+1ixf1BTOLuH+ORb4x8vYMPeIt38n9q0fJDwhv9nSxrV46mxbLF0nmELIo9CKQB2gHfuC4+hww6xejJ6VYnBHQ==} + dev: false + + /@umijs/runtime@3.5.43(react@16.14.0): + resolution: {integrity: sha512-jCmkF5QcqbqzJgtd12Hy6XthLTAcaD4feMHnzM+UqTE74N7lfD13P0brXHrGqkcLbI1NgUs+9rKYIUa56w6jpw==} + peerDependencies: + react: 16.x || 17.x + 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) + dev: false + + /@umijs/server@3.5.43: + resolution: {integrity: sha512-aUSNqnO6WvhgIU6jK1+2YCNkuP6UgiEhTaT/VkSPZdCjagfov2ZfJQ0xWl8x7tocuAaBph6UvXFJWjCQvZ5pHw==} + dependencies: + '@umijs/core': 3.5.43 + '@umijs/deps': 3.5.43 + '@umijs/utils': 3.5.43 + dev: false + + /@umijs/test@3.5.43: + resolution: {integrity: sha512-9jrziC5ngjrfiJFSdhNDMYcQNrnCQoph/Bu8lZsuBmBQwswN3YqVqefDc4fh4Kl1e4OisKtDfUDtUro8ZApaRQ==} + hasBin: true + 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 + jest-cli: 26.6.3 + 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-router@5.2.0)(react@16.14.0): + resolution: {integrity: sha512-XVZuT1X+VpPYrdlDEeginBwBNZaYUDtt3WOyFvfGmBEdqD0iNx0ZgyWmJBhlfRcck5+oYkFpOzmmRIROux2zlA==} + 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-router@5.2.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 + dev: false + + /@umijs/types@3.5.43(react-dom@16.14.0)(react@16.14.0): + resolution: {integrity: sha512-XVZuT1X+VpPYrdlDEeginBwBNZaYUDtt3WOyFvfGmBEdqD0iNx0ZgyWmJBhlfRcck5+oYkFpOzmmRIROux2zlA==} + 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) + '@umijs/server': 3.5.43 + '@umijs/utils': 3.5.43 + webpack-chain: 6.5.1 + transitivePeerDependencies: + - react + - react-dom + - react-router + dev: false + + /@umijs/use-params@1.0.9: + resolution: {integrity: sha512-QlN0RJSBVQBwLRNxbxjQ5qzqYIGn+K7USppMoIOVlf7fxXHsnQZ2bEsa6Pm74bt6DVQxpUE8HqvdStn6Y9FV1w==} + peerDependencies: + react: '*' + dev: false + + /@umijs/utils@3.5.43: + resolution: {integrity: sha512-LQrCkZEa9Fb0zhId1n6CdU489tzJp4/usHVvVcTwjah7jF48zrHXD4OClGjSxvZ63d+3950mZY5IWE9UZVhnDg==} + dependencies: + '@umijs/babel-preset-umi': 3.5.43 + '@umijs/deps': 3.5.43 + + /@webassemblyjs/ast@1.14.1: + resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} + dependencies: + '@webassemblyjs/helper-numbers': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + dev: false + + /@webassemblyjs/floating-point-hex-parser@1.13.2: + resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==} + dev: false + + /@webassemblyjs/helper-api-error@1.13.2: + resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==} + dev: false + + /@webassemblyjs/helper-buffer@1.14.1: + resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==} + dev: false + + /@webassemblyjs/helper-numbers@1.13.2: + resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==} + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.13.2 + '@webassemblyjs/helper-api-error': 1.13.2 + '@xtuc/long': 4.2.2 + dev: false + + /@webassemblyjs/helper-wasm-bytecode@1.13.2: + resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==} + dev: false + + /@webassemblyjs/helper-wasm-section@1.14.1: + resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==} + 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 + dev: false + + /@webassemblyjs/ieee754@1.13.2: + resolution: {integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==} + dependencies: + '@xtuc/ieee754': 1.2.0 + dev: false + + /@webassemblyjs/leb128@1.13.2: + resolution: {integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==} + dependencies: + '@xtuc/long': 4.2.2 + dev: false + + /@webassemblyjs/utf8@1.13.2: + resolution: {integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==} + dev: false + + /@webassemblyjs/wasm-edit@1.14.1: + resolution: {integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==} + 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 + dev: false + + /@webassemblyjs/wasm-gen@1.14.1: + resolution: {integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==} + 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 + dev: false + + /@webassemblyjs/wasm-opt@1.14.1: + resolution: {integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==} + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + dev: false + + /@webassemblyjs/wasm-parser@1.14.1: + resolution: {integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==} + 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 + dev: false + + /@webassemblyjs/wast-printer@1.14.1: + resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@xtuc/long': 4.2.2 + dev: false + + /@webgpu/glslang@0.0.15: + resolution: {integrity: sha512-niT+Prh3Aff8Uf1MVBVUsaNjFj9rJAKDXuoHIKiQbB+6IUP/3J3JIhBNyZ7lDhytvXxw6ppgnwKZdDJ08UMj4Q==} + dev: false + + /@webgpu/types@0.0.31: + resolution: {integrity: sha512-cvvCMSZBT4VsRNtt0lI6XQqvOIIWw6+NRUtnPUMDVDgsI4pCZColz3qzF5QcP9wIYOHEc3jssIBse8UWONKhlQ==} + dev: false + + /@webgpu/types@0.1.56: + resolution: {integrity: sha512-JkT4ngqwk4gKAFoWtXCcC1+TGhSStVtauS9z27slOGSFYr+QqjS0CoawiAxP7Gq9xkT4Pw9uouvWPT44HwbUiw==} + dev: false + + /@xobotyi/scrollbar-width@1.9.5: + resolution: {integrity: sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==} + dev: false + + /@xtuc/ieee754@1.2.0: + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + dev: false + + /@xtuc/long@4.2.2: + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + dev: false + + /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'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + dev: false + + /acorn-globals@6.0.0: + resolution: {integrity: sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==} + dependencies: + acorn: 7.4.1 + acorn-walk: 7.2.0 + + /acorn-jsx@5.3.2(acorn@8.14.1): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.14.1 + + /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'} + dependencies: + acorn: 8.14.1 + dev: true + + /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==} + dependencies: + object-assign: 4.1.1 + dev: false + + /address@1.2.2: + resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} + engines: {node: '>= 10.0.0'} + dev: false + + /adjust-sourcemap-loader@4.0.0: + resolution: {integrity: sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==} + engines: {node: '>=8.9'} + dependencies: + loader-utils: 2.0.4 + regex-parser: 2.3.1 + dev: false + + /adler-32@1.2.0: + resolution: {integrity: sha512-/vUqU/UY4MVeFsg+SsK6c+/05RZXIHZMGJA+PX5JyWI0ZRcBpupnRuPLU/NXXoFwMYCPCoxIfElM2eS+DUXCqQ==} + engines: {node: '>=0.8'} + hasBin: true + dependencies: + exit-on-epipe: 1.0.1 + printj: 1.1.2 + dev: false + + /adler-32@1.3.1: + resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==} + engines: {node: '>=0.8'} + dev: false + + /agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + + /aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + + /ahooks@2.10.14: + resolution: {integrity: sha512-axWa7VoAgu7bxA56dDl0CXW4rvaQmDBiov/d3tAy0x1YNYywYMKokL8TdLgJ5zO/oXGiWmG7BxlGOQGkqE/zkQ==} + engines: {node: '>=8.0.0'} + peerDependencies: + react: ^16.8.6 || ^17.0 + dependencies: + '@ahooksjs/use-request': 2.8.15 + '@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 + resize-observer-polyfill: 1.5.1 + screenfull: 5.2.0 + dev: false + + /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 + dependencies: + '@babel/runtime': 7.26.10 + dayjs: 1.11.13 + intersection-observer: 0.12.2 + js-cookie: 3.0.5 + lodash: 4.17.21 + react-fast-compare: 3.2.2 + resize-observer-polyfill: 1.5.1 + screenfull: 5.2.0 + tslib: 2.8.1 + dev: false + + /ajv-errors@1.0.1(ajv@6.12.6): + resolution: {integrity: sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==} + peerDependencies: + ajv: '>=5.0.0' + dependencies: + ajv: 6.12.6 + dev: false + + /ajv-formats@2.1.1: + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependenciesMeta: + ajv: + optional: true + dependencies: + ajv: 8.17.1 + dev: false + + /ajv-keywords@3.5.2(ajv@6.12.6): + resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} + peerDependencies: + ajv: ^6.9.1 + dependencies: + ajv: 6.12.6 + + /ajv-keywords@5.1.0(ajv@8.17.1): + resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} + peerDependencies: + ajv: ^8.8.2 + dependencies: + ajv: 8.17.1 + fast-deep-equal: 3.1.3 + dev: false + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + /ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.6 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + dev: false + + /align-text@0.1.4: + resolution: {integrity: sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + longest: 1.0.1 + repeat-string: 1.6.1 + dev: false + + /amdefine@1.0.1: + resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==} + engines: {node: '>=0.4.2'} + dev: false + + /ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + dev: true + + /ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + + /ansi-html-community@0.0.8: + resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} + engines: {'0': node >= 0.8.0} + hasBin: true + dev: false + + /ansi-html@0.0.9: + resolution: {integrity: sha512-ozbS3LuenHVxNRh/wdnN16QapUHzauqSomAl1jwwJRRsGwFwtj644lIhxfWu0Fy0acCij2+AEgHvjscq3dlVXg==} + engines: {'0': node >= 0.8.0} + hasBin: true + dev: false + + /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'} + dev: false + + /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'} + dependencies: + color-convert: 1.9.3 + dev: false + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + + /ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + dev: false + + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: false + + /antd-mobile@2.3.4: + resolution: {integrity: sha512-Uw02Ghc+DPzaQceJQ+5p1ZnQFafvILA0chTTen7m7c89Uzbw6Ny3zsVZDE1gfteNEIsL4JpPe0I/+aI3Q/nPAA==} + 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 + rc-slider: 8.2.0 + rc-swipeout: 2.0.11 + rmc-calendar: 1.1.4 + rmc-cascader: 5.0.3 + rmc-date-picker: 6.0.10 + rmc-dialog: 1.1.1 + 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 + rmc-nuka-carousel: 3.0.1 + rmc-picker: 5.0.10 + rmc-pull-to-refresh: 1.0.13 + rmc-steps: 1.0.1 + rmc-tabs: 1.2.29 + rmc-tooltip: 1.0.1 + transitivePeerDependencies: + - react + - react-dom + dev: false + + /antd-style@3.7.1(@types/react@17.0.52)(antd@5.24.4): + resolution: {integrity: sha512-CQOfddVp4aOvBfCepa+Kj2e7ap+2XBINg1Kn2osdE3oQvrD7KJu/K0sfnLcFLkgCJygbxmuazYdWLKb+drPDYA==} + peerDependencies: + antd: '>=5.8.1' + react: '>=18' + dependencies: + '@ant-design/cssinjs': 1.23.0 + '@babel/runtime': 7.26.10 + '@emotion/cache': 11.14.0 + '@emotion/css': 11.13.5 + '@emotion/react': 11.14.0(@types/react@17.0.52) + '@emotion/serialize': 1.3.3 + '@emotion/utils': 1.4.2 + antd: 5.24.4(moment@2.30.1) + use-merge-value: 1.2.0 + transitivePeerDependencies: + - '@types/react' + - react-dom + - supports-color + dev: false + + /antd@4.24.16: + resolution: {integrity: sha512-zZrK4UYxHtU6tGOOf0uG/kBRx1kTvypfuSB3GqE/SBQxFhZ/TZ+yj7Z1qwI8vGfMtUUJdLeuoCAqGDa1zPsXnQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@ant-design/colors': 6.0.0 + '@ant-design/icons': 4.8.3 + '@ant-design/react-slick': 1.0.2 + '@babel/runtime': 7.26.10 + '@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 + rc-checkbox: 3.0.1 + rc-collapse: 3.4.2 + rc-dialog: 9.0.4 + rc-drawer: 6.3.0 + rc-dropdown: 4.0.1 + rc-field-form: 1.38.2 + rc-image: 5.13.0 + rc-input: 0.1.4 + rc-input-number: 7.3.11 + rc-mentions: 1.13.1 + rc-menu: 9.8.4 + rc-motion: 2.9.5 + rc-notification: 4.6.1 + rc-pagination: 3.2.0 + rc-picker: 2.7.6 + rc-progress: 3.4.2 + rc-rate: 2.9.3 + rc-resize-observer: 1.4.3 + rc-segmented: 2.3.0 + rc-select: 14.1.18 + rc-slider: 10.0.1 + rc-steps: 5.0.0 + rc-switch: 3.2.2 + rc-table: 7.26.0 + rc-tabs: 12.5.10 + rc-textarea: 0.4.7 + rc-tooltip: 5.2.2 + rc-tree: 5.7.12 + rc-tree-select: 5.5.5 + rc-trigger: 5.3.4 + rc-upload: 4.3.6 + rc-util: 5.44.4 + scroll-into-view-if-needed: 2.2.31 + dev: false + + /antd@5.24.4(moment@2.30.1): + resolution: {integrity: sha512-s89666DcoWeekJFaIqbtz2vRlIvgPR28GuDYYGUpW1mVP08bV7HZAPBH5lFJKYNGKrN3dHbZGgRK5aNRD2iPHg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@ant-design/colors': 7.2.0 + '@ant-design/cssinjs': 1.23.0 + '@ant-design/cssinjs-utils': 1.1.3 + '@ant-design/fast-color': 2.0.6 + '@ant-design/icons': 5.6.1 + '@ant-design/react-slick': 1.1.2 + '@babel/runtime': 7.26.10 + '@rc-component/color-picker': 2.0.1 + '@rc-component/mutate-observer': 1.1.0 + '@rc-component/qrcode': 1.0.0 + '@rc-component/tour': 1.15.1 + '@rc-component/trigger': 2.2.6 + classnames: 2.5.1 + copy-to-clipboard: 3.3.3 + dayjs: 1.11.13 + rc-cascader: 3.33.1 + rc-checkbox: 3.5.0 + rc-collapse: 3.9.0 + rc-dialog: 9.6.0 + rc-drawer: 7.2.0 + rc-dropdown: 4.2.1 + rc-field-form: 2.7.0 + rc-image: 7.11.1 + rc-input: 1.7.3 + rc-input-number: 9.4.0 + rc-mentions: 2.19.1 + rc-menu: 9.16.1 + rc-motion: 2.9.5 + rc-notification: 5.6.3 + rc-pagination: 5.1.0 + rc-picker: 4.11.3(dayjs@1.11.13)(moment@2.30.1) + rc-progress: 4.0.0 + rc-rate: 2.13.1 + rc-resize-observer: 1.4.3 + rc-segmented: 2.7.0 + rc-select: 14.16.6 + rc-slider: 11.1.8 + rc-steps: 6.0.1 + rc-switch: 4.1.0 + rc-table: 7.50.4 + rc-tabs: 15.5.1 + rc-textarea: 1.9.0 + rc-tooltip: 6.4.0 + rc-tree: 5.13.1 + rc-tree-select: 5.27.0 + rc-upload: 4.8.1 + rc-util: 5.44.4 + scroll-into-view-if-needed: 3.1.0 + throttle-debounce: 5.0.2 + transitivePeerDependencies: + - date-fns + - luxon + - moment + dev: false + + /any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + dev: false + + /anymatch@1.3.2: + resolution: {integrity: sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==} + requiresBuild: true + dependencies: + micromatch: 2.3.11 + normalize-path: 2.1.1 + dev: true + optional: true + + /anymatch@2.0.0: + resolution: {integrity: sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==} + dependencies: + micromatch: 3.1.10 + normalize-path: 2.1.1 + transitivePeerDependencies: + - supports-color + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + /arch@2.2.0: + resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} + + /arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + dev: true + + /arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + dev: false + + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + + /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'} + dev: false + + /arr-diff@2.0.0: + resolution: {integrity: sha512-dtXTVMkh6VkEEA7OhXnN1Ecb8aAGFdZ1LFxtOCoqj4qkyOJMt7+qs6Ahdy6p/NQCPYsRSXXivhSB/J5E9jmYKA==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + arr-flatten: 1.1.0 + dev: true + optional: true + + /arr-diff@4.0.0: + resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} + engines: {node: '>=0.10.0'} + requiresBuild: true + + /arr-flatten@1.1.0: + resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==} + engines: {node: '>=0.10.0'} + requiresBuild: true + + /arr-union@3.1.0: + resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} + engines: {node: '>=0.10.0'} + requiresBuild: true + + /array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + /array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + dev: false + + /array-includes@3.1.8: + resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} + engines: {node: '>= 0.4'} + 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 + dev: false + + /array-tree-filter@2.1.0: + resolution: {integrity: sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==} + dev: false + + /array-union@1.0.2: + resolution: {integrity: sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==} + engines: {node: '>=0.10.0'} + dependencies: + array-uniq: 1.0.3 + dev: false + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: false + + /array-uniq@1.0.3: + resolution: {integrity: sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==} + engines: {node: '>=0.10.0'} + dev: false + + /array-unique@0.2.1: + resolution: {integrity: sha512-G2n5bG5fSUCpnsXz4+8FUkYsGPkNfLn9YvS66U5qbTIXI2Ynnlo4Bi42bWv+omKUCqz+ejzfClwne0alJWJPhg==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dev: true + optional: true + + /array-unique@0.3.2: + resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + + /array.prototype.findlast@1.2.5: + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} + 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 + dev: false + + /array.prototype.findlastindex@1.2.6: + resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==} + engines: {node: '>= 0.4'} + 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 + dev: false + + /array.prototype.flat@1.3.3: + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-shim-unscopables: 1.1.0 + dev: false + + /array.prototype.flatmap@1.3.3: + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-shim-unscopables: 1.1.0 + dev: false + + /array.prototype.reduce@1.0.8: + resolution: {integrity: sha512-DwuEqgXFBwbmZSRqt3BpQigWNUoqw9Ml2dTWdF3B2zQlQX4OeUE0zyuzX0fX0IbTvjdkZbcBTU3idgpO78qkTw==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} + engines: {node: '>= 0.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 + dev: false + + /arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 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: + resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==} + engines: {node: '>=8'} + dev: false + + /as-number@1.0.0: + resolution: {integrity: sha512-HkI/zLo2AbSRO4fqVkmyf3hms0bJDs3iboHqTrNuwTiCRvdYXM7HFhfhB6Dk51anV2LM/IMB83mtK9mHw4FlAg==} + dev: false + + /asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + + /asn1.js@4.10.1: + resolution: {integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==} + dependencies: + bn.js: 4.12.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + dev: false + + /assert@1.5.1: + resolution: {integrity: sha512-zzw1uCAgLbsKwBfFc8CX78DDg+xZeBksSO3vwVIDDN5i94eOrPsSSyiVhmsSABFDM/OcpE2aagCat9dnWQLG1A==} + dependencies: + object.assign: 4.1.7 + util: 0.10.4 + dev: false + + /assign-symbols@1.0.0: + resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} + engines: {node: '>=0.10.0'} + requiresBuild: true + + /ast-types-flow@0.0.8: + resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + dev: false + + /astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + dev: true + + /async-each@1.0.6: + resolution: {integrity: sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg==} + requiresBuild: true + dev: true + optional: true + + /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==} + dev: false + + /async-validator@4.2.5: + resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} + dev: false + + /async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + dev: false + + /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'} + dev: false + + /atob@2.1.2: + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} + engines: {node: '>= 4.5.0'} + hasBin: true + requiresBuild: true + + /autoprefixer@10.4.21(postcss@8.5.3): + resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + dependencies: + browserslist: 4.24.4 + caniuse-lite: 1.0.30001705 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.1.1 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /autoprefixer@9.8.8: + resolution: {integrity: sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==} + hasBin: true + dependencies: + browserslist: 4.24.4 + caniuse-lite: 1.0.30001705 + normalize-range: 0.1.2 + num2fraction: 1.2.2 + picocolors: 0.2.1 + postcss: 7.0.32 + postcss-value-parser: 4.2.0 + dev: false + + /available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + dependencies: + possible-typed-array-names: 1.1.0 + + /axe-core@4.10.3: + resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==} + engines: {node: '>=4'} + dev: false + + /axios@0.21.4: + resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} + dependencies: + follow-redirects: 1.15.9 + transitivePeerDependencies: + - debug + dev: true + + /axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + dev: false + + /babel-cli@6.26.0: + resolution: {integrity: sha512-wau+BDtQfuSBGQ9PzzFL3REvR9Sxnd4LKwtcHAiPjhugA7K/80vpHXafj+O5bAqJOuSefjOx5ZJnNSR2J1Qw6Q==} + hasBin: true + 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 + dev: true + + /babel-code-frame@6.26.0: + resolution: {integrity: sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==} + dependencies: + chalk: 1.1.3 + esutils: 2.0.3 + js-tokens: 3.0.2 + dev: true + + /babel-core@6.26.3: + resolution: {integrity: sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==} + 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 + dev: true + + /babel-generator@6.26.1: + resolution: {integrity: sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==} + 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 + dev: true + + /babel-helper-call-delegate@6.24.1: + resolution: {integrity: sha512-RL8n2NiEj+kKztlrVJM9JT1cXzzAdvWFh76xh/H1I4nKwunzE4INBXn8ieCZ+wh4zWszZk7NBS1s/8HR5jDkzQ==} + 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 + dev: true + + /babel-helper-define-map@6.26.0: + resolution: {integrity: sha512-bHkmjcC9lM1kmZcVpA5t2om2nzT/xiZpo6TJq7UlZ3wqKfzia4veeXbIhKvJXAMzhhEBd3cR1IElL5AenWEUpA==} + 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 + dev: true + + /babel-helper-function-name@6.24.1: + resolution: {integrity: sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q==} + 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 + dev: true + + /babel-helper-get-function-arity@6.24.1: + resolution: {integrity: sha512-WfgKFX6swFB1jS2vo+DwivRN4NB8XUdM3ij0Y1gnC21y1tdBoe6xjVnd7NSI6alv+gZXCtJqvrTeMW3fR/c0ng==} + dependencies: + babel-runtime: 6.26.0 + babel-types: 6.26.0 + dev: true + + /babel-helper-hoist-variables@6.24.1: + resolution: {integrity: sha512-zAYl3tqerLItvG5cKYw7f1SpvIxS9zi7ohyGHaI9cgDUjAT6YcY9jIEH5CstetP5wHIVSceXwNS7Z5BpJg+rOw==} + dependencies: + babel-runtime: 6.26.0 + babel-types: 6.26.0 + dev: true + + /babel-helper-optimise-call-expression@6.24.1: + resolution: {integrity: sha512-Op9IhEaxhbRT8MDXx2iNuMgciu2V8lDvYCNQbDGjdBNCjaMvyLf4wl4A3b8IgndCyQF8TwfgsQ8T3VD8aX1/pA==} + dependencies: + babel-runtime: 6.26.0 + babel-types: 6.26.0 + dev: true + + /babel-helper-regex@6.26.0: + resolution: {integrity: sha512-VlPiWmqmGJp0x0oK27Out1D+71nVVCTSdlbhIVoaBAj2lUgrNjBCRR9+llO4lTSb2O4r7PJg+RobRkhBrf6ofg==} + dependencies: + babel-runtime: 6.26.0 + babel-types: 6.26.0 + lodash: 4.17.21 + dev: true + + /babel-helper-replace-supers@6.24.1: + resolution: {integrity: sha512-sLI+u7sXJh6+ToqDr57Bv973kCepItDhMou0xCP2YPVmR1jkHSCY+p1no8xErbV1Siz5QE8qKT1WIwybSWlqjw==} + 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 + dev: true + + /babel-helpers@6.24.1: + resolution: {integrity: sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ==} + dependencies: + babel-runtime: 6.26.0 + babel-template: 6.26.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-jest@26.6.3(@babel/core@7.18.6): + resolution: {integrity: sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==} + engines: {node: '>= 10.14.2'} + peerDependencies: + '@babel/core': ^7.0.0 + 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): + 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 + 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 + dev: false + + /babel-loader@8.4.1(@babel/core@7.26.10)(webpack@5.98.0): + resolution: {integrity: sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==} + engines: {node: '>= 8.9'} + peerDependencies: + '@babel/core': ^7.0.0 + webpack: '>=2' + 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.98.0 + dev: false + + /babel-messages@6.23.0: + resolution: {integrity: sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w==} + dependencies: + babel-runtime: 6.26.0 + dev: true + + /babel-plugin-check-es2015-constants@6.22.0: + resolution: {integrity: sha512-B1M5KBP29248dViEo1owyY32lk1ZSH2DaNNrXLGt8lyjjHm7pBqAdQ7VKUPR6EEDO323+OvT3MQXbCin8ooWdA==} + dependencies: + babel-runtime: 6.26.0 + dev: true + + /babel-plugin-dva-hmr@0.4.2: + resolution: {integrity: sha512-QP5W0IT9LDFgoqkXD0g7wn/FMn7zO562P8qys23twXri4i3E1SGOQ3z7jqcPrqzfTZHx+Ufr+cXy9oI6OLMYZg==} + peerDependencies: + redbox-react: 1.x + dev: false + + /babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + 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: + resolution: {integrity: sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==} + engines: {node: '>= 10.14.2'} + dependencies: + '@babel/template': 7.26.9 + '@babel/types': 7.26.10 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.20.6 + + /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} + dependencies: + '@babel/template': 7.26.9 + '@babel/types': 7.26.10 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.20.6 + dev: false + + /babel-plugin-macros@3.1.0: + resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} + engines: {node: '>=10', npm: '>=6'} + dependencies: + '@babel/runtime': 7.26.10 + cosmiconfig: 7.1.0 + resolve: 1.22.10 + dev: false + + /babel-plugin-named-asset-import@0.3.8(@babel/core@7.26.10): + resolution: {integrity: sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==} + peerDependencies: + '@babel/core': ^7.1.0 + dependencies: + '@babel/core': 7.26.10 + dev: false + + /babel-plugin-polyfill-corejs2@0.4.12(@babel/core@7.26.10): + resolution: {integrity: sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/core': 7.26.10 + '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.10) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: false + + /babel-plugin-polyfill-corejs3@0.11.1(@babel/core@7.26.10): + resolution: {integrity: sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.10) + core-js-compat: 3.41.0 + transitivePeerDependencies: + - supports-color + dev: false + + /babel-plugin-polyfill-regenerator@0.6.3(@babel/core@7.26.10): + resolution: {integrity: sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.10) + transitivePeerDependencies: + - supports-color + dev: false + + /babel-plugin-transform-es2015-arrow-functions@6.22.0: + resolution: {integrity: sha512-PCqwwzODXW7JMrzu+yZIaYbPQSKjDTAsNNlK2l5Gg9g4rz2VzLnZsStvp/3c46GfXpwkyufb3NCyG9+50FF1Vg==} + dependencies: + babel-runtime: 6.26.0 + dev: true + + /babel-plugin-transform-es2015-block-scoped-functions@6.22.0: + resolution: {integrity: sha512-2+ujAT2UMBzYFm7tidUsYh+ZoIutxJ3pN9IYrF1/H6dCKtECfhmB8UkHVpyxDwkj0CYbQG35ykoz925TUnBc3A==} + dependencies: + babel-runtime: 6.26.0 + dev: true + + /babel-plugin-transform-es2015-block-scoping@6.26.0: + resolution: {integrity: sha512-YiN6sFAQ5lML8JjCmr7uerS5Yc/EMbgg9G8ZNmk2E3nYX4ckHR01wrkeeMijEf5WHNK5TW0Sl0Uu3pv3EdOJWw==} + 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 + dev: true + + /babel-plugin-transform-es2015-classes@6.24.1: + resolution: {integrity: sha512-5Dy7ZbRinGrNtmWpquZKZ3EGY8sDgIVB4CU8Om8q8tnMLrD/m94cKglVcHps0BCTdZ0TJeeAWOq2TK9MIY6cag==} + 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 + dev: true + + /babel-plugin-transform-es2015-computed-properties@6.24.1: + resolution: {integrity: sha512-C/uAv4ktFP/Hmh01gMTvYvICrKze0XVX9f2PdIXuriCSvUmV9j+u+BB9f5fJK3+878yMK6dkdcq+Ymr9mrcLzw==} + dependencies: + babel-runtime: 6.26.0 + babel-template: 6.26.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-transform-es2015-destructuring@6.23.0: + resolution: {integrity: sha512-aNv/GDAW0j/f4Uy1OEPZn1mqD+Nfy9viFGBfQ5bZyT35YqOiqx7/tXdyfZkJ1sC21NyEsBdfDY6PYmLHF4r5iA==} + dependencies: + babel-runtime: 6.26.0 + dev: true + + /babel-plugin-transform-es2015-duplicate-keys@6.24.1: + resolution: {integrity: sha512-ossocTuPOssfxO2h+Z3/Ea1Vo1wWx31Uqy9vIiJusOP4TbF7tPs9U0sJ9pX9OJPf4lXRGj5+6Gkl/HHKiAP5ug==} + dependencies: + babel-runtime: 6.26.0 + babel-types: 6.26.0 + dev: true + + /babel-plugin-transform-es2015-for-of@6.23.0: + resolution: {integrity: sha512-DLuRwoygCoXx+YfxHLkVx5/NpeSbVwfoTeBykpJK7JhYWlL/O8hgAK/reforUnZDlxasOrVPPJVI/guE3dCwkw==} + dependencies: + babel-runtime: 6.26.0 + dev: true + + /babel-plugin-transform-es2015-function-name@6.24.1: + resolution: {integrity: sha512-iFp5KIcorf11iBqu/y/a7DK3MN5di3pNCzto61FqCNnUX4qeBwcV1SLqe10oXNnCaxBUImX3SckX2/o1nsrTcg==} + dependencies: + babel-helper-function-name: 6.24.1 + babel-runtime: 6.26.0 + babel-types: 6.26.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-transform-es2015-literals@6.22.0: + resolution: {integrity: sha512-tjFl0cwMPpDYyoqYA9li1/7mGFit39XiNX5DKC/uCNjBctMxyL1/PT/l4rSlbvBG1pOKI88STRdUsWXB3/Q9hQ==} + dependencies: + babel-runtime: 6.26.0 + dev: true + + /babel-plugin-transform-es2015-modules-amd@6.24.1: + resolution: {integrity: sha512-LnIIdGWIKdw7zwckqx+eGjcS8/cl8D74A3BpJbGjKTFFNJSMrjN4bIh22HY1AlkUbeLG6X6OZj56BDvWD+OeFA==} + dependencies: + babel-plugin-transform-es2015-modules-commonjs: 6.26.2 + babel-runtime: 6.26.0 + babel-template: 6.26.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-transform-es2015-modules-commonjs@6.26.2: + resolution: {integrity: sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==} + 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 + dev: true + + /babel-plugin-transform-es2015-modules-systemjs@6.24.1: + resolution: {integrity: sha512-ONFIPsq8y4bls5PPsAWYXH/21Hqv64TBxdje0FvU3MhIV6QM2j5YS7KvAzg/nTIVLot2D2fmFQrFWCbgHlFEjg==} + dependencies: + babel-helper-hoist-variables: 6.24.1 + babel-runtime: 6.26.0 + babel-template: 6.26.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-transform-es2015-modules-umd@6.24.1: + resolution: {integrity: sha512-LpVbiT9CLsuAIp3IG0tfbVo81QIhn6pE8xBJ7XSeCtFlMltuar5VuBV6y6Q45tpui9QWcy5i0vLQfCfrnF7Kiw==} + dependencies: + babel-plugin-transform-es2015-modules-amd: 6.24.1 + babel-runtime: 6.26.0 + babel-template: 6.26.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-transform-es2015-object-super@6.24.1: + resolution: {integrity: sha512-8G5hpZMecb53vpD3mjs64NhI1au24TAmokQ4B+TBFBjN9cVoGoOvotdrMMRmHvVZUEvqGUPWL514woru1ChZMA==} + dependencies: + babel-helper-replace-supers: 6.24.1 + babel-runtime: 6.26.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-transform-es2015-parameters@6.24.1: + resolution: {integrity: sha512-8HxlW+BB5HqniD+nLkQ4xSAVq3bR/pcYW9IigY+2y0dI+Y7INFeTbfAQr+63T3E4UDsZGjyb+l9txUnABWxlOQ==} + 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 + dev: true + + /babel-plugin-transform-es2015-shorthand-properties@6.24.1: + resolution: {integrity: sha512-mDdocSfUVm1/7Jw/FIRNw9vPrBQNePy6wZJlR8HAUBLybNp1w/6lr6zZ2pjMShee65t/ybR5pT8ulkLzD1xwiw==} + dependencies: + babel-runtime: 6.26.0 + babel-types: 6.26.0 + dev: true + + /babel-plugin-transform-es2015-spread@6.22.0: + resolution: {integrity: sha512-3Ghhi26r4l3d0Js933E5+IhHwk0A1yiutj9gwvzmFbVV0sPMYk2lekhOufHBswX7NCoSeF4Xrl3sCIuSIa+zOg==} + dependencies: + babel-runtime: 6.26.0 + dev: true + + /babel-plugin-transform-es2015-sticky-regex@6.24.1: + resolution: {integrity: sha512-CYP359ADryTo3pCsH0oxRo/0yn6UsEZLqYohHmvLQdfS9xkf+MbCzE3/Kolw9OYIY4ZMilH25z/5CbQbwDD+lQ==} + dependencies: + babel-helper-regex: 6.26.0 + babel-runtime: 6.26.0 + babel-types: 6.26.0 + dev: true + + /babel-plugin-transform-es2015-template-literals@6.22.0: + resolution: {integrity: sha512-x8b9W0ngnKzDMHimVtTfn5ryimars1ByTqsfBDwAqLibmuuQY6pgBQi5z1ErIsUOWBdw1bW9FSz5RZUojM4apg==} + dependencies: + babel-runtime: 6.26.0 + dev: true + + /babel-plugin-transform-es2015-typeof-symbol@6.23.0: + resolution: {integrity: sha512-fz6J2Sf4gYN6gWgRZaoFXmq93X+Li/8vf+fb0sGDVtdeWvxC9y5/bTD7bvfWMEq6zetGEHpWjtzRGSugt5kNqw==} + dependencies: + babel-runtime: 6.26.0 + dev: true + + /babel-plugin-transform-es2015-unicode-regex@6.24.1: + resolution: {integrity: sha512-v61Dbbihf5XxnYjtBN04B/JBvsScY37R1cZT5r9permN1cp+b70DY3Ib3fIkgn1DI9U3tGgBJZVD8p/mE/4JbQ==} + dependencies: + babel-helper-regex: 6.26.0 + babel-runtime: 6.26.0 + regexpu-core: 2.0.0 + dev: true + + /babel-plugin-transform-react-remove-prop-types@0.4.24: + resolution: {integrity: sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==} + dev: false + + /babel-plugin-transform-regenerator@6.26.0: + resolution: {integrity: sha512-LS+dBkUGlNR15/5WHKe/8Neawx663qttS6AGqoOUhICc9d1KciBvtrQSuc0PI+CxQ2Q/S1aKuJ+u64GtLdcEZg==} + dependencies: + regenerator-transform: 0.10.1 + dev: true + + /babel-plugin-transform-strict-mode@6.24.1: + resolution: {integrity: sha512-j3KtSpjyLSJxNoCDrhwiJad8kw0gJ9REGj8/CqL0HeRyLnvUNYV9zcqluL6QJSXh3nfsLEmSLvwRfGzrgR96Pw==} + dependencies: + babel-runtime: 6.26.0 + babel-types: 6.26.0 + dev: true + + /babel-polyfill@6.26.0: + resolution: {integrity: sha512-F2rZGQnAdaHWQ8YAoeRbukc7HS9QgdgeyJ0rQDd485v9opwuPvjpPFcOOT/WmkKTdgy9ESgSPXDcTNpzrGr6iQ==} + dependencies: + babel-runtime: 6.26.0 + core-js: 2.6.12 + regenerator-runtime: 0.10.5 + dev: true + + /babel-preset-current-node-syntax@1.1.0(@babel/core@7.18.6): + resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} + peerDependencies: + '@babel/core': ^7.0.0 + 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): + resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} + peerDependencies: + '@babel/core': ^7.0.0 + 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) + dev: false + + /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!' + 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 + dev: true + + /babel-preset-jest@26.6.2(@babel/core@7.18.6): + resolution: {integrity: sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ==} + engines: {node: '>= 10.14.2'} + peerDependencies: + '@babel/core': ^7.0.0 + 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): + 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 + 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) + dev: false + + /babel-preset-react-app@10.1.0: + resolution: {integrity: sha512-f9B1xMdnkCIqe+2dHrJsoQFRz7reChaAHE/65SdaykPklQqhme2WaC08oD3is77x9ff98/9EazAKFDZv5rFEQg==} + 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.26.0(@babel/core@7.26.10) + '@babel/runtime': 7.26.10 + babel-plugin-macros: 3.1.0 + babel-plugin-transform-react-remove-prop-types: 0.4.24 + transitivePeerDependencies: + - supports-color + dev: false + + /babel-register@6.26.0: + resolution: {integrity: sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A==} + 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 + dev: true + + /babel-runtime@6.26.0: + resolution: {integrity: sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==} + dependencies: + core-js: 2.6.12 + regenerator-runtime: 0.11.1 + + /babel-template@6.26.0: + resolution: {integrity: sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg==} + 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 + dev: true + + /babel-traverse@6.26.0: + resolution: {integrity: sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA==} + 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 + dev: true + + /babel-types@6.26.0: + resolution: {integrity: sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==} + dependencies: + babel-runtime: 6.26.0 + esutils: 2.0.3 + lodash: 4.17.21 + to-fast-properties: 1.0.3 + dev: true + + /babylon@6.18.0: + resolution: {integrity: sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==} + hasBin: true + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + /base16@1.0.0: + resolution: {integrity: sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ==} + dev: false + + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: false + + /base@0.11.2: + resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} + engines: {node: '>=0.10.0'} + requiresBuild: true + 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: + resolution: {integrity: sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA==} + dev: false + + /batch@0.6.1: + resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} + dev: false + + /bfj@7.1.0: + resolution: {integrity: sha512-I6MMLkn+anzNdCUp9hMRyui1HaNEUCco50lxbvNS4+EyXg8lN3nJ48PjPWtbH8UVS9CuMoaKE9U2V3l29DaRQw==} + engines: {node: '>= 8.0.0'} + dependencies: + bluebird: 3.7.2 + check-types: 11.2.3 + hoopy: 0.1.4 + jsonpath: 1.1.1 + tryer: 1.0.1 + dev: false + + /big.js@5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + + /bignumber.js@9.1.2: + resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} + dev: false + + /binary-extensions@1.13.1: + resolution: {integrity: sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dev: true + optional: true + + /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==} + requiresBuild: true + dependencies: + file-uri-to-path: 1.0.0 + dev: true + optional: true + + /bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + dev: false + + /bn.js@4.12.1: + resolution: {integrity: sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==} + dev: false + + /bn.js@5.2.1: + resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} + dev: false + + /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} + 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 + dev: false + + /bonjour-service@1.3.0: + resolution: {integrity: sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==} + dependencies: + fast-deep-equal: 3.1.3 + multicast-dns: 7.2.5 + dev: false + + /boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: false + + /braces@1.8.5: + resolution: {integrity: sha512-xU7bpz2ytJl1bH9cgIurjpg/n8Gohy9GTw81heDYLJQ4RU60dlyJsa+atVF2pI0yMMvKxI9HkKwjePCj5XI1hw==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + expand-range: 1.8.2 + preserve: 0.2.0 + repeat-element: 1.1.4 + dev: true + optional: true + + /braces@2.3.2: + resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} + engines: {node: '>=0.10.0'} + requiresBuild: true + 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: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.1.1 + + /brorand@1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + dev: false + + /browser-process-hrtime@1.0.0: + resolution: {integrity: sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==} + + /browserify-aes@1.2.0: + resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + 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 + dev: false + + /browserify-cipher@1.0.1: + resolution: {integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==} + dependencies: + browserify-aes: 1.2.0 + browserify-des: 1.0.2 + evp_bytestokey: 1.0.3 + dev: false + + /browserify-des@1.0.2: + resolution: {integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==} + dependencies: + cipher-base: 1.0.6 + des.js: 1.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /browserify-rsa@4.1.1: + resolution: {integrity: sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==} + engines: {node: '>= 0.10'} + dependencies: + bn.js: 5.2.1 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + dev: false + + /browserify-sign@4.2.3: + resolution: {integrity: sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==} + engines: {node: '>= 0.12'} + dependencies: + bn.js: 5.2.1 + 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 + dev: false + + /browserify-zlib@0.2.0: + resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==} + dependencies: + pako: 1.0.11 + dev: false + + /browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001705 + electron-to-chromium: 1.5.119 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.24.4) + + /bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + dependencies: + node-int64: 0.4.0 + + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + /buffer-xor@1.0.3: + resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + dev: false + + /buffer@4.9.2: + resolution: {integrity: sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + isarray: 1.0.0 + dev: false + + /builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + dev: false + + /builtin-status-codes@3.0.0: + resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==} + dev: false + + /bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + dev: false + + /bytewise-core@1.2.3: + resolution: {integrity: sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA==} + dependencies: + typewise-core: 1.2.0 + dev: false + + /bytewise@1.1.0: + resolution: {integrity: sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ==} + dependencies: + bytewise-core: 1.2.3 + typewise: 1.0.3 + dev: false + + /cache-base@1.0.1: + resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + 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: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + /call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + /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'} + dependencies: + callsites: 2.0.0 + dev: false + + /caller-path@2.0.0: + resolution: {integrity: sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==} + engines: {node: '>=4'} + dependencies: + caller-callsite: 2.0.0 + dev: false + + /callsites@2.0.0: + resolution: {integrity: sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==} + engines: {node: '>=4'} + dev: false + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + /camel-case@4.1.2: + resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} + dependencies: + pascal-case: 3.1.2 + tslib: 2.8.1 + + /camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + dev: false + + /camelcase@1.2.1: + resolution: {integrity: sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==} + engines: {node: '>=0.10.0'} + dev: false + + /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==} + dependencies: + browserslist: 4.24.4 + caniuse-lite: 1.0.30001705 + lodash.memoize: 4.1.2 + lodash.uniq: 4.5.0 + dev: false + + /caniuse-lite@1.0.30001705: + resolution: {integrity: sha512-S0uyMMiYvA7CxNgomYBwwwPUnWzFD83f3B1ce5jHUfHTH//QL6hHsreI8RVC5606R4ssqravelYO5TU6t8sEyg==} + + /capture-exit@2.0.0: + resolution: {integrity: sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==} + engines: {node: 6.* || 8.* || >= 10.*} + dependencies: + rsvp: 4.8.5 + + /case-sensitive-paths-webpack-plugin@2.4.0: + resolution: {integrity: sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==} + engines: {node: '>=4'} + dev: false + + /center-align@0.1.3: + resolution: {integrity: sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==} + engines: {node: '>=0.10.0'} + dependencies: + align-text: 0.1.4 + lazy-cache: 1.0.4 + dev: false + + /cfb@1.2.2: + resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==} + engines: {node: '>=0.8'} + dependencies: + adler-32: 1.3.1 + crc-32: 1.2.2 + dev: false + + /chalk@1.1.3: + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} + engines: {node: '>=0.10.0'} + 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: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: false + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + /change-emitter@0.1.6: + resolution: {integrity: sha512-YXzt1cQ4a2jqazhcuSWEOc1K2q8g9H6eWNsyZgi640LDzRWVQ2eDe+Y/kVdftH+vYdPF2rgDb3dLdpxE1jvAxw==} + dev: false + + /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'} + dev: false + + /check-types@11.2.3: + resolution: {integrity: sha512-+67P1GkJRaxQD6PKK0Et9DhwQB+vGg3PM5+aavopCpZT1lj9jeqfvpgTLAWErNj8qApkkmXlu/Ug74kmhagkXg==} + dev: false + + /chokidar@1.7.0: + resolution: {integrity: sha512-mk8fAWcRUOxY7btlLtitj3A45jOwSAxH4tOFOoEGbVsl6cL6pPMWUy7dwZ/canfj3QEdP6FHSnf/l1c6/WkzVg==} + requiresBuild: true + 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 + dev: true + optional: true + + /chokidar@3.5.1: + resolution: {integrity: sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==} + engines: {node: '>= 8.10.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.5.0 + optionalDependencies: + fsevents: 2.3.3 + + /chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.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 + dev: false + + /chrome-trace-event@1.0.4: + resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} + engines: {node: '>=6.0'} + dev: false + + /ci-info@1.6.0: + resolution: {integrity: sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==} + dev: true + + /ci-info@2.0.0: + resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} + + /ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + dev: false + + /cipher-base@1.0.6: + resolution: {integrity: sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==} + engines: {node: '>= 0.10'} + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /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==} + dev: false + + /clamp@1.0.1: + resolution: {integrity: sha512-kgMuFyE78OC6Dyu3Dy7vcx4uy97EIbVxJB/B0eJ3bUNAkwdNcxYzgKltnyADiYwsR7SEqkkUPsEUT//OVS6XMA==} + dev: false + + /class-utils@0.3.6: + resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + arr-union: 3.1.0 + define-property: 0.2.5 + isobject: 3.0.1 + static-extend: 0.1.2 + + /classnames@2.5.1: + resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} + dev: false + + /clean-css@4.2.4: + resolution: {integrity: sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==} + engines: {node: '>= 4.0'} + dependencies: + source-map: 0.6.1 + dev: true + + /clean-css@5.3.3: + resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} + engines: {node: '>= 10.0'} + dependencies: + source-map: 0.6.1 + dev: false + + /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'} + dependencies: + restore-cursor: 3.1.0 + dev: true + + /cli-truncate@2.1.0: + resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} + engines: {node: '>=8'} + dependencies: + slice-ansi: 3.0.0 + string-width: 4.2.3 + dev: true + + /clipboardy@2.3.0: + resolution: {integrity: sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==} + engines: {node: '>=8'} + dependencies: + arch: 2.2.0 + execa: 1.0.0 + is-wsl: 2.2.0 + + /cliui@2.1.0: + resolution: {integrity: sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==} + dependencies: + center-align: 0.1.3 + right-align: 0.1.3 + wordwrap: 0.0.2 + dev: false + + /cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + + /cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: false + + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + /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'} + dependencies: + '@types/q': 1.5.8 + chalk: 2.4.2 + q: 1.5.1 + dev: false + + /codepage@1.15.0: + resolution: {integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==} + engines: {node: '>=0.8'} + dev: false + + /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'} + requiresBuild: true + dependencies: + map-visit: 1.0.0 + object-visit: 1.0.1 + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: false + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: false + + /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==} + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + dev: false + + /color@3.2.1: + resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + dependencies: + color-convert: 1.9.3 + color-string: 1.9.1 + dev: false + + /colord@2.9.3: + resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} + dev: false + + /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'} + dependencies: + delayed-stream: 1.0.0 + + /commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + dev: true + + /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'} + dev: true + + /commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + dev: false + + /commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + dev: false + + /common-tags@1.8.2: + resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} + engines: {node: '>=4.0.0'} + dev: false + + /commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + dev: false + + /component-classes@1.2.6: + resolution: {integrity: sha512-hPFGULxdwugu1QWW3SvVOCUHLzO34+a2J6Wqy0c5ASQkfi9/8nZcBB0ZohaEbXOQlCflMAEMmEWk7u7BVs4koA==} + dependencies: + component-indexof: 0.0.3 + dev: false + + /component-emitter@1.3.1: + resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} + requiresBuild: true + + /component-indexof@0.0.3: + resolution: {integrity: sha512-puDQKvx/64HZXb4hBwIcvQLaLgux8o1CbWl39s41hrIIZDl1lJiD5jc22gj3RBeGK0ovxALDYpIbyjqDUUl0rw==} + dev: false + + /compressible@2.0.18: + resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.53.0 + dev: false + + /compression@1.8.0: + resolution: {integrity: sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==} + engines: {node: '>= 0.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 + dev: false + + /compute-scroll-into-view@1.0.20: + resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==} + dev: false + + /compute-scroll-into-view@3.1.1: + resolution: {integrity: sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==} + dev: false + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + /confusing-browser-globals@1.0.11: + resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} + dev: false + + /connect-history-api-fallback@2.0.0: + resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==} + engines: {node: '>=0.8'} + dev: false + + /connected-react-router@6.5.2(history@4.10.1)(react-redux@7.2.9)(redux@4.2.1): + 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 + dependencies: + history: 4.10.1 + immutable: 3.8.2 + prop-types: 15.8.1 + react-redux: 7.2.9 + redux: 4.2.1 + seamless-immutable: 7.1.4 + dev: false + + /console-browserify@1.2.0: + resolution: {integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==} + dev: false + + /constants-browserify@1.0.0: + resolution: {integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==} + dev: false + + /content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + dev: false + + /contour_plot@0.0.1: + resolution: {integrity: sha512-Nil2HI76Xux6sVGORvhSS8v66m+/h5CwFkBJDO+U5vWaMdNC0yXNCsGDPbzPhvqOEU5koebhdEvD372LI+IyLw==} + dev: false + + /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==} + dev: false + + /cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + dev: false + + /cookie@0.7.1: + resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} + engines: {node: '>= 0.6'} + dev: false + + /copy-descriptor@0.1.1: + resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} + engines: {node: '>=0.10.0'} + requiresBuild: true + + /copy-to-clipboard@3.3.3: + resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} + dependencies: + toggle-selection: 1.0.6 + dev: false + + /core-js-compat@3.41.0: + resolution: {integrity: sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==} + dependencies: + browserslist: 4.24.4 + dev: false + + /core-js-pure@3.41.0: + resolution: {integrity: sha512-71Gzp96T9YPk63aUvE5Q5qP+DryB4ZloUZPSOebGM88VNw8VNfvdA7z6kGA8iGOTEzAomsRidp4jXSmUIJsL+Q==} + requiresBuild: true + dev: false + + /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. + dev: false + + /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. + requiresBuild: true + + /core-js@3.41.0: + resolution: {integrity: sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==} + requiresBuild: true + dev: false + + /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. + requiresBuild: true + + /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. + requiresBuild: true + + /core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + /cosmiconfig@5.2.1: + resolution: {integrity: sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==} + engines: {node: '>=4'} + dependencies: + import-fresh: 2.0.0 + is-directory: 0.3.1 + js-yaml: 3.14.1 + parse-json: 4.0.0 + dev: false + + /cosmiconfig@6.0.0: + resolution: {integrity: sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==} + engines: {node: '>=8'} + 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 + dev: false + + /cosmiconfig@7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + 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): + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + parse-json: 5.2.0 + typescript: 4.9.5 + + /cp-file@7.0.0: + resolution: {integrity: sha512-0Cbj7gyvFVApzpK/uhCtQ/9kE9UnYpxMzaq5nQQC/Dh4iaj5fxp7iEFIullrYwzj8nf0qnsI1Qsx34hAeAebvw==} + engines: {node: '>=8'} + dependencies: + graceful-fs: 4.2.11 + make-dir: 3.1.0 + nested-error-stacks: 2.1.1 + p-event: 4.2.0 + dev: false + + /cpy@8.1.2: + resolution: {integrity: sha512-dmC4mUesv0OYH2kNFEidtf/skUwv4zePmGeepjyyJ0qTo5+8KhA1o99oIAwVVLzQMAeDJml74d6wPPKb6EZUTg==} + engines: {node: '>=8'} + 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 + dev: false + + /crc-32@1.2.2: + resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} + engines: {node: '>=0.8'} + hasBin: true + dev: false + + /create-ecdh@4.0.4: + resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} + dependencies: + bn.js: 4.12.1 + elliptic: 6.6.1 + dev: false + + /create-hash@1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + dependencies: + cipher-base: 1.0.6 + inherits: 2.0.4 + md5.js: 1.3.5 + ripemd160: 2.0.2 + sha.js: 2.4.11 + dev: false + + /create-hmac@1.1.7: + resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + 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 + dev: false + + /create-react-class@15.7.0: + resolution: {integrity: sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng==} + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + dev: false + + /create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + dev: true + + /cross-fetch@3.2.0: + resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: false + + /cross-spawn@5.1.0: + resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + dependencies: + lru-cache: 4.1.5 + shebang-command: 1.2.0 + which: 1.3.1 + dev: true + + /cross-spawn@6.0.6: + resolution: {integrity: sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==} + engines: {node: '>=4.8'} + 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: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + /crypto-browserify@3.12.1: + resolution: {integrity: sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==} + engines: {node: '>= 0.10'} + 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 + dev: false + + /crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + dev: false + + /crypto-random-string@2.0.0: + resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} + engines: {node: '>=8'} + dev: false + + /crypto-random-string@5.0.0: + resolution: {integrity: sha512-KWjTXWwxFd6a94m5CdRGW/t82Tr8DoBc9dNnPCAbFI1EBweN6v1tv8y4Y1m7ndkp/nkIBRxUxAzpaBnR2k3bcQ==} + engines: {node: '>=14.16'} + dependencies: + type-fest: 2.19.0 + dev: false + + /css-animation@1.6.1: + resolution: {integrity: sha512-/48+/BaEaHRY6kNQ2OIPzKf9A6g8WjZYjhiNDNuIVbsm5tXCGIAsHDjB4Xu1C4vXJtUWZo26O68OQkDpNBaPog==} + dependencies: + babel-runtime: 6.26.0 + component-classes: 1.2.6 + dev: false + + /css-blank-pseudo@0.1.4: + resolution: {integrity: sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + postcss: 7.0.32 + dev: false + + /css-blank-pseudo@3.0.3(postcss@8.5.3): + resolution: {integrity: sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==} + engines: {node: ^12 || ^14 || >=16} + hasBin: true + peerDependencies: + postcss: ^8.4 + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + dev: false + + /css-box-model@1.2.1: + resolution: {integrity: sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==} + dependencies: + tiny-invariant: 1.3.3 + dev: false + + /css-declaration-sorter@6.4.1(postcss@8.5.3): + resolution: {integrity: sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==} + engines: {node: ^10 || ^12 || >=14} + peerDependencies: + postcss: ^8.0.9 + dependencies: + postcss: 8.5.3 + dev: false + + /css-has-pseudo@0.10.0: + resolution: {integrity: sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + postcss: 7.0.32 + postcss-selector-parser: 5.0.0 + dev: false + + /css-has-pseudo@3.0.4(postcss@8.5.3): + resolution: {integrity: sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==} + engines: {node: ^12 || ^14 || >=16} + hasBin: true + peerDependencies: + postcss: ^8.4 + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + dev: false + + /css-in-js-utils@3.1.0: + resolution: {integrity: sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==} + dependencies: + hyphenate-style-name: 1.1.0 + dev: false + + /css-loader@6.11.0(webpack@5.98.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 + 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 + webpack: 5.98.0 + dev: false + + /css-minimizer-webpack-plugin@3.4.1(webpack@5.98.0): + 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 + dependencies: + cssnano: 5.1.15(postcss@8.5.3) + jest-worker: 27.5.1 + postcss: 8.5.3 + schema-utils: 4.3.0 + serialize-javascript: 6.0.2 + source-map: 0.6.1 + webpack: 5.98.0 + dev: false + + /css-prefers-color-scheme@3.1.1: + resolution: {integrity: sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + postcss: 7.0.32 + dev: false + + /css-prefers-color-scheme@6.0.3(postcss@8.5.3): + resolution: {integrity: sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==} + engines: {node: ^12 || ^14 || >=16} + hasBin: true + peerDependencies: + postcss: ^8.4 + dependencies: + postcss: 8.5.3 + dev: false + + /css-select-base-adapter@0.1.1: + resolution: {integrity: sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==} + dev: false + + /css-select@2.1.0: + resolution: {integrity: sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==} + dependencies: + boolbase: 1.0.0 + css-what: 3.4.2 + domutils: 1.7.0 + nth-check: 1.0.2 + dev: false + + /css-select@4.3.0: + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + 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: + resolution: {integrity: sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==} + engines: {node: '>=8.0.0'} + dependencies: + mdn-data: 2.0.4 + source-map: 0.6.1 + dev: false + + /css-tree@1.1.3: + resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} + engines: {node: '>=8.0.0'} + dependencies: + mdn-data: 2.0.14 + source-map: 0.6.1 + dev: false + + /css-what@3.4.2: + resolution: {integrity: sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==} + engines: {node: '>= 6'} + dev: false + + /css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + + /csscolorparser@1.0.3: + resolution: {integrity: sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==} + dev: false + + /cssdb@4.4.0: + resolution: {integrity: sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ==} + dev: false + + /cssdb@7.11.2: + resolution: {integrity: sha512-lhQ32TFkc1X4eTefGfYPvgovRSzIMofHkigfH8nWtyRL4XJLsRhJFreRvEgKzept7x1rjBuy3J/MurXLaFxW/A==} + dev: false + + /cssesc@2.0.0: + resolution: {integrity: sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /cssnano-preset-default@5.2.14(postcss@8.5.3): + resolution: {integrity: sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + 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) + dev: false + + /cssnano-utils@3.1.0(postcss@8.5.3): + resolution: {integrity: sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.5.3 + dev: false + + /cssnano@5.1.15(postcss@8.5.3): + resolution: {integrity: sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + cssnano-preset-default: 5.2.14(postcss@8.5.3) + lilconfig: 2.1.0 + postcss: 8.5.3 + yaml: 1.10.2 + dev: false + + /csso@4.2.0: + resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==} + engines: {node: '>=8.0.0'} + dependencies: + css-tree: 1.1.3 + dev: false + + /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'} + dependencies: + cssom: 0.3.8 + + /csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + /d3-array@1.2.4: + resolution: {integrity: sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==} + dev: false + + /d3-array@2.12.1: + resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==} + dependencies: + internmap: 1.0.1 + dev: false + + /d3-collection@1.0.7: + resolution: {integrity: sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==} + dev: false + + /d3-color@1.4.1: + resolution: {integrity: sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==} + dev: false + + /d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + dev: false + + /d3-dispatch@2.0.0: + resolution: {integrity: sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA==} + dev: false + + /d3-dsv@1.2.0: + resolution: {integrity: sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==} + hasBin: true + dependencies: + commander: 2.20.3 + iconv-lite: 0.4.24 + rw: 1.3.3 + dev: false + + /d3-ease@1.0.7: + resolution: {integrity: sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==} + dev: false + + /d3-force@2.1.1: + resolution: {integrity: sha512-nAuHEzBqMvpFVMf9OX75d00OxvOXdxY+xECIXjW6Gv8BRrXu6gAWbv/9XKrvfJ5i5DCokDW7RYE50LRoK092ew==} + dependencies: + d3-dispatch: 2.0.0 + d3-quadtree: 2.0.0 + d3-timer: 2.0.0 + dev: false + + /d3-format@1.4.5: + resolution: {integrity: sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==} + dev: false + + /d3-hexbin@0.2.2: + resolution: {integrity: sha512-KS3fUT2ReD4RlGCjvCEm1RgMtp2NFZumdMu4DBzQK8AZv3fXRM6Xm8I4fSU07UXvH4xxg03NwWKWdvxfS/yc4w==} + dev: false + + /d3-hierarchy@2.0.0: + resolution: {integrity: sha512-SwIdqM3HxQX2214EG9GTjgmCc/mbSx4mQBn+DuEETubhOw6/U3fmnji4uCVrmzOydMHSO1nZle5gh6HB/wdOzw==} + dev: false + + /d3-interpolate@1.4.0: + resolution: {integrity: sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==} + dependencies: + d3-color: 1.4.1 + dev: false + + /d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + dependencies: + d3-color: 3.1.0 + dev: false + + /d3-quadtree@2.0.0: + resolution: {integrity: sha512-b0Ed2t1UUalJpc3qXzKi+cPGxeXRr4KU9YSlocN74aTzp6R/Ud43t79yLLqxHRWZfsvWXmbDWPpoENK1K539xw==} + dev: false + + /d3-regression@1.3.10: + resolution: {integrity: sha512-PF8GWEL70cHHWpx2jUQXc68r1pyPHIA+St16muk/XRokETzlegj5LriNKg7o4LR0TySug4nHYPJNNRz/W+/Niw==} + dev: false + + /d3-scale@2.2.2: + resolution: {integrity: sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==} + 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 + dev: false + + /d3-time-format@2.3.0: + resolution: {integrity: sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==} + dependencies: + d3-time: 1.1.0 + dev: false + + /d3-time@1.1.0: + resolution: {integrity: sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==} + dev: false + + /d3-timer@1.0.10: + resolution: {integrity: sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==} + dev: false + + /d3-timer@2.0.0: + resolution: {integrity: sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA==} + dev: false + + /d@1.0.2: + resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} + engines: {node: '>=0.12'} + dependencies: + es5-ext: 0.10.64 + type: 2.7.3 + + /dagre-compound@0.0.11(dagre@0.8.5): + resolution: {integrity: sha512-UrSgRP9LtOZCYb9e5doolZXpc7xayyszgyOs7uakTK4n4KsLegLVTRRtq01GpQd/iZjYw5fWMapx9ed+c80MAQ==} + engines: {node: '>=6.0.0'} + peerDependencies: + dagre: ^0.8.5 + dependencies: + dagre: 0.8.5 + dev: false + + /dagre@0.8.5: + resolution: {integrity: sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==} + dependencies: + graphlib: 2.1.8 + lodash: 4.17.21 + dev: false + + /damerau-levenshtein@1.0.8: + resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + dev: false + + /data-urls@2.0.0: + resolution: {integrity: sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==} + engines: {node: '>=10'} + dependencies: + abab: 2.0.6 + whatwg-mimetype: 2.3.0 + whatwg-url: 8.7.0 + + /data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + /data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + /data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + /date-fns@2.30.0: + resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} + engines: {node: '>=0.11'} + dependencies: + '@babel/runtime': 7.26.10 + dev: false + + /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 + dependencies: + ms: 2.0.0 + + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: false + + /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 + dependencies: + ms: 2.1.3 + + /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'} + dev: false + + /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'} + 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 + dev: false + + /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'} + dev: false + + /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'} + dependencies: + execa: 5.1.1 + dev: false + + /define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + /define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + dev: false + + /define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + /define-property@0.2.5: + resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + is-descriptor: 0.1.7 + + /define-property@1.0.0: + resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + is-descriptor: 1.0.3 + + /define-property@2.0.2: + resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + is-descriptor: 1.0.3 + isobject: 3.0.1 + + /defined@1.0.1: + resolution: {integrity: sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==} + dev: false + + /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'} + dev: false + + /depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dev: false + + /dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + dev: false + + /des.js@1.1.0: + resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + dev: false + + /destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dev: false + + /detect-browser@4.8.0: + resolution: {integrity: sha512-f4h2dFgzHUIpjpBLjhnDIteXv8VQiUm8XzAuzQtYUqECX/eKh67ykuiVoyb7Db7a0PUSmJa3OGXStG0CbQFUVw==} + dev: false + + /detect-browser@5.3.0: + resolution: {integrity: sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==} + dev: false + + /detect-indent@4.0.0: + resolution: {integrity: sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A==} + engines: {node: '>=0.10.0'} + dependencies: + repeating: 2.0.1 + dev: true + + /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==} + dev: false + + /detect-port-alt@1.1.6: + resolution: {integrity: sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==} + engines: {node: '>= 4.2.1'} + hasBin: true + dependencies: + address: 1.2.2 + debug: 2.6.9 + transitivePeerDependencies: + - supports-color + dev: false + + /didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + dev: false + + /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} + dev: false + + /diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + dev: true + + /diff@5.2.0: + resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} + engines: {node: '>=0.3.1'} + dev: false + + /diffie-hellman@5.0.3: + resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} + dependencies: + bn.js: 4.12.1 + miller-rabin: 4.0.1 + randombytes: 2.1.0 + dev: false + + /dir-glob@2.2.2: + resolution: {integrity: sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==} + engines: {node: '>=4'} + dependencies: + path-type: 3.0.0 + dev: false + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: false + + /dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dev: false + + /dns-packet@5.6.1: + resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} + engines: {node: '>=6'} + dependencies: + '@leichtgewicht/ip-codec': 2.0.5 + dev: false + + /doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + dependencies: + esutils: 2.0.3 + dev: false + + /dom-align@1.12.4: + resolution: {integrity: sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==} + dev: false + + /dom-converter@0.2.0: + resolution: {integrity: sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==} + dependencies: + utila: 0.4.0 + + /dom-scroll-into-view@1.2.1: + resolution: {integrity: sha512-LwNVg3GJOprWDO+QhLL1Z9MMgWe/KAFLxVWKzjRTxNSPn8/LLDIfmuG71YHznXCqaqTjvHJDYO1MEAgX6XCNbQ==} + dev: false + + /dom-serializer@0.2.2: + resolution: {integrity: sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==} + dependencies: + domelementtype: 2.3.0 + entities: 2.2.0 + dev: false + + /dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + + /dom-walk@0.1.2: + resolution: {integrity: sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==} + dev: false + + /domain-browser@1.2.0: + resolution: {integrity: sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==} + engines: {node: '>=0.4', npm: '>=1.2'} + dev: false + + /domelementtype@1.3.1: + resolution: {integrity: sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==} + dev: false + + /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 + dependencies: + webidl-conversions: 5.0.0 + + /domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + dependencies: + domelementtype: 2.3.0 + + /domutils@1.7.0: + resolution: {integrity: sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==} + dependencies: + dom-serializer: 0.2.2 + domelementtype: 1.3.1 + dev: false + + /domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + + /dot-case@3.0.4: + resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + + /dotenv-expand@5.1.0: + resolution: {integrity: sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==} + dev: false + + /dotenv@10.0.0: + resolution: {integrity: sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==} + engines: {node: '>=10'} + dev: false + + /dotenv@16.4.7: + resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} + engines: {node: '>=12'} + dev: true + + /dotignore@0.1.2: + resolution: {integrity: sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw==} + hasBin: true + dependencies: + minimatch: 3.1.2 + dev: false + + /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 + dependencies: + fbjs: 0.8.18 + immutable: 3.7.6 + object-assign: 4.1.1 + dev: false + + /drange@1.1.1: + resolution: {integrity: sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==} + engines: {node: '>=4'} + dev: false + + /dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + /duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + dev: false + + /dva-core@2.0.4(redux@4.2.1): + resolution: {integrity: sha512-Zh39llFyItu9HKXKfCZVf9UFtDTcypdAjGBew1S+wK8BGVzFpm1GPTdd6uIMeg7O6STtCvt2Qv+RwUut1GFynA==} + peerDependencies: + redux: 4.x + dependencies: + '@babel/runtime': 7.26.10 + 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 + dev: false + + /dva-immer@0.5.2(dva@2.6.0-beta.23): + resolution: {integrity: sha512-xg23ktGsrdzgiU0ACl8vFm2+E2GBWbtXndXRKM9wtHDR+yMH27NfttVuAZQWvv4aaj6f5/bC+TdsZ9t7n6cAhQ==} + peerDependencies: + dva: ^2.5.0-0 + dependencies: + '@babel/runtime': 7.26.10 + dva: 2.6.0-beta.23 + immer: 7.0.15 + dev: false + + /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 + dependencies: + '@babel/runtime': 7.26.10 + dev: false + + /dva@2.6.0-beta.23: + resolution: {integrity: sha512-noeOz3Erxpc6YLEsyyS//zGszeRYWKEvZoeCZ0LaCvWrV7Cxah9Xt/I9V1SS9eYDySaSgTUOoU+dLweQpCScAA==} + peerDependencies: + react: ^16.8.4 + react-dom: ^16.8.4 + dependencies: + '@babel/runtime': 7.26.10 + '@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)(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-redux: 7.2.9 + react-router-dom: 5.3.4 + redux: 4.2.1 + transitivePeerDependencies: + - react-native + - react-router + dev: false + + /earcut@2.2.4: + resolution: {integrity: sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==} + dev: false + + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: false + + /ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + dev: false + + /ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + jake: 10.9.2 + dev: false + + /electron-to-chromium@1.5.119: + resolution: {integrity: sha512-Ku4NMzUjz3e3Vweh7PhApPrZSS4fyiCIbcIrG9eKrriYVLmbMepETR/v6SU7xPm98QTqMSYiCwfO89QNjXLkbQ==} + + /element-resize-detector@1.2.4: + resolution: {integrity: sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg==} + dependencies: + batch-processor: 1.0.0 + dev: false + + /elliptic@6.6.1: + resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} + dependencies: + bn.js: 4.12.1 + 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 + dev: false + + /emittery@0.10.2: + resolution: {integrity: sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==} + engines: {node: '>=12'} + dev: false + + /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'} + dev: false + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: false + + /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'} + dev: false + + /encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + dev: false + + /encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + dependencies: + iconv-lite: 0.6.3 + dev: false + + /end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + + /enhanced-resolve@5.18.1: + resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + dev: false + + /enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + dev: true + + /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==} + dependencies: + is-arrayish: 0.2.1 + + /error-stack-parser@2.1.4: + resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} + dependencies: + stackframe: 1.3.4 + dev: false + + /es-abstract@1.23.9: + resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} + engines: {node: '>= 0.4'} + 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: + 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'} + 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 + dev: false + + /es-module-lexer@0.7.1: + resolution: {integrity: sha512-MgtWFl5No+4S3TmhDmCz2ObFGm6lEpTnzbQi+Dd+pw4mlTIZTmM2iAs5gRlmx5zS9luzobCSBSI90JM/1/JgOw==} + dev: false + + /es-module-lexer@1.6.0: + resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} + dev: false + + /es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + + /es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} + engines: {node: '>= 0.4'} + dependencies: + hasown: 2.0.2 + dev: false + + /es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + /es5-ext@0.10.64: + resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==} + engines: {node: '>=0.10'} + requiresBuild: true + 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: + resolution: {integrity: sha512-2MPI0t/VV4j/oz1qbMekb4gCW81dewTpM2XJHKnPpZiPGu+1rVWmhTnwcq1vt8AFwWrkNF4RE7OZ9ibnKFYKwg==} + dev: false + + /es6-iterator@2.0.3: + resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-symbol: 3.1.4 + + /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'} + dependencies: + d: 1.0.2 + ext: 1.7.0 + + /es6-weak-map@2.0.3: + resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==} + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-iterator: 2.0.3 + es6-symbol: 3.1.4 + + /esbuild@0.12.15: + resolution: {integrity: sha512-72V4JNd2+48eOVCXx49xoSWHgC3/cCy96e7mbXKY+WOWghN00cCmlGnwVLRhRHorvv0dgCyuMYBZlM2xDM5OQw==} + hasBin: true + requiresBuild: 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==} + dev: false + + /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 + dependencies: + esprima: 4.0.1 + estraverse: 4.3.0 + esutils: 2.0.3 + optionator: 0.8.3 + optionalDependencies: + source-map: 0.6.1 + dev: false + + /escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + 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(eslint@9.22.0)(jest@27.5.1)(typescript@4.9.5): + resolution: {integrity: sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==} + engines: {node: '>=14.0.0'} + peerDependencies: + eslint: ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@babel/core': 7.26.10 + '@babel/eslint-parser': 7.26.10(@babel/core@7.26.10)(eslint@9.22.0) + '@rushstack/eslint-patch': 1.11.0 + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@9.22.0)(typescript@4.9.5) + '@typescript-eslint/parser': 5.62.0(eslint@9.22.0)(typescript@4.9.5) + babel-preset-react-app: 10.1.0 + confusing-browser-globals: 1.0.11 + eslint: 9.22.0 + eslint-plugin-flowtype: 8.0.3(eslint@9.22.0) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0)(eslint@9.22.0) + eslint-plugin-jest: 25.7.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint@9.22.0)(jest@27.5.1)(typescript@4.9.5) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.22.0) + eslint-plugin-react: 7.37.4(eslint@9.22.0) + eslint-plugin-react-hooks: 4.6.2(eslint@9.22.0) + eslint-plugin-testing-library: 5.11.1(eslint@9.22.0)(typescript@4.9.5) + 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 + dev: false + + /eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + dependencies: + debug: 3.2.7 + is-core-module: 2.16.1 + resolve: 1.22.10 + transitivePeerDependencies: + - supports-color + dev: false + + /eslint-module-utils@2.12.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint@9.22.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 + dependencies: + '@typescript-eslint/parser': 5.62.0(eslint@9.22.0)(typescript@4.9.5) + debug: 3.2.7 + eslint: 9.22.0 + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + dev: false + + /eslint-plugin-flowtype@8.0.3(eslint@9.22.0): + 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 + dependencies: + eslint: 9.22.0 + lodash: 4.17.21 + string-natural-compare: 3.0.1 + dev: false + + /eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0)(eslint@9.22.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 + dependencies: + '@rtsao/scc': 1.1.0 + '@typescript-eslint/parser': 5.62.0(eslint@9.22.0)(typescript@4.9.5) + 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.22.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint@9.22.0) + 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 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: false + + /eslint-plugin-jest@25.7.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint@9.22.0)(jest@27.5.1)(typescript@4.9.5): + 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 + dependencies: + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@9.22.0)(typescript@4.9.5) + '@typescript-eslint/experimental-utils': 5.62.0(eslint@9.22.0)(typescript@4.9.5) + eslint: 9.22.0 + jest: 27.5.1 + transitivePeerDependencies: + - supports-color + - typescript + dev: false + + /eslint-plugin-jsx-a11y@6.10.2(eslint@9.22.0): + resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==} + engines: {node: '>=4.0'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 + 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.22.0 + 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 + dev: false + + /eslint-plugin-react-hooks@4.6.2(eslint@9.22.0): + 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 + dependencies: + eslint: 9.22.0 + + /eslint-plugin-react@7.37.4(eslint@9.22.0): + resolution: {integrity: sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.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.22.0 + 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 + dev: false + + /eslint-plugin-testing-library@5.11.1(eslint@9.22.0)(typescript@4.9.5): + 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 + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@9.22.0)(typescript@4.9.5) + eslint: 9.22.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: false + + /eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: false + + /eslint-scope@8.3.0: + resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + /eslint-visitor-keys@2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + dev: false + + /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(eslint@9.22.0)(webpack@5.98.0): + resolution: {integrity: sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==} + engines: {node: '>= 12.13.0'} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + webpack: ^5.0.0 + dependencies: + '@types/eslint': 8.56.12 + eslint: 9.22.0 + jest-worker: 28.1.3 + micromatch: 4.0.8 + normalize-path: 3.0.0 + schema-utils: 4.3.0 + webpack: 5.98.0 + dev: false + + /eslint@9.22.0: + resolution: {integrity: sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + dependencies: + '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.19.2 + '@eslint/config-helpers': 0.1.0 + '@eslint/core': 0.12.0 + '@eslint/eslintrc': 3.3.0 + '@eslint/js': 9.22.0 + '@eslint/plugin-kit': 0.2.7 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.2 + '@types/estree': 1.0.6 + '@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 + transitivePeerDependencies: + - supports-color + + /esniff@2.0.1: + resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==} + engines: {node: '>=0.10'} + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + event-emitter: 0.3.5 + type: 2.7.3 + + /espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.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: + resolution: {integrity: sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: false + + /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'} + dependencies: + estraverse: 5.3.0 + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + + /estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + dev: false + + /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==} + dev: false + + /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'} + dev: false + + /event-emitter@0.3.5: + resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + + /eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + dev: false + + /eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + dev: false + + /events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + dev: false + + /evp_bytestokey@1.0.3: + resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + dependencies: + md5.js: 1.3.5 + safe-buffer: 5.2.1 + dev: false + + /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'} + 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 + dev: true + + /execa@1.0.0: + resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} + engines: {node: '>=6'} + 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: + resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} + engines: {node: '>=10'} + 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: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + 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 + dev: false + + /exenv@1.2.2: + resolution: {integrity: sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==} + dev: false + + /exit-on-epipe@1.0.1: + resolution: {integrity: sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==} + engines: {node: '>=0.8'} + dev: false + + /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'} + requiresBuild: true + dependencies: + is-posix-bracket: 0.1.1 + dev: true + optional: true + + /expand-brackets@2.1.4: + resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} + engines: {node: '>=0.10.0'} + requiresBuild: true + 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: + resolution: {integrity: sha512-AFASGfIlnIbkKPQwX1yHaDjFvh/1gyKJODme52V6IORh69uEYgZp0o9C+qsIGNVEiuuhQU0CSSl++Rlegg1qvA==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + fill-range: 2.2.4 + dev: true + optional: true + + /expect@26.6.2: + resolution: {integrity: sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA==} + engines: {node: '>= 10.14.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: + resolution: {integrity: sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + '@jest/types': 27.5.1 + jest-get-type: 27.5.1 + jest-matcher-utils: 27.5.1 + jest-message-util: 27.5.1 + dev: false + + /express@4.21.2: + resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} + engines: {node: '>= 0.10.0'} + 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 + dev: false + + /ext@1.7.0: + resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} + dependencies: + type: 2.7.3 + + /extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + is-extendable: 0.1.1 + + /extend-shallow@3.0.2: + resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + assign-symbols: 1.0.0 + is-extendable: 1.0.1 + + /extglob@0.3.2: + resolution: {integrity: sha512-1FOj1LOwn42TMrruOHGt18HemVnbwAmAak7krWk+wa93KXxGbK+2jpezm+ytJYDaBX0/SPLZFHKM7m+tKobWGg==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + is-extglob: 1.0.0 + dev: true + optional: true + + /extglob@2.0.4: + resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} + engines: {node: '>=0.10.0'} + requiresBuild: true + 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: + resolution: {integrity: sha512-fcKIanU/v+tcdgG0+xMbS0C2VZ0/CF3qqxSjHiWfWICh0yFBezPr3SsOhgdzwE5E82plG6p1orEsfSqgldpxVg==} + dependencies: + as-number: 1.0.0 + gl-vec2: 1.3.0 + polyline-miter-util: 1.0.1 + dev: false + + /fast-deep-equal@3.1.1: + resolution: {integrity: sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==} + dev: false + + /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'} + 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 + dev: false + + /fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + dev: false + + /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==} + dev: false + + /fast-uri@3.0.6: + resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} + dev: false + + /fastest-stable-stringify@2.0.2: + resolution: {integrity: sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==} + dev: false + + /fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + dependencies: + reusify: 1.1.0 + dev: false + + /faye-websocket@0.11.4: + resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} + engines: {node: '>=0.8.0'} + dependencies: + websocket-driver: 0.7.4 + dev: false + + /fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + dependencies: + bser: 2.1.1 + + /fbemitter@3.0.0: + resolution: {integrity: sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==} + dependencies: + fbjs: 3.0.5 + transitivePeerDependencies: + - encoding + dev: false + + /fbjs-css-vars@1.0.2: + resolution: {integrity: sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==} + dev: false + + /fbjs@0.8.18: + resolution: {integrity: sha512-EQaWFK+fEPSoibjNy8IxUtaFOMXcWsY0JaVrQoZR9zC8N2Ygf9iDITPWjUTVIax95b6I742JFLqASHfsag/vKA==} + 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 + dev: false + + /fbjs@3.0.5: + resolution: {integrity: sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==} + dependencies: + cross-fetch: 3.2.0 + 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 + dev: false + + /fecha@4.2.3: + resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} + dev: false + + /fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + dev: false + + /file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + dependencies: + flat-cache: 4.0.1 + + /file-loader@6.2.0(webpack@5.98.0): + resolution: {integrity: sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==} + engines: {node: '>= 10.13.0'} + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + dependencies: + loader-utils: 2.0.4 + schema-utils: 3.3.0 + webpack: 5.98.0 + dev: false + + /file-saver@2.0.5: + resolution: {integrity: sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==} + dev: false + + /file-uri-to-path@1.0.0: + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + requiresBuild: true + dev: true + optional: true + + /filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + dependencies: + minimatch: 5.1.6 + dev: false + + /filename-regex@2.0.1: + resolution: {integrity: sha512-BTCqyBaWBTsauvnHiE8i562+EdJj+oUpkqWp2R1iCoR8f6oo8STRu3of7WJJ0TqWtxN50a5YFpzYK4Jj9esYfQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dev: true + optional: true + + /filesize@10.1.6: + resolution: {integrity: sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==} + engines: {node: '>= 10.4.0'} + dev: false + + /filesize@8.0.7: + resolution: {integrity: sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==} + engines: {node: '>= 0.4.0'} + dev: false + + /fill-range@2.2.4: + resolution: {integrity: sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + is-number: 2.1.0 + isobject: 2.1.0 + randomatic: 3.1.1 + repeat-element: 1.1.4 + repeat-string: 1.6.1 + dev: true + optional: true + + /fill-range@4.0.0: + resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + 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: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + + /filter-obj@1.1.0: + resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} + engines: {node: '>=0.10.0'} + dev: false + + /filter-obj@5.1.0: + resolution: {integrity: sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==} + engines: {node: '>=14.16'} + dev: false + + /finalhandler@1.3.1: + resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} + engines: {node: '>= 0.8'} + 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 + dev: false + + /find-cache-dir@3.3.2: + resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} + engines: {node: '>=8'} + dependencies: + commondir: 1.0.1 + make-dir: 3.1.0 + pkg-dir: 4.2.0 + dev: false + + /find-root@1.1.0: + resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} + dev: false + + /find-up@3.0.0: + resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} + engines: {node: '>=6'} + dependencies: + locate-path: 3.0.0 + dev: false + + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + /flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + /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. + dev: false + + /flux@4.0.4: + resolution: {integrity: sha512-NCj3XlayA2UsapRpM7va6wU1+9rE5FIL7qoMcmxWHRzbp0yujihMBm9BBHZ1MDIk5h5o2Bl6eGiCe8rYELAmYw==} + peerDependencies: + react: ^15.0.2 || ^16.0.0 || ^17.0.0 + dependencies: + fbemitter: 3.0.0 + fbjs: 3.0.5 + transitivePeerDependencies: + - encoding + dev: false + + /fmin@0.0.2: + resolution: {integrity: sha512-sSi6DzInhl9d8yqssDfGZejChO8d2bAGIpysPsvYsxFe898z89XhCZg6CPNV3nhUhFefeC/AXZK2bAJxlBjN6A==} + dependencies: + contour_plot: 0.0.1 + json2module: 0.0.3 + rollup: 0.25.8 + tape: 4.17.0 + uglify-js: 2.8.29 + dev: false + + /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'} + dependencies: + is-callable: 1.2.7 + + /for-in@1.0.2: + resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + + /for-own@0.1.5: + resolution: {integrity: sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + for-in: 1.0.2 + dev: true + optional: true + + /foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + dev: false + + /fork-ts-checker-webpack-plugin@6.5.3(eslint@9.22.0)(typescript@4.9.5)(webpack@5.98.0): + 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 + 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 + eslint: 9.22.0 + 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.98.0 + dev: false + + /form-data@3.0.3: + resolution: {integrity: sha512-q5YBMeWy6E2Un0nMGWMgI65MAKtaylxfNJGJxpGh45YDciZB4epbWpaAfImil6CPAPTYB4sh0URQNDRIZG5F2w==} + engines: {node: '>= 6'} + 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: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + dev: false + + /frac@1.1.2: + resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==} + engines: {node: '>=0.8'} + dev: false + + /fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + dev: false + + /fragment-cache@0.2.1: + resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + map-cache: 0.2.2 + + /fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + dev: false + + /fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + /fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: false + + /fs-monkey@1.0.6: + resolution: {integrity: sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==} + dev: false + + /fs-readdir-recursive@1.1.0: + resolution: {integrity: sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==} + dev: true + + /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 + requiresBuild: true + dependencies: + bindings: 1.5.0 + nan: 2.22.2 + dev: true + optional: true + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + optional: true + + /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'} + 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: + 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==} + dev: false + + /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'} + 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: + 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'} + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + /get-stream@3.0.0: + resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} + engines: {node: '>=4'} + dev: true + + /get-stream@4.1.0: + resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} + engines: {node: '>=6'} + dependencies: + pump: 3.0.2 + + /get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + dependencies: + pump: 3.0.2 + + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: false + + /get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + + /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==} + dev: false + + /gl-vec2@1.3.0: + resolution: {integrity: sha512-YiqaAuNsheWmUV0Sa8k94kBB0D6RWjwZztyO+trEYS8KzJ6OQB/4686gdrf59wld4hHFIvaxynO3nRxpk1Ij/A==} + dev: false + + /glob-base@0.3.0: + resolution: {integrity: sha512-ab1S1g1EbO7YzauaJLkgLp7DZVAqj9M/dvKlTt8DkXA2tiOIcSMrlVI2J1RZyB5iJVccEscjGn+kpOG9788MHA==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + glob-parent: 2.0.0 + is-glob: 2.0.1 + dev: true + optional: true + + /glob-parent@2.0.0: + resolution: {integrity: sha512-JDYOvfxio/t42HKdxkAYaCiBN7oYiuxykOxKxdaUW5Qn0zaYN3gRQWolrwdnf0shM9/EP0ebuuTmyoXNr1cC5w==} + requiresBuild: true + dependencies: + is-glob: 2.0.1 + dev: true + optional: true + + /glob-parent@3.1.0: + resolution: {integrity: sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==} + dependencies: + is-glob: 3.1.0 + path-dirname: 1.0.2 + dev: false + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + + /glob-to-regexp@0.3.0: + resolution: {integrity: sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==} + dev: false + + /glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + dev: false + + /glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + 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 + dev: false + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + 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: + resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} + engines: {node: '>=6'} + dependencies: + global-prefix: 3.0.0 + dev: false + + /global-prefix@3.0.0: + resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} + engines: {node: '>=6'} + dependencies: + ini: 1.3.8 + kind-of: 6.0.3 + which: 1.3.1 + dev: false + + /global@4.4.0: + resolution: {integrity: sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==} + dependencies: + min-document: 2.19.0 + process: 0.11.10 + dev: false + + /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'} + dev: true + + /globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + dev: false + + /globby@9.2.0: + resolution: {integrity: sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==} + engines: {node: '>=6'} + 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 + dev: false + + /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==} + dev: false + + /graphlib@2.1.8: + resolution: {integrity: sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==} + dependencies: + lodash: 4.17.21 + dev: false + + /grid-index@1.1.0: + resolution: {integrity: sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==} + dev: false + + /growly@1.3.0: + resolution: {integrity: sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==} + requiresBuild: true + optional: true + + /gzip-size@6.0.0: + resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} + engines: {node: '>=10'} + dependencies: + duplexer: 0.1.2 + dev: false + + /hammerjs@2.0.8: + resolution: {integrity: sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==} + engines: {node: '>=0.8.0'} + dev: false + + /handle-thing@2.0.1: + resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} + dev: false + + /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'} + dependencies: + ansi-regex: 2.1.1 + + /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'} + dev: true + + /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'} + dependencies: + is-glob: 3.1.0 + dev: false + + /has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + dependencies: + es-define-property: 1.0.1 + + /has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + dependencies: + dunder-proto: 1.0.1 + + /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'} + dependencies: + has-symbols: 1.1.0 + + /has-value@0.3.1: + resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + get-value: 2.0.6 + has-values: 0.1.4 + isobject: 2.1.0 + + /has-value@1.0.0: + resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + get-value: 2.0.6 + has-values: 1.0.0 + isobject: 3.0.1 + + /has-values@0.1.4: + resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + + /has-values@1.0.0: + resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + is-number: 3.0.0 + kind-of: 4.0.0 + + /has@1.0.4: + resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==} + engines: {node: '>= 0.4.0'} + dev: false + + /hash-base@3.0.5: + resolution: {integrity: sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==} + engines: {node: '>= 0.10'} + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + dev: false + + /hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + + /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'} + dev: false + + /highlightjs-solidity@2.0.6: + resolution: {integrity: sha512-DySXWfQghjm2l6a/flF+cteroJqD4gI8GSdL4PtvxZSsAHie8m3yVe2JFoRg03ROKT6hp2Lc/BxXkqerNmtQYg==} + dev: false + + /history-with-query@4.10.4: + resolution: {integrity: sha512-JnskQK8X+PbRFHSdDAExhoJyhLnlLZL+UuHQuQhys+Se9/ukRDRBWU4JVTjsiIfbv1fcEmR3oqKW56OYmk5M5w==} + dependencies: + '@babel/runtime': 7.26.10 + 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 + dev: false + + /history@4.10.1: + resolution: {integrity: sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==} + dependencies: + '@babel/runtime': 7.26.10 + 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 + dev: false + + /history@5.3.0: + resolution: {integrity: sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==} + dependencies: + '@babel/runtime': 7.26.10 + dev: false + + /hmac-drbg@1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + dev: false + + /hoist-non-react-statics@1.2.0: + resolution: {integrity: sha512-r8huvKK+m+VraiRipdZYc+U4XW43j6OFG/oIafe7GfDbRpCduRoX9JI/DRxqgtBSCeL+et6N6ibZoedHS2NyOQ==} + dev: false + + /hoist-non-react-statics@3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + dependencies: + react-is: 16.13.1 + dev: false + + /home-or-tmp@2.0.0: + resolution: {integrity: sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg==} + engines: {node: '>=0.10.0'} + dependencies: + os-homedir: 1.0.2 + os-tmpdir: 1.0.2 + dev: true + + /hoopy@0.1.4: + resolution: {integrity: sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==} + engines: {node: '>= 6.0.0'} + dev: false + + /hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + + /hpack.js@2.1.6: + resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} + dependencies: + inherits: 2.0.4 + obuf: 1.1.2 + readable-stream: 2.3.8 + wbuf: 1.7.3 + dev: false + + /html-encoding-sniffer@2.0.1: + resolution: {integrity: sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==} + engines: {node: '>=10'} + dependencies: + whatwg-encoding: 1.0.5 + + /html-entities@2.5.2: + resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} + dev: false + + /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 + 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 + dev: true + + /html-minifier-terser@6.1.0: + resolution: {integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==} + engines: {node: '>=12'} + hasBin: true + 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 + dev: false + + /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 + 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 + dev: true + + /html-webpack-plugin@5.6.3(webpack@5.98.0): + 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 + 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 + webpack: 5.98.0 + dev: false + + /htmlparser2@6.1.0: + resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + domutils: 2.8.0 + entities: 2.2.0 + + /http-deceiver@1.2.7: + resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} + dev: false + + /http-errors@1.6.3: + resolution: {integrity: sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==} + engines: {node: '>= 0.6'} + dependencies: + depd: 1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.0 + statuses: 1.5.0 + dev: false + + /http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + dev: false + + /http-parser-js@0.5.9: + resolution: {integrity: sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==} + dev: false + + /http-proxy-agent@4.0.1: + resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} + engines: {node: '>= 6'} + dependencies: + '@tootallnate/once': 1.1.2 + agent-base: 6.0.2 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + + /http-proxy-middleware@2.0.7(@types/express@4.17.21): + resolution: {integrity: sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/express': ^4.17.13 + peerDependenciesMeta: + '@types/express': + optional: true + dependencies: + '@types/express': 4.17.21 + '@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 + transitivePeerDependencies: + - debug + dev: false + + /http-proxy@1.18.1: + resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} + engines: {node: '>=8.0.0'} + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.15.9 + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + dev: false + + /http2-client@1.3.5: + resolution: {integrity: sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==} + + /https-browserify@1.0.0: + resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} + dev: false + + /https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + + /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'} + dev: false + + /hyphenate-style-name@1.1.0: + resolution: {integrity: sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==} + dev: false + + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + + /iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /icss-utils@5.1.0(postcss@8.5.3): + resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + postcss: 8.5.3 + dev: false + + /idb@7.1.1: + resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==} + dev: false + + /identity-obj-proxy@3.0.0: + resolution: {integrity: sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==} + engines: {node: '>=4'} + dependencies: + harmony-reflect: 1.6.2 + + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: false + + /ignore@4.0.6: + resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==} + engines: {node: '>= 4'} + dev: false + + /ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + /immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + dev: false + + /immer@7.0.15: + resolution: {integrity: sha512-yM7jo9+hvYgvdCQdqvhCNRRio0SCXc8xDPzA25SvKWa7b1WVPjLwQs1VYU5JPXjcJPTqAa5NP5dqpORGYBQ2AA==} + dev: false + + /immer@9.0.21: + resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==} + dev: false + + /immutable@3.7.6: + resolution: {integrity: sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==} + engines: {node: '>=0.8.0'} + dev: false + + /immutable@3.8.2: + resolution: {integrity: sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg==} + engines: {node: '>=0.10.0'} + dev: false + + /import-cwd@2.1.0: + resolution: {integrity: sha512-Ew5AZzJQFqrOV5BTW3EIoHAnoie1LojZLXKcCQ/yTRyVZosBhK1x1ViYjHGf5pAFOq8ZyChZp6m/fSN7pJyZtg==} + engines: {node: '>=4'} + dependencies: + import-from: 2.1.0 + dev: false + + /import-fresh@2.0.0: + resolution: {integrity: sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==} + engines: {node: '>=4'} + dependencies: + caller-path: 2.0.0 + resolve-from: 3.0.0 + dev: false + + /import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + /import-from@2.1.0: + resolution: {integrity: sha512-0vdnLL2wSGnhlRmzHJAg5JHjt1l2vYhzJ7tNLGbeVg0fse56tpGaH0uzH+r9Slej+BSXXEHvBKDEnVSLLE9/+w==} + engines: {node: '>=4'} + dependencies: + resolve-from: 3.0.0 + dev: false + + /import-local@3.2.0: + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} + engines: {node: '>=8'} + hasBin: true + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + + /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==} + dev: false + + /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. + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + /inherits@2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + dev: false + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + /ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: false + + /inline-style-prefixer@7.0.1: + resolution: {integrity: sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==} + dependencies: + css-in-js-utils: 3.1.0 + dev: false + + /insert-css@2.0.0: + resolution: {integrity: sha512-xGq5ISgcUP5cvGkS2MMFLtPDBtrtQPSFfC6gA6U8wHKqfjTIMZLZNxOItQnoSjdOzlXOLU/yD32RKC4SvjNbtA==} + dev: false + + /internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + + /internmap@1.0.1: + resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==} + dev: false + + /intersection-observer@0.12.2: + resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==} + dev: false + + /intersection-observer@0.7.0: + resolution: {integrity: sha512-Id0Fij0HsB/vKWGeBe9PxeY45ttRiBmhFyyt/geBdDHBYNctMRTE3dC1U3ujzz3lap+hVXlEcVaB56kZP/eEUg==} + dev: false + + /intl-format-cache@4.3.1: + resolution: {integrity: sha512-OEUYNA7D06agqPOYhbTkl0T8HA3QKSuwWh1HiClEnpd9vw7N+3XsQt5iZ0GUEchp5CW1fQk/tary+NsbF3yQ1Q==} + dev: false + + /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 + dependencies: + '@formatjs/intl-unified-numberformat': 3.3.7 + dev: false + + /intl-messageformat@7.8.4: + resolution: {integrity: sha512-yS0cLESCKCYjseCOGXuV4pxJm/buTfyCJ1nzQjryHmSehlptbZbn9fnlk1I9peLopZGGbjj46yHHiTAEZ1qOTA==} + dependencies: + intl-format-cache: 4.3.1 + intl-messageformat-parser: 3.6.4 + dev: false + + /intl@1.2.5: + resolution: {integrity: sha512-rK0KcPHeBFBcqsErKSpvZnrOmWOj+EmDkyJ57e90YWaQNqbcivcqmKDlHEeNprDWOsKzPsh1BfSpPQdDvclHVw==} + dev: false + + /invariant@2.2.4: + resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} + dependencies: + loose-envify: 1.4.0 + + /inversify-inject-decorators@3.1.0: + resolution: {integrity: sha512-/seBlVp5bXrLQS3DpKEmlgeZL6C7Tf/QITd+IMQrbBBGuCbxb7k3hRAWu9XSreNpFzLgSboz3sClLSEmGwHphw==} + dev: false + + /inversify@5.1.1: + resolution: {integrity: sha512-j8grHGDzv1v+8T1sAQ+3boTCntFPfvxLCkNcxB1J8qA0lUN+fAlSyYd+RXKvaPRL4AGyPxViutBEJHNXOyUdFQ==} + dev: false + + /ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + dev: false + + /ipaddr.js@2.2.0: + resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} + engines: {node: '>= 10'} + dev: false + + /is-accessor-descriptor@1.0.1: + resolution: {integrity: sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==} + engines: {node: '>= 0.10'} + requiresBuild: true + dependencies: + hasown: 2.0.2 + + /is-any-array@2.0.1: + resolution: {integrity: sha512-UtilS7hLRu++wb/WBAw9bNuP1Eg04Ivn1vERJck8zJthEvXCBEBpGR/33u/xLKWEQf95803oalHrVDptcAvFdQ==} + dev: false + + /is-arguments@1.2.0: + resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + dev: false + + /is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + /is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + dev: false + + /is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + dependencies: + has-bigints: 1.1.0 + + /is-binary-path@1.0.1: + resolution: {integrity: sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + binary-extensions: 1.13.1 + dev: true + optional: true + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.3.0 + + /is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + /is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + requiresBuild: true + + /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 + dependencies: + ci-info: 1.6.0 + dev: true + + /is-ci@2.0.0: + resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==} + hasBin: true + dependencies: + ci-info: 2.0.0 + + /is-class-hotfix@0.0.6: + resolution: {integrity: sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ==} + dev: true + + /is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + dependencies: + hasown: 2.0.2 + + /is-data-descriptor@1.0.1: + resolution: {integrity: sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==} + engines: {node: '>= 0.4'} + requiresBuild: true + dependencies: + hasown: 2.0.2 + + /is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + + /is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + /is-descriptor@0.1.7: + resolution: {integrity: sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==} + engines: {node: '>= 0.4'} + requiresBuild: true + dependencies: + is-accessor-descriptor: 1.0.1 + is-data-descriptor: 1.0.1 + + /is-descriptor@1.0.3: + resolution: {integrity: sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==} + engines: {node: '>= 0.4'} + requiresBuild: true + dependencies: + is-accessor-descriptor: 1.0.1 + is-data-descriptor: 1.0.1 + + /is-directory@0.3.1: + resolution: {integrity: sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==} + engines: {node: '>=0.10.0'} + dev: false + + /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'} + requiresBuild: true + dev: true + optional: true + + /is-equal-shallow@0.1.3: + resolution: {integrity: sha512-0EygVC5qPvIyb+gSz7zdD5/AAoS6Qrx1e//6N4yv4oNm30kqvdmG66oZFWVlQHUWe5OjP08FuTw2IdT0EOTcYA==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + is-primitive: 2.0.0 + dev: true + optional: true + + /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'} + requiresBuild: true + dependencies: + is-plain-object: 2.0.4 + + /is-extglob@1.0.0: + resolution: {integrity: sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dev: true + optional: true + + /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'} + dependencies: + call-bound: 1.0.4 + + /is-finite@1.1.0: + resolution: {integrity: sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==} + engines: {node: '>=0.10.0'} + dev: true + + /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'} + 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: + resolution: {integrity: sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + is-extglob: 1.0.0 + dev: true + optional: true + + /is-glob@3.1.0: + resolution: {integrity: sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: false + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + + /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==} + dev: false + + /is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + /is-number@2.1.0: + resolution: {integrity: sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + kind-of: 3.2.2 + dev: true + optional: true + + /is-number@3.0.0: + resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + kind-of: 3.2.2 + + /is-number@4.0.0: + resolution: {integrity: sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dev: true + optional: true + + /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'} + dev: false + + /is-plain-obj@3.0.0: + resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} + engines: {node: '>=10'} + dev: false + + /is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + + /is-posix-bracket@0.1.1: + resolution: {integrity: sha512-Yu68oeXJ7LeWNmZ3Zov/xg/oDBnBK2RNxwYY1ilNJX+tKKZqgPK+qOn/Gs9jEu66KDY9Netf5XLKNGzas/vPfQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dev: true + optional: true + + /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'} + requiresBuild: true + dev: true + optional: true + + /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'} + dependencies: + call-bind: 1.0.8 + has-tostringtag: 1.0.2 + dev: false + + /is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + /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'} + dev: false + + /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'} + dependencies: + call-bound: 1.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'} + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + /is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + /is-type-of@1.4.0: + resolution: {integrity: sha512-EddYllaovi5ysMLMEN7yzHEKh8A850cZ7pykrY1aNRQGn/CDjRDE9qEWbIdt7xGEVJmjBXzU/fNnC4ABTm8tEQ==} + dependencies: + core-util-is: 1.0.3 + is-class-hotfix: 0.0.6 + isstream: 0.1.2 + dev: true + + /is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.19 + + /is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + + /is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + dev: true + + /is-url@1.2.4: + resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} + dev: false + + /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'} + dependencies: + call-bound: 1.0.4 + + /is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + /is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + requiresBuild: true + + /is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + dependencies: + is-docker: 2.2.1 + + /isarray@0.0.1: + resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} + dev: false + + /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'} + requiresBuild: true + dependencies: + isarray: 1.0.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==} + dependencies: + node-fetch: 1.7.3 + whatwg-fetch: 3.6.20 + dev: false + + /isstream@0.1.2: + resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} + dev: true + + /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'} + 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: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + dependencies: + '@babel/core': 7.18.6 + '@babel/parser': 7.26.10 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + /istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + /istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + dependencies: + debug: 4.4.0 + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + + /istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + /iterator.prototype@1.1.5: + resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} + engines: {node: '>= 0.4'} + 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 + dev: false + + /jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + dev: false + + /jake@10.9.2: + resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + async: 3.2.6 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + dev: false + + /javascript-stringify@2.1.0: + resolution: {integrity: sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==} + dev: false + + /jest-changed-files@26.6.2: + resolution: {integrity: sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/types': 26.6.2 + execa: 4.1.0 + throat: 5.0.0 + + /jest-changed-files@27.5.1: + resolution: {integrity: sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + '@jest/types': 27.5.1 + execa: 5.1.1 + throat: 6.0.2 + dev: false + + /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} + dependencies: + '@jest/environment': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.13.10 + 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 + dev: false + + /jest-cli@26.6.3: + resolution: {integrity: sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg==} + engines: {node: '>= 10.14.2'} + hasBin: true + dependencies: + '@jest/core': 26.6.3 + '@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 + 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: + 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 + dependencies: + '@jest/core': 27.5.1 + '@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 + jest-util: 27.5.1 + jest-validate: 27.5.1 + prompts: 2.4.2 + yargs: 16.2.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + dev: false + + /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 + dependencies: + '@babel/core': 7.18.6 + '@jest/test-sequencer': 26.6.3 + '@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 + 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 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + + /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 + 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 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + dev: false + + /jest-diff@26.6.2: + resolution: {integrity: sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==} + engines: {node: '>= 10.14.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: + resolution: {integrity: sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + chalk: 4.1.2 + diff-sequences: 27.5.1 + jest-get-type: 27.5.1 + pretty-format: 27.5.1 + dev: false + + /jest-docblock@26.0.0: + resolution: {integrity: sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==} + engines: {node: '>= 10.14.2'} + dependencies: + detect-newline: 3.1.0 + + /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} + dependencies: + detect-newline: 3.1.0 + dev: false + + /jest-each@26.6.2: + resolution: {integrity: sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A==} + engines: {node: '>= 10.14.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: + resolution: {integrity: sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + 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 + dev: false + + /jest-environment-jsdom@26.6.2: + resolution: {integrity: sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/environment': 26.6.2 + '@jest/fake-timers': 26.6.2 + '@jest/types': 26.6.2 + '@types/node': 22.13.10 + 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: + resolution: {integrity: sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + '@jest/environment': 27.5.1 + '@jest/fake-timers': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.13.10 + jest-mock: 27.5.1 + jest-util: 27.5.1 + jsdom: 16.7.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + dev: false + + /jest-environment-node@26.6.2: + resolution: {integrity: sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/environment': 26.6.2 + '@jest/fake-timers': 26.6.2 + '@jest/types': 26.6.2 + '@types/node': 22.13.10 + jest-mock: 26.6.2 + jest-util: 26.6.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} + dependencies: + '@jest/environment': 27.5.1 + '@jest/fake-timers': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.13.10 + jest-mock: 27.5.1 + jest-util: 27.5.1 + dev: false + + /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} + dev: false + + /jest-haste-map@26.6.2: + resolution: {integrity: sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/types': 26.6.2 + '@types/graceful-fs': 4.1.9 + '@types/node': 22.13.10 + 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: + resolution: {integrity: sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + '@jest/types': 27.5.1 + '@types/graceful-fs': 4.1.9 + '@types/node': 22.13.10 + 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 + dev: false + + /jest-jasmine2@26.6.3: + resolution: {integrity: sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==} + engines: {node: '>= 10.14.2'} + dependencies: + '@babel/traverse': 7.26.10 + '@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.13.10 + 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 + 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: + resolution: {integrity: sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + 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.13.10 + 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 + dev: false + + /jest-leak-detector@26.6.2: + resolution: {integrity: sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg==} + engines: {node: '>= 10.14.2'} + dependencies: + jest-get-type: 26.3.0 + pretty-format: 26.6.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} + dependencies: + jest-get-type: 27.5.1 + pretty-format: 27.5.1 + dev: false + + /jest-matcher-utils@26.6.2: + resolution: {integrity: sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==} + engines: {node: '>= 10.14.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: + resolution: {integrity: sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + chalk: 4.1.2 + jest-diff: 27.5.1 + jest-get-type: 27.5.1 + pretty-format: 27.5.1 + dev: false + + /jest-message-util@26.6.2: + resolution: {integrity: sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==} + engines: {node: '>= 10.14.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: + resolution: {integrity: sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + 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 + dev: false + + /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} + 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 + dev: false + + /jest-mock@26.6.2: + resolution: {integrity: sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/types': 26.6.2 + '@types/node': 22.13.10 + + /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} + dependencies: + '@jest/types': 27.5.1 + '@types/node': 22.13.10 + dev: false + + /jest-pnp-resolver@1.2.3(jest-resolve@26.6.2): + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + dependencies: + jest-resolve: 26.6.2 + + /jest-pnp-resolver@1.2.3(jest-resolve@27.5.1): + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + dependencies: + jest-resolve: 27.5.1 + dev: false + + /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} + dev: false + + /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} + dev: false + + /jest-resolve-dependencies@26.6.3: + resolution: {integrity: sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg==} + engines: {node: '>= 10.14.2'} + 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: + resolution: {integrity: sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + '@jest/types': 27.5.1 + jest-regex-util: 27.5.1 + jest-snapshot: 27.5.1 + transitivePeerDependencies: + - supports-color + dev: false + + /jest-resolve@26.6.2: + resolution: {integrity: sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ==} + engines: {node: '>= 10.14.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: + resolution: {integrity: sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + 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 + dev: false + + /jest-runner@26.6.3: + resolution: {integrity: sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ==} + engines: {node: '>= 10.14.2'} + 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.13.10 + chalk: 4.1.2 + emittery: 0.7.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 26.6.3 + 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 + 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: + resolution: {integrity: sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + 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.13.10 + 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 + dev: false + + /jest-runtime@26.6.3: + resolution: {integrity: sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==} + engines: {node: '>= 10.14.2'} + hasBin: true + 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 + 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: + resolution: {integrity: sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + 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 + dev: false + + /jest-serializer@26.6.2: + resolution: {integrity: sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==} + engines: {node: '>= 10.14.2'} + dependencies: + '@types/node': 22.13.10 + graceful-fs: 4.2.11 + + /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} + dependencies: + '@types/node': 22.13.10 + graceful-fs: 4.2.11 + dev: false + + /jest-snapshot@26.6.2: + resolution: {integrity: sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og==} + engines: {node: '>= 10.14.2'} + dependencies: + '@babel/types': 7.26.10 + '@jest/types': 26.6.2 + '@types/babel__traverse': 7.20.6 + '@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: + resolution: {integrity: sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + '@babel/core': 7.26.10 + '@babel/generator': 7.26.10 + '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.10) + '@babel/traverse': 7.26.10 + '@babel/types': 7.26.10 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/babel__traverse': 7.20.6 + '@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 + dev: false + + /jest-util@26.6.2: + resolution: {integrity: sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/types': 26.6.2 + '@types/node': 22.13.10 + chalk: 4.1.2 + graceful-fs: 4.2.11 + is-ci: 2.0.0 + micromatch: 4.0.8 + + /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} + dependencies: + '@jest/types': 27.5.1 + '@types/node': 22.13.10 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + dev: false + + /jest-util@28.1.3: + resolution: {integrity: sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/types': 28.1.3 + '@types/node': 22.13.10 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + dev: false + + /jest-validate@26.6.2: + resolution: {integrity: sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ==} + engines: {node: '>= 10.14.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: + resolution: {integrity: sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + 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 + dev: false + + /jest-watch-typeahead@1.1.0(jest@27.5.1): + 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 + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + jest: 27.5.1 + 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 + dev: false + + /jest-watcher@26.6.2: + resolution: {integrity: sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/test-result': 26.6.2 + '@jest/types': 26.6.2 + '@types/node': 22.13.10 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + jest-util: 26.6.2 + string-length: 4.0.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} + dependencies: + '@jest/test-result': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.13.10 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + jest-util: 27.5.1 + string-length: 4.0.2 + dev: false + + /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} + dependencies: + '@jest/test-result': 28.1.3 + '@jest/types': 28.1.3 + '@types/node': 22.13.10 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.10.2 + jest-util: 28.1.3 + string-length: 4.0.2 + dev: false + + /jest-worker@24.9.0: + resolution: {integrity: sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==} + engines: {node: '>= 6'} + dependencies: + merge-stream: 2.0.0 + supports-color: 6.1.0 + + /jest-worker@26.6.2: + resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/node': 22.13.10 + merge-stream: 2.0.0 + supports-color: 7.2.0 + + /jest-worker@27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/node': 22.13.10 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: false + + /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} + dependencies: + '@types/node': 22.13.10 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: false + + /jest@26.6.3: + resolution: {integrity: sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q==} + engines: {node: '>= 10.14.2'} + hasBin: true + dependencies: + '@jest/core': 26.6.3 + import-local: 3.2.0 + jest-cli: 26.6.3 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + /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 + dependencies: + '@jest/core': 27.5.1 + import-local: 3.2.0 + jest-cli: 27.5.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + dev: false + + /jiti@1.21.7: + resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} + hasBin: true + dev: false + + /jquery-mousewheel@3.1.13: + resolution: {integrity: sha512-GXhSjfOPyDemM005YCEHvzrEALhKDIswtxSHSR2e4K/suHVJKJxxRCGz3skPjNxjJjQa9AVSGGlYjv1M3VLIPg==} + dev: false + + /jquery@3.7.1: + resolution: {integrity: sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==} + dev: false + + /js-base64@2.6.4: + resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==} + dev: true + + /js-base64@3.7.7: + resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==} + dev: false + + /js-cookie@2.2.1: + resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==} + dev: false + + /js-cookie@3.0.5: + resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} + engines: {node: '>=14'} + dev: false + + /js-tokens@3.0.2: + resolution: {integrity: sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==} + dev: true + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + /js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + + /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 + 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.18 + 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: + resolution: {integrity: sha512-tz3Mt26EjMntSXPHWxFZfNyAROVfOGAUkdvSkuorilP2HBO/Ll4jYMf39f9ajvyEkTIpNNB3CBmaa+4Xx7A5zw==} + dependencies: + jsencrypt: 3.3.2 + dev: false + + /jsencrypt@3.3.2: + resolution: {integrity: sha512-arQR1R1ESGdAxY7ZheWr12wCaF2yF47v5qpB76TtV64H1pyGudk9Hvw8Y9tb/FiTIaaTRUyaSnm5T/Y53Ghm/A==} + dev: false + + /jsesc@0.5.0: + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + hasBin: true + dev: true + + /jsesc@1.3.0: + resolution: {integrity: sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA==} + hasBin: true + dev: true + + /jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + dev: false + + /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==} + dev: false + + /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==} + dev: false + + /json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + dev: false + + /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==} + dev: false + + /json2module@0.0.3: + resolution: {integrity: sha512-qYGxqrRrt4GbB8IEOy1jJGypkNsjWoIMlZt4bAsmUScCA507Hbc2p1JOhBzqn45u3PWafUgH2OnzyNU7udO/GA==} + hasBin: true + dependencies: + rw: 1.3.3 + dev: false + + /json2mq@0.2.0: + resolution: {integrity: sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==} + dependencies: + string-convert: 0.2.1 + dev: false + + /json5@0.5.1: + resolution: {integrity: sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw==} + hasBin: true + dev: true + + /json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + + /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==} + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + /jsonpath@1.1.1: + resolution: {integrity: sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==} + dependencies: + esprima: 1.2.2 + static-eval: 2.0.2 + underscore: 1.12.1 + dev: false + + /jsonpointer@5.0.1: + resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} + engines: {node: '>=0.10.0'} + dev: false + + /jsx-ast-utils@3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + dependencies: + array-includes: 3.1.8 + array.prototype.flat: 1.3.3 + object.assign: 4.1.7 + object.values: 1.2.1 + dev: false + + /junk@3.1.0: + resolution: {integrity: sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==} + engines: {node: '>=8'} + dev: false + + /kdbush@3.0.0: + resolution: {integrity: sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==} + dev: false + + /kdbush@4.0.2: + resolution: {integrity: sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==} + dev: false + + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + + /kind-of@3.2.2: + resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-buffer: 1.1.6 + + /kind-of@4.0.0: + resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + is-buffer: 1.1.6 + + /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'} + dev: false + + /language-subtag-registry@0.3.23: + resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} + dev: false + + /language-tags@1.0.9: + resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} + engines: {node: '>=0.10'} + dependencies: + language-subtag-registry: 0.3.23 + dev: false + + /launch-editor@2.10.0: + resolution: {integrity: sha512-D7dBRJo/qcGX9xlvt/6wUYzQxjh5G1RvZPgPv8vi4KRU99DVQL/oW7tnVOCCTm2HGeo3C5HvGE5Yrh6UBoZ0vA==} + dependencies: + picocolors: 1.1.1 + shell-quote: 1.8.2 + dev: false + + /lazy-cache@1.0.4: + resolution: {integrity: sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==} + engines: {node: '>=0.10.0'} + dev: false + + /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'} + dependencies: + prelude-ls: 1.1.2 + type-check: 0.3.2 + dev: false + + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + /lie@3.1.1: + resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==} + dependencies: + immediate: 3.0.6 + dev: false + + /lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + dev: false + + /lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + dev: false + + /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 + 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 + dev: true + + /listr2@3.14.0(enquirer@2.4.1): + resolution: {integrity: sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==} + engines: {node: '>=10.0.0'} + peerDependencies: + enquirer: '>= 2.3.0 < 3' + peerDependenciesMeta: + enquirer: + optional: true + dependencies: + cli-truncate: 2.1.0 + colorette: 2.0.20 + enquirer: 2.4.1 + 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 + dev: true + + /loader-runner@4.3.0: + resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} + engines: {node: '>=6.11.5'} + dev: false + + /loader-utils@1.4.2: + resolution: {integrity: sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==} + engines: {node: '>=4.0.0'} + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 1.0.2 + + /loader-utils@2.0.4: + resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==} + engines: {node: '>=8.9.0'} + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 2.2.3 + + /loader-utils@3.3.1: + resolution: {integrity: sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==} + engines: {node: '>= 12.13.0'} + dev: false + + /localforage@1.10.0: + resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==} + dependencies: + lie: 3.1.1 + dev: false + + /locate-path@3.0.0: + resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} + engines: {node: '>=6'} + dependencies: + p-locate: 3.0.0 + path-exists: 3.0.0 + dev: false + + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + + /lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + dev: false + + /lodash._reinterpolate@3.0.0: + resolution: {integrity: sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==} + dev: false + + /lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + dev: false + + /lodash.curry@4.1.1: + resolution: {integrity: sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA==} + dev: false + + /lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + dev: false + + /lodash.flow@3.5.0: + resolution: {integrity: sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw==} + dev: false + + /lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. + dev: false + + /lodash.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + dev: false + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + /lodash.sortby@4.7.0: + resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + dev: false + + /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. + dependencies: + lodash._reinterpolate: 3.0.0 + lodash.templatesettings: 4.2.0 + dev: false + + /lodash.templatesettings@4.2.0: + resolution: {integrity: sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==} + dependencies: + lodash._reinterpolate: 3.0.0 + dev: false + + /lodash.throttle@4.1.1: + resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} + dev: false + + /lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + dev: false + + /lodash.upperfirst@4.3.1: + resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} + dev: false + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + /log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + dev: true + + /log-update@4.0.0: + resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} + engines: {node: '>=10'} + dependencies: + ansi-escapes: 4.3.2 + cli-cursor: 3.1.0 + slice-ansi: 4.0.0 + wrap-ansi: 6.2.0 + dev: true + + /longest@1.0.1: + resolution: {integrity: sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==} + engines: {node: '>=0.10.0'} + dev: false + + /loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + dependencies: + js-tokens: 4.0.0 + + /lottie-web@5.12.2: + resolution: {integrity: sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==} + dev: false + + /lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + dependencies: + tslib: 2.8.1 + + /lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + dev: false + + /lru-cache@4.1.5: + resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + dependencies: + pseudomap: 1.0.2 + yallist: 2.1.2 + dev: true + + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + + /lru-queue@0.1.0: + resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==} + dependencies: + es5-ext: 0.10.64 + + /magic-string@0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + dependencies: + sourcemap-codec: 1.4.8 + dev: false + + /make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + dependencies: + semver: 6.3.1 + dev: false + + /make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + dependencies: + semver: 7.7.1 + + /make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: true + + /makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + dependencies: + tmpl: 1.0.5 + + /mana-common@0.3.2: + resolution: {integrity: sha512-1oylLR9CcyshQcTiBdM96HxIoaA413eudpo1INiOCwyZE554TDJNUD0zrIjmeBvw8CBAjukzaAHn2gn0hZphIg==} + dev: false + + /mana-syringe@0.2.2: + resolution: {integrity: sha512-Sv5r0/PrQRq4pW+9lDicGsEPzPLkd1PwjTs5zHUV1I293S3alkBNyuSjktVeBploofH8MAMLd4DS2crwct48wg==} + dependencies: + inversify: 5.1.1 + dev: false + + /map-cache@0.2.2: + resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} + engines: {node: '>=0.10.0'} + requiresBuild: true + + /map-visit@1.0.0: + resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + object-visit: 1.0.1 + + /mapbox-gl@1.13.3: + resolution: {integrity: sha512-p8lJFEiqmEQlyv+DQxFAOG/XPWN0Wp7j/Psq93Zywz7qt9CcUKFYDBOoOEKzqe6gudHVJY8/Bhqw6VDpX2lSBg==} + engines: {node: '>=6.4.0'} + 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 + dev: false + + /maplibre-gl@3.6.2: + resolution: {integrity: sha512-krg2KFIdOpLPngONDhP6ixCoWl5kbdMINP0moMSJFVX7wX1Clm2M9hlNKXS8vBGlVWwR5R3ZfI6IPrYz7c+aCQ==} + engines: {node: '>=16.14.0', npm: '>=8.1.0'} + 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 + dev: false + + /material-colors@1.2.6: + resolution: {integrity: sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==} + dev: false + + /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==} + requiresBuild: true + dev: true + optional: true + + /md5.js@1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + dependencies: + hash-base: 3.0.5 + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /mdn-data@2.0.14: + resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + dev: false + + /mdn-data@2.0.4: + resolution: {integrity: sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==} + dev: false + + /media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + dev: false + + /memfs@3.5.3: + resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} + engines: {node: '>= 4.0.0'} + dependencies: + fs-monkey: 1.0.6 + dev: false + + /memoize-one@5.2.1: + resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==} + dev: false + + /memoizee@0.4.17: + resolution: {integrity: sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==} + engines: {node: '>=0.12'} + 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: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + dev: false + + /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'} + dev: false + + /methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + dev: false + + /micromatch@2.3.11: + resolution: {integrity: sha512-LnU2XFEk9xxSJ6rfgAry/ty5qwUTyHYOBU0g4R6tIw5ljwgGIBmiKhRWLw5NpMOnrgUNcDJ4WMp8rl3sYVHLNA==} + engines: {node: '>=0.10.0'} + requiresBuild: true + 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 + dev: true + optional: true + + /micromatch@3.1.10: + resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} + engines: {node: '>=0.10.0'} + 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: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + /miller-rabin@4.0.1: + resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} + hasBin: true + dependencies: + bn.js: 4.12.1 + brorand: 1.1.0 + dev: false + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + /mime-db@1.53.0: + resolution: {integrity: sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + + /mime@1.4.1: + resolution: {integrity: sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==} + hasBin: true + dev: false + + /mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + /min-document@2.19.0: + resolution: {integrity: sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==} + dependencies: + dom-walk: 0.1.2 + dev: false + + /mini-create-react-context@0.4.1(prop-types@15.8.1)(react@16.14.0): + 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 + dependencies: + '@babel/runtime': 7.26.10 + prop-types: 15.8.1 + react: 16.14.0 + tiny-warning: 1.0.3 + dev: false + + /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 + dependencies: + loader-utils: 2.0.4 + schema-utils: 3.3.0 + webpack-sources: 1.4.3 + dev: true + + /mini-css-extract-plugin@2.9.2(webpack@5.98.0): + resolution: {integrity: sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + dependencies: + schema-utils: 4.3.0 + tapable: 2.2.1 + webpack: 5.98.0 + dev: false + + /minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + dev: false + + /minimalistic-crypto-utils@1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + dev: false + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + + /minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: false + + /minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: false + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + /minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + dev: false + + /mixin-deep@1.3.2: + resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + for-in: 1.0.2 + is-extendable: 1.0.1 + + /mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + dependencies: + minimist: 1.2.8 + + /ml-array-max@1.2.4: + resolution: {integrity: sha512-BlEeg80jI0tW6WaPyGxf5Sa4sqvcyY6lbSn5Vcv44lp1I2GR6AWojfUvLnGTNsIXrZ8uqWmo8VcG1WpkI2ONMQ==} + dependencies: + is-any-array: 2.0.1 + dev: false + + /ml-array-min@1.2.3: + resolution: {integrity: sha512-VcZ5f3VZ1iihtrGvgfh/q0XlMobG6GQ8FsNyQXD3T+IlstDv85g8kfV0xUG1QPRO/t21aukaJowDzMTc7j5V6Q==} + dependencies: + is-any-array: 2.0.1 + dev: false + + /ml-array-rescale@1.3.7: + resolution: {integrity: sha512-48NGChTouvEo9KBctDfHC3udWnQKNKEWN0ziELvY3KG25GR5cA8K8wNVzracsqSW1QEkAXjTNx+ycgAv06/1mQ==} + dependencies: + is-any-array: 2.0.1 + ml-array-max: 1.2.4 + ml-array-min: 1.2.3 + dev: false + + /ml-matrix@6.12.1: + resolution: {integrity: sha512-TJ+8eOFdp+INvzR4zAuwBQJznDUfktMtOB6g/hUcGh3rcyjxbz4Te57Pgri8Q9bhSQ7Zys4IYOGhFdnlgeB6Lw==} + dependencies: + is-any-array: 2.0.1 + ml-array-rescale: 1.3.7 + dev: false + + /ml-matrix@6.5.0: + resolution: {integrity: sha512-sms732Dge+rs5dU4mnjE0oqLWm1WujvR2fr38LgUHRG2cjXjWlO3WJupLYaSz3++2iYr0UrGDK72OAivr3J8dg==} + dependencies: + ml-array-rescale: 1.3.7 + dev: false + + /mock-property@1.0.3: + resolution: {integrity: sha512-2emPTb1reeLLYwHxyVx993iYyCHEiRRO+y8NFXFPL5kl5q14sgTK76cXyEKkeKCHeRw35SfdkUJ10Q1KfHuiIQ==} + engines: {node: '>= 0.4'} + 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 + dev: false + + /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 + dependencies: + commander: 13.1.0 + + /moment@2.30.1: + resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} + dev: false + + /mousetrap@1.6.5: + resolution: {integrity: sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==} + dev: false + + /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 + dependencies: + dns-packet: 5.6.1 + thunky: 1.1.0 + dev: false + + /murmurhash-js@1.0.0: + resolution: {integrity: sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==} + dev: false + + /mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + dev: false + + /nan@2.22.2: + resolution: {integrity: sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==} + requiresBuild: true + dev: true + optional: true + + /nano-css@5.6.2: + resolution: {integrity: sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw==} + peerDependencies: + react: '*' + react-dom: '*' + 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 + rtl-css-js: 1.16.1 + stacktrace-js: 2.0.2 + stylis: 4.3.6 + dev: false + + /nanoid@3.3.10: + resolution: {integrity: sha512-vSJJTG+t/dIKAUhUDw/dLdZ9s//5OxcHqLaDWWrW4Cdq7o6tdLIczUkMXt2MBNmk6sJRZBZRXVixs7URY1CmIg==} + 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'} + requiresBuild: true + 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: + resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} + dev: false + + /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'} + dev: false + + /negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + dev: false + + /neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + dev: false + + /nested-error-stacks@2.1.1: + resolution: {integrity: sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==} + dev: false + + /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==} + dependencies: + lower-case: 2.0.2 + tslib: 2.8.1 + + /node-fetch-h2@2.3.0: + resolution: {integrity: sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==} + engines: {node: 4.x || >=6.0.0} + dependencies: + http2-client: 1.3.5 + + /node-fetch@1.7.3: + resolution: {integrity: sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==} + dependencies: + encoding: 0.1.13 + is-stream: 1.1.0 + dev: false + + /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 + dependencies: + whatwg-url: 5.0.0 + + /node-forge@1.3.1: + resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} + engines: {node: '>= 6.13.0'} + dev: false + + /node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + + /node-libs-browser@2.2.1: + resolution: {integrity: sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==} + 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 + dev: false + + /node-notifier@8.0.2: + resolution: {integrity: sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg==} + requiresBuild: true + 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: + resolution: {integrity: sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA==} + dependencies: + es6-promise: 3.3.1 + + /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==} + 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: + resolution: {integrity: sha512-7WyT0w8jhpDStXRq5836AMmihQwq2nrUVQrgjvUo/p/NZf9uy/MeJ246lBJVmWuYXMlJuG9BNZHF0hWjfTbQUA==} + engines: {node: '>=0.10.0'} + dev: true + + /normalize-path@2.1.1: + resolution: {integrity: sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==} + engines: {node: '>=0.10.0'} + dependencies: + remove-trailing-separator: 1.1.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'} + dev: false + + /normalize-url@1.9.1: + resolution: {integrity: sha512-A48My/mtCklowHBlI8Fq2jFWK4tX4lJ5E6ytFsSOq1fzpvT0SQSgKhSg7lN5c2uYFOrUAOQp6zhhJnpp1eMloQ==} + engines: {node: '>=4'} + dependencies: + object-assign: 4.1.1 + prepend-http: 1.0.4 + query-string: 4.3.4 + sort-keys: 1.1.2 + dev: false + + /normalize-url@6.1.0: + resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} + engines: {node: '>=10'} + dev: false + + /normalize.css@7.0.0: + resolution: {integrity: sha512-LYaFZxj2Q1Q9e1VJ0f6laG46Rt5s9URhKyckNaA2vZnL/0gwQHWhM7ALQkp3WBQKM5sXRLQ5Ehrfkp+E/ZiCRg==} + dev: false + + /npm-run-path@2.0.2: + resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} + engines: {node: '>=4'} + dependencies: + path-key: 2.0.1 + + /npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + + /nth-check@1.0.2: + resolution: {integrity: sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==} + dependencies: + boolbase: 1.0.0 + dev: false + + /nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + dependencies: + boolbase: 1.0.0 + + /num2fraction@1.2.2: + resolution: {integrity: sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==} + dev: false + + /numericjs@1.2.6: + resolution: {integrity: sha512-AbumaZGCaoXy0Fn231zqrFbQ1b6yUX5WD2Ve5jvD1hJbIYaCKFsG7XPFz5M8+O5rqdxI6Ms5+TQL8ZeSdN5FdA==} + dev: false + + /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 + dependencies: + a-sync-waterfall: 1.0.1 + asap: 2.0.6 + commander: 5.1.0 + + /nwsapi@2.2.18: + resolution: {integrity: sha512-p1TRH/edngVEHVbwqWnxUViEmq5znDvyB+Sik5cmuLpGOIfDf/39zLiq3swPF8Vakqn+gvNiOQAZu8djYlQILA==} + + /oas-kit-common@1.0.8: + resolution: {integrity: sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==} + dependencies: + fast-safe-stringify: 2.1.1 + + /oas-linter@3.2.2: + resolution: {integrity: sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==} + dependencies: + '@exodus/schemasafe': 1.3.0 + should: 13.2.3 + yaml: 1.10.2 + + /oas-resolver@2.5.6: + resolution: {integrity: sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==} + hasBin: true + 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: + resolution: {integrity: sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==} + + /oas-validator@5.0.8: + resolution: {integrity: sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==} + 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: + 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'} + requiresBuild: true + dependencies: + copy-descriptor: 0.1.1 + define-property: 0.2.5 + kind-of: 3.2.2 + + /object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + dev: false + + /object-inspect@1.12.3: + resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + dev: false + + /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'} + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + dev: false + + /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'} + requiresBuild: true + dependencies: + isobject: 3.0.1 + + /object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + dev: false + + /object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-object-atoms: 1.1.1 + dev: false + + /object.getownpropertydescriptors@2.1.8: + resolution: {integrity: sha512-qkHIGe4q0lSYMv0XI4SsBTJz3WaURhLvd0lKSgtVuOsJ2krg4SgMw3PIRQFMp07yi++UR3se2mkcLqsBNpBb/A==} + engines: {node: '>= 0.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: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + dev: false + + /object.omit@2.0.1: + resolution: {integrity: sha512-UiAM5mhmIuKLsOvrL+B0U2d1hXHF3bFYWIuH1LMpuV2EJEHG1Ntz06PgLEHjm6VFd87NpH8rastvPoyv6UW2fA==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + for-own: 0.1.5 + is-extendable: 0.1.1 + dev: true + optional: true + + /object.pick@1.3.0: + resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + isobject: 3.0.1 + + /object.values@1.2.1: + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + dev: false + + /obuf@1.1.2: + resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} + dev: false + + /omit.js@1.0.2: + resolution: {integrity: sha512-/QPc6G2NS+8d4L/cQhbk6Yit1WTB6Us2g84A7A/1+w9d/eRGHyEqC5kkQtHVoHZ5NFWGG7tUGgrhVZwgZanKrQ==} + dependencies: + babel-runtime: 6.26.0 + dev: false + + /on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: false + + /on-headers@1.0.2: + resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} + engines: {node: '>= 0.8'} + dev: false + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + + /onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + + /open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + dev: false + + /openapi3-ts@2.0.2: + resolution: {integrity: sha512-TxhYBMoqx9frXyOgnRHufjQfPXomTIHYKhSKJ6jHfj13kS8OEIhvmE8CTuQyKtjjWttAjX5DPxM1vmalEpo8Qw==} + dependencies: + yaml: 1.10.2 + + /optionator@0.8.3: + resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} + engines: {node: '>= 0.8.0'} + 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 + dev: false + + /optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + 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: + resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} + dev: false + + /os-homedir@1.0.2: + resolution: {integrity: sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==} + engines: {node: '>=0.10.0'} + dev: true + + /os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + dev: true + + /output-file-sync@1.1.2: + resolution: {integrity: sha512-uQLlclru4xpCi+tfs80l3QF24KL81X57ELNMy7W/dox+JTtxUf1bLyQ8968fFCmSqqbokjW0kn+WBIlO+rSkNg==} + dependencies: + graceful-fs: 4.2.11 + mkdirp: 0.5.6 + object-assign: 4.1.1 + dev: true + + /own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + + /p-all@2.1.0: + resolution: {integrity: sha512-HbZxz5FONzz/z2gJfk6bFca0BCiSRF8jU3yCsWOen/vR6lZjfPOu/e7L3uFzTW1i0H8TlC3vqQstEJPQL4/uLA==} + engines: {node: '>=6'} + dependencies: + p-map: 2.1.0 + dev: false + + /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'} + dependencies: + p-timeout: 3.2.0 + dev: false + + /p-filter@2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} + engines: {node: '>=8'} + dependencies: + p-map: 2.1.0 + dev: false + + /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'} + dependencies: + p-try: 2.2.0 + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + + /p-locate@3.0.0: + resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} + engines: {node: '>=6'} + dependencies: + p-limit: 2.3.0 + dev: false + + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + + /p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + dev: false + + /p-map@3.0.0: + resolution: {integrity: sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==} + engines: {node: '>=8'} + dependencies: + aggregate-error: 3.1.0 + dev: false + + /p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + dependencies: + aggregate-error: 3.1.0 + dev: true + + /p-retry@4.6.2: + resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} + engines: {node: '>=8'} + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 + dev: false + + /p-timeout@3.2.0: + resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} + engines: {node: '>=8'} + dependencies: + p-finally: 1.0.0 + dev: false + + /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==} + dev: false + + /pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + dev: false + + /param-case@3.0.4: + resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} + dependencies: + dot-case: 3.0.4 + tslib: 2.8.1 + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + + /parse-asn1@5.1.7: + resolution: {integrity: sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==} + engines: {node: '>= 0.10'} + 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 + dev: false + + /parse-glob@3.0.4: + resolution: {integrity: sha512-FC5TeK0AwXzq3tUBFtH74naWkPQCEWs4K+xMxWZBlKDWu0bVHXGZa+KKqxKidd7xwhdZ19ZNuF2uO1M/r196HA==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + glob-base: 0.3.0 + is-dotfile: 1.0.3 + is-extglob: 1.0.0 + is-glob: 2.0.1 + dev: true + optional: true + + /parse-json@4.0.0: + resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} + engines: {node: '>=4'} + dependencies: + error-ex: 1.3.2 + json-parse-better-errors: 1.0.2 + dev: false + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + 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: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + + /parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + dev: false + + /pascal-case@3.1.2: + resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + + /pascalcase@0.1.1: + resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} + engines: {node: '>=0.10.0'} + requiresBuild: true + + /path-browserify@0.0.1: + resolution: {integrity: sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==} + dev: false + + /path-dirname@1.0.2: + resolution: {integrity: sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==} + dev: false + + /path-exists@3.0.0: + resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} + engines: {node: '>=4'} + dev: false + + /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'} + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + dev: false + + /path-to-regexp@0.1.12: + resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + dev: false + + /path-to-regexp@1.9.0: + resolution: {integrity: sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==} + dependencies: + isarray: 0.0.1 + dev: false + + /path-to-regexp@7.2.0: + resolution: {integrity: sha512-0W4AcUxPpFlcS8ql8ZEmFwaI0X5WshUVAFdXe3PBurrt18DK8bvSS+UKHvJUAfGILco/nTtc/E4LcPNfVysfwQ==} + engines: {node: '>=16'} + dev: false + + /path-to-regexp@8.2.0: + resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} + engines: {node: '>=16'} + dev: false + + /path-type@3.0.0: + resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==} + engines: {node: '>=4'} + dependencies: + pify: 3.0.0 + dev: false + + /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 + dependencies: + ieee754: 1.2.1 + resolve-protobuf-schema: 2.1.0 + dev: false + + /pbkdf2@3.1.2: + resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} + engines: {node: '>=0.12'} + 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 + dev: false + + /pdfast@0.2.0: + resolution: {integrity: sha512-cq6TTu6qKSFUHwEahi68k/kqN2mfepjkGrG9Un70cgdRRKLKY6Rf8P8uvP2NvZktaQZNF3YE7agEkLj0vGK9bA==} + dev: false + + /performance-now@2.1.0: + resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} + dev: false + + /picocolors@0.2.1: + resolution: {integrity: sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==} + dev: false + + /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'} + dev: false + + /pify@3.0.0: + resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} + engines: {node: '>=4'} + dev: false + + /pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + dev: false + + /pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + + /pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + + /pkg-up@3.1.0: + resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==} + engines: {node: '>=8'} + dependencies: + find-up: 3.0.0 + dev: false + + /please-upgrade-node@3.2.0: + resolution: {integrity: sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==} + dependencies: + semver-compare: 1.0.0 + dev: true + + /pmtiles@2.11.0: + resolution: {integrity: sha512-dU9SzzaqmCGpdEuTnIba6bDHT6j09ZJFIXxwGpvkiEnce3ZnBB1VKt6+EOmJGueriweaZLAMTUmKVElU2CBe0g==} + dependencies: + fflate: 0.8.2 + dev: false + + /polygon-clipping@0.15.7: + resolution: {integrity: sha512-nhfdr83ECBg6xtqOAJab1tbksbBAOMUltN60bU+llHVOL0e5Onm1WpAXXWXVB39L8AJFssoIhEVuy/S90MmotA==} + dependencies: + robust-predicates: 3.0.2 + splaytree: 3.1.2 + dev: false + + /polyline-miter-util@1.0.1: + resolution: {integrity: sha512-/3u91zz6mBerBZo6qnOJOTjv7EfPhKtsV028jMyj86YpzLRNmCCFfrX7IO9tCEQ2W4x45yc+vKOezjf7u2Nd6Q==} + dependencies: + gl-vec2: 1.3.0 + dev: false + + /polyline-normals@2.0.2: + resolution: {integrity: sha512-dpHrAi61ymhsB4N0XlNb3YpkKJeTFnXBXDWpeH8Ucstq0TUZrCN3YK4Jlgk8ofMWN25lhGC4wnxLMv+TUK8rig==} + dependencies: + polyline-miter-util: 1.0.1 + dev: false + + /posix-character-classes@0.1.1: + resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==} + engines: {node: '>=0.10.0'} + requiresBuild: true + + /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==} + dependencies: + postcss: 7.0.32 + postcss-selector-parser: 6.1.2 + dev: false + + /postcss-attribute-case-insensitive@5.0.2(postcss@8.5.3): + resolution: {integrity: sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + dev: false + + /postcss-browser-comments@4.0.0(browserslist@4.24.4)(postcss@8.5.3): + resolution: {integrity: sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==} + engines: {node: '>=8'} + peerDependencies: + browserslist: '>=4' + postcss: '>=8' + dependencies: + browserslist: 4.24.4 + postcss: 8.5.3 + dev: false + + /postcss-calc@8.2.4(postcss@8.5.3): + resolution: {integrity: sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==} + peerDependencies: + postcss: ^8.2.2 + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-clamp@4.1.0(postcss@8.5.3): + resolution: {integrity: sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==} + engines: {node: '>=7.6.0'} + peerDependencies: + postcss: ^8.4.6 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-color-functional-notation@2.0.1: + resolution: {integrity: sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + dev: false + + /postcss-color-functional-notation@4.2.4(postcss@8.5.3): + resolution: {integrity: sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-color-gray@5.0.0: + resolution: {integrity: sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw==} + engines: {node: '>=6.0.0'} + dependencies: + '@csstools/convert-colors': 1.4.0 + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + dev: false + + /postcss-color-hex-alpha@5.0.3: + resolution: {integrity: sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + dev: false + + /postcss-color-hex-alpha@8.0.4(postcss@8.5.3): + resolution: {integrity: sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-color-mod-function@3.0.3: + resolution: {integrity: sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ==} + engines: {node: '>=6.0.0'} + dependencies: + '@csstools/convert-colors': 1.4.0 + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + dev: false + + /postcss-color-rebeccapurple@4.0.1: + resolution: {integrity: sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + dev: false + + /postcss-color-rebeccapurple@7.1.1(postcss@8.5.3): + resolution: {integrity: sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-colormin@5.3.1(postcss@8.5.3): + resolution: {integrity: sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + browserslist: 4.24.4 + caniuse-api: 3.0.0 + colord: 2.9.3 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-convert-values@5.1.3(postcss@8.5.3): + resolution: {integrity: sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + browserslist: 4.24.4 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-custom-media@7.0.8: + resolution: {integrity: sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + dev: false + + /postcss-custom-media@8.0.2(postcss@8.5.3): + resolution: {integrity: sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.3 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-custom-properties@12.1.11(postcss@8.5.3): + resolution: {integrity: sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-custom-properties@8.0.11: + resolution: {integrity: sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + dev: false + + /postcss-custom-selectors@5.1.2: + resolution: {integrity: sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + postcss-selector-parser: 5.0.0 + dev: false + + /postcss-custom-selectors@6.0.3(postcss@8.5.3): + resolution: {integrity: sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.3 + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + dev: false + + /postcss-dir-pseudo-class@5.0.0: + resolution: {integrity: sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw==} + engines: {node: '>=4.0.0'} + dependencies: + postcss: 7.0.32 + postcss-selector-parser: 5.0.0 + dev: false + + /postcss-dir-pseudo-class@6.0.5(postcss@8.5.3): + resolution: {integrity: sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + dev: false + + /postcss-discard-comments@5.1.2(postcss@8.5.3): + resolution: {integrity: sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.5.3 + dev: false + + /postcss-discard-duplicates@5.1.0(postcss@8.5.3): + resolution: {integrity: sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.5.3 + dev: false + + /postcss-discard-empty@5.1.1(postcss@8.5.3): + resolution: {integrity: sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.5.3 + dev: false + + /postcss-discard-overridden@5.1.0(postcss@8.5.3): + resolution: {integrity: sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.5.3 + dev: false + + /postcss-double-position-gradients@1.0.0: + resolution: {integrity: sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + dev: false + + /postcss-double-position-gradients@3.1.2(postcss@8.5.3): + resolution: {integrity: sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + '@csstools/postcss-progressive-custom-properties': 1.3.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-env-function@2.0.2: + resolution: {integrity: sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + dev: false + + /postcss-env-function@4.0.6(postcss@8.5.3): + resolution: {integrity: sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-flexbugs-fixes@4.2.1: + resolution: {integrity: sha512-9SiofaZ9CWpQWxOwRh1b/r85KD5y7GgvsNt1056k6OYLvWUun0czCvogfJgylC22uJTwW1KzY3Gz65NZRlvoiQ==} + dependencies: + postcss: 7.0.32 + dev: false + + /postcss-flexbugs-fixes@5.0.2(postcss@8.5.3): + resolution: {integrity: sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==} + peerDependencies: + postcss: ^8.1.4 + dependencies: + postcss: 8.5.3 + dev: false + + /postcss-focus-visible@4.0.0: + resolution: {integrity: sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + dev: false + + /postcss-focus-visible@6.0.4(postcss@8.5.3): + resolution: {integrity: sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + dev: false + + /postcss-focus-within@3.0.0: + resolution: {integrity: sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + dev: false + + /postcss-focus-within@5.0.4(postcss@8.5.3): + resolution: {integrity: sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + dev: false + + /postcss-font-variant@4.0.1: + resolution: {integrity: sha512-I3ADQSTNtLTTd8uxZhtSOrTCQ9G4qUVKPjHiDk0bV75QSxXjVWiJVJ2VLdspGUi9fbW9BcjKJoRvxAH1pckqmA==} + dependencies: + postcss: 7.0.32 + dev: false + + /postcss-font-variant@5.0.0(postcss@8.5.3): + resolution: {integrity: sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==} + peerDependencies: + postcss: ^8.1.0 + dependencies: + postcss: 8.5.3 + dev: false + + /postcss-gap-properties@2.0.0: + resolution: {integrity: sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + dev: false + + /postcss-gap-properties@3.0.5(postcss@8.5.3): + resolution: {integrity: sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + dev: false + + /postcss-image-set-function@3.0.1: + resolution: {integrity: sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + dev: false + + /postcss-image-set-function@4.0.7(postcss@8.5.3): + resolution: {integrity: sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-import@15.1.0(postcss@8.5.3): + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.10 + dev: false + + /postcss-initial@3.0.4: + resolution: {integrity: sha512-3RLn6DIpMsK1l5UUy9jxQvoDeUN4gP939tDcKUHD/kM8SGSKbFAnvkpFpj3Bhtz3HGk1jWY5ZNWX6mPta5M9fg==} + dependencies: + postcss: 7.0.32 + dev: false + + /postcss-initial@4.0.1(postcss@8.5.3): + resolution: {integrity: sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==} + peerDependencies: + postcss: ^8.0.0 + dependencies: + postcss: 8.5.3 + dev: false + + /postcss-js@4.0.1(postcss@8.5.3): + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + dependencies: + camelcase-css: 2.0.1 + postcss: 8.5.3 + dev: false + + /postcss-lab-function@2.0.1: + resolution: {integrity: sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg==} + engines: {node: '>=6.0.0'} + dependencies: + '@csstools/convert-colors': 1.4.0 + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + dev: false + + /postcss-lab-function@4.2.1(postcss@8.5.3): + resolution: {integrity: sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + '@csstools/postcss-progressive-custom-properties': 1.3.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-less@6.0.0(postcss@8.5.3): + resolution: {integrity: sha512-FPX16mQLyEjLzEuuJtxA8X3ejDLNGGEG503d2YGZR5Ask1SpDN8KmZUMpzCvyalWRywAn1n1VOA5dcqfCLo5rg==} + engines: {node: '>=12'} + peerDependencies: + postcss: ^8.3.5 + dependencies: + postcss: 8.5.3 + dev: true + + /postcss-load-config@2.1.2: + resolution: {integrity: sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw==} + engines: {node: '>= 4'} + dependencies: + cosmiconfig: 5.2.1 + import-cwd: 2.1.0 + dev: false + + /postcss-load-config@4.0.2(postcss@8.5.3): + 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 + dependencies: + lilconfig: 3.1.3 + postcss: 8.5.3 + yaml: 2.7.0 + dev: false + + /postcss-loader@3.0.0: + resolution: {integrity: sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==} + engines: {node: '>= 6'} + dependencies: + loader-utils: 1.4.2 + postcss: 7.0.32 + postcss-load-config: 2.1.2 + schema-utils: 1.0.0 + dev: false + + /postcss-loader@6.2.1(postcss@8.5.3)(webpack@5.98.0): + 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 + dependencies: + cosmiconfig: 7.1.0 + klona: 2.0.6 + postcss: 8.5.3 + semver: 7.7.1 + webpack: 5.98.0 + dev: false + + /postcss-logical@3.0.0: + resolution: {integrity: sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + dev: false + + /postcss-logical@5.0.4(postcss@8.5.3): + resolution: {integrity: sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss: 8.5.3 + dev: false + + /postcss-media-minmax@4.0.0: + resolution: {integrity: sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + dev: false + + /postcss-media-minmax@5.0.0(postcss@8.5.3): + resolution: {integrity: sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + postcss: ^8.1.0 + dependencies: + postcss: 8.5.3 + dev: false + + /postcss-merge-longhand@5.1.7(postcss@8.5.3): + resolution: {integrity: sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + stylehacks: 5.1.1(postcss@8.5.3) + dev: false + + /postcss-merge-rules@5.1.4(postcss@8.5.3): + resolution: {integrity: sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + 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 + dev: false + + /postcss-minify-font-values@5.1.0(postcss@8.5.3): + resolution: {integrity: sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-minify-gradients@5.1.1(postcss@8.5.3): + resolution: {integrity: sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + colord: 2.9.3 + cssnano-utils: 3.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-minify-params@5.1.4(postcss@8.5.3): + resolution: {integrity: sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + browserslist: 4.24.4 + cssnano-utils: 3.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-minify-selectors@5.2.1(postcss@8.5.3): + resolution: {integrity: sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + dev: false + + /postcss-modules-extract-imports@3.1.0(postcss@8.5.3): + resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + postcss: 8.5.3 + dev: false + + /postcss-modules-local-by-default@4.2.0(postcss@8.5.3): + resolution: {integrity: sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + 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 + dev: false + + /postcss-modules-scope@3.2.1(postcss@8.5.3): + resolution: {integrity: sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 7.1.0 + dev: false + + /postcss-modules-values@4.0.0(postcss@8.5.3): + resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + icss-utils: 5.1.0(postcss@8.5.3) + postcss: 8.5.3 + dev: false + + /postcss-nested@6.2.0(postcss@8.5.3): + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + dev: false + + /postcss-nesting@10.2.0(postcss@8.5.3): + resolution: {integrity: sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + '@csstools/selector-specificity': 2.2.0(postcss-selector-parser@6.1.2) + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + dev: false + + /postcss-nesting@7.0.1: + resolution: {integrity: sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + dev: false + + /postcss-normalize-charset@5.1.0(postcss@8.5.3): + resolution: {integrity: sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.5.3 + dev: false + + /postcss-normalize-display-values@5.1.0(postcss@8.5.3): + resolution: {integrity: sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-normalize-positions@5.1.1(postcss@8.5.3): + resolution: {integrity: sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-normalize-repeat-style@5.1.1(postcss@8.5.3): + resolution: {integrity: sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-normalize-string@5.1.0(postcss@8.5.3): + resolution: {integrity: sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-normalize-timing-functions@5.1.0(postcss@8.5.3): + resolution: {integrity: sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-normalize-unicode@5.1.1(postcss@8.5.3): + resolution: {integrity: sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + browserslist: 4.24.4 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-normalize-url@5.1.0(postcss@8.5.3): + resolution: {integrity: sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + normalize-url: 6.1.0 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-normalize-whitespace@5.1.1(postcss@8.5.3): + resolution: {integrity: sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-normalize@10.0.1(browserslist@4.24.4)(postcss@8.5.3): + resolution: {integrity: sha512-+5w18/rDev5mqERcG3W5GZNMJa1eoYYNGo8gB7tEwaos0ajk3ZXAI4mHGcNT47NE+ZnZD1pEpUOFLvltIwmeJA==} + engines: {node: '>= 12'} + peerDependencies: + browserslist: '>= 4' + postcss: '>= 8' + 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 + dev: false + + /postcss-opacity-percentage@1.1.3(postcss@8.5.3): + resolution: {integrity: sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + dev: false + + /postcss-ordered-values@5.1.3(postcss@8.5.3): + resolution: {integrity: sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + cssnano-utils: 3.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-overflow-shorthand@2.0.0: + resolution: {integrity: sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + dev: false + + /postcss-overflow-shorthand@3.0.4(postcss@8.5.3): + resolution: {integrity: sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-page-break@2.0.0: + resolution: {integrity: sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ==} + dependencies: + postcss: 7.0.32 + dev: false + + /postcss-page-break@3.0.4(postcss@8.5.3): + resolution: {integrity: sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==} + peerDependencies: + postcss: ^8 + dependencies: + postcss: 8.5.3 + dev: false + + /postcss-place@4.0.1: + resolution: {integrity: sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + postcss-values-parser: 2.0.1 + dev: false + + /postcss-place@7.0.5(postcss@8.5.3): + resolution: {integrity: sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-preset-env@6.7.0: + resolution: {integrity: sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg==} + engines: {node: '>=6.0.0'} + dependencies: + autoprefixer: 9.8.8 + browserslist: 4.24.4 + caniuse-lite: 1.0.30001705 + 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 + dev: false + + /postcss-preset-env@7.8.3(postcss@8.5.3): + resolution: {integrity: sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + 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 + dev: false + + /postcss-pseudo-class-any-link@6.0.0: + resolution: {integrity: sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + postcss-selector-parser: 5.0.0 + dev: false + + /postcss-pseudo-class-any-link@7.1.6(postcss@8.5.3): + resolution: {integrity: sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + dev: false + + /postcss-reduce-initial@5.1.2(postcss@8.5.3): + resolution: {integrity: sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + browserslist: 4.24.4 + caniuse-api: 3.0.0 + postcss: 8.5.3 + dev: false + + /postcss-reduce-transforms@5.1.0(postcss@8.5.3): + resolution: {integrity: sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + dev: false + + /postcss-replace-overflow-wrap@3.0.0: + resolution: {integrity: sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw==} + dependencies: + postcss: 7.0.32 + dev: false + + /postcss-replace-overflow-wrap@4.0.0(postcss@8.5.3): + resolution: {integrity: sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==} + peerDependencies: + postcss: ^8.0.3 + dependencies: + postcss: 8.5.3 + dev: false + + /postcss-safe-parser@4.0.2: + resolution: {integrity: sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.32 + dev: false + + /postcss-selector-matches@4.0.0: + resolution: {integrity: sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww==} + dependencies: + balanced-match: 1.0.2 + postcss: 7.0.32 + dev: false + + /postcss-selector-not@4.0.1: + resolution: {integrity: sha512-YolvBgInEK5/79C+bdFMyzqTg6pkYqDbzZIST/PDMqa/o3qtXenD05apBG2jLgT0/BQ77d4U2UK12jWpilqMAQ==} + dependencies: + balanced-match: 1.0.2 + postcss: 7.0.32 + dev: false + + /postcss-selector-not@6.0.1(postcss@8.5.3): + resolution: {integrity: sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + dev: false + + /postcss-selector-parser@5.0.0: + resolution: {integrity: sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==} + engines: {node: '>=4'} + dependencies: + cssesc: 2.0.0 + indexes-of: 1.0.1 + uniq: 1.0.1 + dev: false + + /postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: false + + /postcss-selector-parser@7.1.0: + resolution: {integrity: sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: false + + /postcss-strip-inline-comments@0.1.5: + resolution: {integrity: sha512-4EW5hYyv2syFyIBahkXGhZppp9zb5wD5NJ2R65WjXnB5q8T0g4VyLBTevU6ZpxtaN4HkoYZhV03DGUf5Ptd4FA==} + dependencies: + postcss: 5.2.18 + dev: true + + /postcss-svgo@5.1.0(postcss@8.5.3): + resolution: {integrity: sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + svgo: 2.8.0 + dev: false + + /postcss-unique-selectors@5.1.1(postcss@8.5.3): + resolution: {integrity: sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + dev: false + + /postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + dev: false + + /postcss-values-parser@2.0.1: + resolution: {integrity: sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==} + engines: {node: '>=6.14.4'} + dependencies: + flatten: 1.0.3 + indexes-of: 1.0.1 + uniq: 1.0.1 + dev: false + + /postcss@5.2.18: + resolution: {integrity: sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==} + engines: {node: '>=0.12'} + dependencies: + chalk: 1.1.3 + js-base64: 2.6.4 + source-map: 0.5.7 + supports-color: 3.2.3 + dev: true + + /postcss@7.0.32: + resolution: {integrity: sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==} + engines: {node: '>=6.0.0'} + dependencies: + chalk: 2.4.2 + source-map: 0.6.1 + supports-color: 6.1.0 + dev: false + + /postcss@7.0.39: + resolution: {integrity: sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==} + engines: {node: '>=6.0.0'} + dependencies: + picocolors: 0.2.1 + source-map: 0.6.1 + dev: false + + /postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.10 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + /potpack@1.0.2: + resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==} + dev: false + + /potpack@2.0.0: + resolution: {integrity: sha512-Q+/tYsFU9r7xoOJ+y/ZTtdVQwTWfzjbiXBDMM/JKUux3+QPP02iUuIoeBQ+Ot6oEDlC+/PGjB/5A3K7KKb7hcw==} + dev: false + + /prelude-ls@1.1.2: + resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} + engines: {node: '>= 0.8.0'} + dev: false + + /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'} + dev: false + + /preserve@0.2.0: + resolution: {integrity: sha512-s/46sYeylUfHNjI+sA/78FAHlmIuKqI9wNnzEOGehAlUUYeObv5C2mOinXBjyUyWmJ2SfcS2/ydApH4hTF4WXQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dev: true + optional: true + + /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'} + dev: false + + /pretty-error@2.1.2: + resolution: {integrity: sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==} + dependencies: + lodash: 4.17.21 + renderkid: 2.0.7 + dev: true + + /pretty-error@4.0.0: + resolution: {integrity: sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==} + dependencies: + lodash: 4.17.21 + renderkid: 3.0.0 + dev: false + + /pretty-format@26.6.2: + resolution: {integrity: sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==} + engines: {node: '>= 10'} + 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: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + dev: false + + /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} + dependencies: + '@jest/schemas': 28.1.3 + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 18.3.1 + dev: false + + /printj@1.1.2: + resolution: {integrity: sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==} + engines: {node: '>=0.8'} + hasBin: true + dev: false + + /prism-react-renderer@1.3.5: + resolution: {integrity: sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg==} + peerDependencies: + react: '>=0.14.9' + dev: false + + /prism-react@1.0.2: + resolution: {integrity: sha512-OoBo0kX55Fi+M4oGuYQ+AkU4/xSvB357mLXbYGP3j4oi4RtsdY5Rn3ViJ6gGU8IkZKs5cnmF7IteWWwUFyVd7Q==} + peerDependencies: + react: ^15.0.2 || ^0.14.8 + dependencies: + recompose: 0.22.0 + dev: false + + /prism-redux@1.0.2: + resolution: {integrity: sha512-e1DGRK+V/dxL6n6M25Py1QrAQLHkeueXyNxDTURT1y+KAMwSJdnlNvGU3ZLY2RIaA+ZdFTc9oTvTSR+mS88VyQ==} + dev: false + + /prism@4.1.2: + resolution: {integrity: sha512-SsqrfKkYKYEYz/7RRET2KVZd9O22Rnj3331Al06ClLMycKWoM+MpfrjQrKuHGoIJ9IOy+k27kPEFnqPoAeFZpA==} + dependencies: + prism-react: 1.0.2 + prism-redux: 1.0.2 + transitivePeerDependencies: + - react + dev: false + + /private@0.1.8: + resolution: {integrity: sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==} + engines: {node: '>= 0.6'} + dev: true + + /probe.gl@3.6.0: + resolution: {integrity: sha512-19JydJWI7+DtR4feV+pu4Mn1I5TAc0xojuxVgZdXIyfmTLfUaFnk4OloWK1bKbPtkgGKLr2lnbnCXmpZEcEp9g==} + dependencies: + '@babel/runtime': 7.26.10 + '@probe.gl/env': 3.6.0 + '@probe.gl/log': 3.6.0 + '@probe.gl/stats': 3.6.0 + dev: false + + /process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + requiresBuild: true + + /process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + dev: false + + /promise@7.3.1: + resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==} + dependencies: + asap: 2.0.6 + dev: false + + /promise@8.3.0: + resolution: {integrity: sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==} + dependencies: + asap: 2.0.6 + dev: false + + /prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + /prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + dev: false + + /protocol-buffers-schema@3.6.0: + resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==} + dev: false + + /proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + dev: false + + /pseudomap@1.0.2: + resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + dev: true + + /psl@1.15.0: + resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} + dependencies: + punycode: 2.3.1 + + /public-encrypt@4.0.3: + resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} + dependencies: + bn.js: 4.12.1 + browserify-rsa: 4.1.1 + create-hash: 1.2.0 + parse-asn1: 5.1.7 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + dev: false + + /pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + + /punycode@1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + dev: false + + /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==} + dev: false + + /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) + dev: false + + /qs@6.13.0: + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.1.0 + dev: false + + /qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.1.0 + dev: false + + /query-string@4.3.4: + resolution: {integrity: sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==} + engines: {node: '>=0.10.0'} + dependencies: + object-assign: 4.1.1 + strict-uri-encode: 1.1.0 + dev: false + + /query-string@6.14.1: + resolution: {integrity: sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==} + engines: {node: '>=6'} + dependencies: + decode-uri-component: 0.2.2 + filter-obj: 1.1.0 + split-on-first: 1.1.0 + strict-uri-encode: 2.0.0 + dev: false + + /query-string@8.2.0: + resolution: {integrity: sha512-tUZIw8J0CawM5wyGBiDOAp7ObdRQh4uBor/fUR9ZjmbZVvw95OD9If4w3MQxr99rg0DJZ/9CIORcpEqU5hQG7g==} + engines: {node: '>=14.16'} + dependencies: + decode-uri-component: 0.4.1 + filter-obj: 5.1.0 + split-on-first: 3.0.0 + dev: false + + /query-string@9.1.1: + resolution: {integrity: sha512-MWkCOVIcJP9QSKU52Ngow6bsAWAPlPK2MludXvcrS2bGZSl+T1qX9MZvRIkqUIkGLJquMJHWfsT6eRqUpp4aWg==} + engines: {node: '>=18'} + dependencies: + decode-uri-component: 0.4.1 + filter-obj: 5.1.0 + split-on-first: 3.0.0 + dev: false + + /querystring-es3@0.2.1: + resolution: {integrity: sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==} + engines: {node: '>=0.4.x'} + dev: false + + /querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: false + + /quickselect@2.0.0: + resolution: {integrity: sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==} + dev: false + + /raf-schd@4.0.3: + resolution: {integrity: sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==} + dev: false + + /raf@3.4.1: + resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==} + dependencies: + performance-now: 2.1.0 + dev: false + + /ramda@0.27.2: + resolution: {integrity: sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==} + dev: false + + /randexp@0.5.3: + resolution: {integrity: sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w==} + engines: {node: '>=4'} + dependencies: + drange: 1.1.1 + ret: 0.2.2 + dev: false + + /randomatic@3.1.1: + resolution: {integrity: sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==} + engines: {node: '>= 0.10.0'} + requiresBuild: true + dependencies: + is-number: 4.0.0 + kind-of: 6.0.3 + math-random: 1.0.4 + dev: true + optional: true + + /randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /randomfill@1.0.4: + resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} + dependencies: + randombytes: 2.1.0 + safe-buffer: 5.2.1 + dev: false + + /range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + dev: false + + /raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: false + + /rc-align@2.4.5: + resolution: {integrity: sha512-nv9wYUYdfyfK+qskThf4BQUSIadeI/dCsfaMZfNEoxm9HwOIioQ+LyqmMK6jWHAZQgOzMLaqawhuBXlF63vgjw==} + dependencies: + babel-runtime: 6.26.0 + dom-align: 1.12.4 + prop-types: 15.8.1 + rc-util: 4.21.1 + dev: false + + /rc-align@4.0.15: + resolution: {integrity: sha512-wqJtVH60pka/nOX7/IspElA8gjPNQKIx/ZqJ6heATCkXpe1Zg4cPVrMD2vC96wjsFFL8WsmhPbx9tdMo1qqlIA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + dom-align: 1.12.4 + rc-util: 5.44.4 + resize-observer-polyfill: 1.5.1 + dev: false + + /rc-animate@2.11.1: + resolution: {integrity: sha512-1NyuCGFJG/0Y+9RKh5y/i/AalUCA51opyyS/jO2seELpgymZm2u9QV3xwODwEuzkmeQ1BDPxMLmYLcTJedPlkQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.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-lifecycles-compat: 3.0.4 + dev: false + + /rc-cascader@3.33.1: + resolution: {integrity: sha512-Kyl4EJ7ZfCBuidmZVieegcbFw0RcU5bHHSbtEdmuLYd0fYHCAiYKZ6zon7fWAVyC6rWWOOib0XKdTSf7ElC9rg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-select: 14.16.6 + rc-tree: 5.13.1 + rc-util: 5.44.4 + dev: false + + /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' + dependencies: + '@babel/runtime': 7.26.10 + array-tree-filter: 2.1.0 + classnames: 2.5.1 + rc-select: 14.1.18 + rc-tree: 5.7.12 + rc-util: 5.44.4 + dev: false + + /rc-checkbox@2.0.3: + resolution: {integrity: sha512-sSDV5AcxK5CxBTyUNj9pb0zfhdgLLsWKHwJG18ikeGoIwklcxXvIF6cI/KGVbPLFDa8mPS5WLOlLRqbq/1/ouw==} + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + prop-types: 15.8.1 + rc-util: 4.21.1 + dev: false + + /rc-checkbox@3.0.1: + resolution: {integrity: sha512-k7nxDWxYF+jDI0ZcCvuvj71xONmWRVe5+1MKcERRR9MRyP3tZ69b+yUCSXXh+sik4/Hc9P5wHr2nnUoGS2zBjA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /rc-checkbox@3.5.0: + resolution: {integrity: sha512-aOAQc3E98HteIIsSqm6Xk2FPKIER6+5vyEFMZfo73TqM+VVAIqOkHoPjgKLqSNtVLWScoaM7vY2ZrGEheI79yg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /rc-collapse@1.9.3: + resolution: {integrity: sha512-8cG+FzudmgFCC9zRGKXJZA36zoI9Dmyjp6UDi8N80sXUch0JOpsZDxgcFzw4HPpPpK/dARtTilEe9zyuspnW0w==} + dependencies: + classnames: 2.5.1 + css-animation: 1.6.1 + prop-types: 15.8.1 + rc-animate: 2.11.1 + transitivePeerDependencies: + - react + - react-dom + dev: false + + /rc-collapse@3.4.2: + resolution: {integrity: sha512-jpTwLgJzkhAgp2Wpi3xmbTbbYExg6fkptL67Uu5LCRVEj6wqmy0DHTjjeynsjOLsppHGHu41t1ELntZ0lEvS/Q==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-motion: 2.9.5 + rc-util: 5.44.4 + shallowequal: 1.1.0 + dev: false + + /rc-collapse@3.9.0: + resolution: {integrity: sha512-swDdz4QZ4dFTo4RAUMLL50qP0EY62N2kvmk2We5xYdRwcRn8WcYtuetCJpwpaCbUfUt5+huLpVxhvmnK+PHrkA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-motion: 2.9.5 + rc-util: 5.44.4 + dev: false + + /rc-dialog@9.0.4: + resolution: {integrity: sha512-pmnPRZKd9CGzGgf4a1ysBvMhxm8Afx5fF6M7AzLtJ0qh8X1bshurDlqnK4MBNAB4hAeAMMbz6Ytb1rkGMvKFbQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + '@rc-component/portal': 1.1.2 + classnames: 2.5.1 + rc-motion: 2.9.5 + rc-util: 5.44.4 + dev: false + + /rc-dialog@9.6.0: + resolution: {integrity: sha512-ApoVi9Z8PaCQg6FsUzS8yvBEQy0ZL2PkuvAgrmohPkN3okps5WZ5WQWPc1RNuiOKaAYv8B97ACdsFU5LizzCqg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + '@rc-component/portal': 1.1.2 + classnames: 2.5.1 + rc-motion: 2.9.5 + rc-util: 5.44.4 + dev: false + + /rc-drawer@6.3.0: + resolution: {integrity: sha512-uBZVb3xTAR+dBV53d/bUhTctCw3pwcwJoM7g5aX+7vgwt2zzVzoJ6aqFjYJpBlZ9zp0dVYN8fV+hykFE7c4lig==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + '@rc-component/portal': 1.1.2 + classnames: 2.5.1 + rc-motion: 2.9.5 + rc-util: 5.44.4 + dev: false + + /rc-drawer@7.2.0: + resolution: {integrity: sha512-9lOQ7kBekEJRdEpScHvtmEtXnAsy+NGDXiRWc2ZVC7QXAazNVbeT4EraQKYwCME8BJLa8Bxqxvs5swwyOepRwg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + '@rc-component/portal': 1.1.2 + classnames: 2.5.1 + rc-motion: 2.9.5 + rc-util: 5.44.4 + dev: false + + /rc-dropdown@3.6.2: + resolution: {integrity: sha512-Wsw7GkVbUXADEs8FPL0v8gd+3mWQiydPFXBlr2imMScQaf8hh79pG9KrBc1DwK+nqHmYOpQfK2gn6jG2AQw9Pw==} + peerDependencies: + react: '>=16.11.0' + react-dom: '>=16.11.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-trigger: 5.3.4 + rc-util: 5.44.4 + dev: false + + /rc-dropdown@4.0.1: + resolution: {integrity: sha512-OdpXuOcme1rm45cR0Jzgfl1otzmU4vuBVb+etXM8vcaULGokAKVpKlw8p6xzspG7jGd/XxShvq+N3VNEfk/l5g==} + peerDependencies: + react: '>=16.11.0' + react-dom: '>=16.11.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-trigger: 5.3.4 + rc-util: 5.44.4 + dev: false + + /rc-dropdown@4.2.1: + resolution: {integrity: sha512-YDAlXsPv3I1n42dv1JpdM7wJ+gSUBfeyPK59ZpBD9jQhK9jVuxpjj3NmWQHOBceA1zEPVX84T2wbdb2SD0UjmA==} + peerDependencies: + react: '>=16.11.0' + react-dom: '>=16.11.0' + dependencies: + '@babel/runtime': 7.26.10 + '@rc-component/trigger': 2.2.6 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /rc-editor-core@0.8.10: + resolution: {integrity: sha512-T3aHpeMCIYA1sdAI7ynHHjXy5fqp83uPlD68ovZ0oClTSc3tbHmyCxXlA+Ti4YgmcpCYv7avF6a+TIbAka53kw==} + peerDependencies: + react: '>=15.0.0' + react-dom: '>=15.0.0' + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + draft-js: 0.10.5 + immutable: 3.7.6 + lodash: 4.17.21 + prop-types: 15.8.1 + setimmediate: 1.0.5 + dev: false + + /rc-editor-mention@1.1.13: + resolution: {integrity: sha512-3AOmGir91Fi2ogfRRaXLtqlNuIwQpvla7oUnGHS1+3eo7b+fUp5IlKcagqtwUBB5oDNofoySXkLBxzWvSYNp/Q==} + peerDependencies: + react: '>=15.x' + react-dom: '>=15.x' + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + dom-scroll-into-view: 1.2.1 + draft-js: 0.10.5 + immutable: 3.7.6 + prop-types: 15.8.1 + rc-animate: 2.11.1 + rc-editor-core: 0.8.10 + dev: false + + /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' + dependencies: + '@babel/runtime': 7.26.10 + async-validator: 4.2.5 + rc-util: 5.44.4 + dev: false + + /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' + dependencies: + '@babel/runtime': 7.26.10 + async-validator: 4.2.5 + rc-util: 5.44.4 + dev: false + + /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' + dependencies: + '@babel/runtime': 7.26.10 + '@rc-component/async-validator': 5.0.4 + rc-util: 5.44.4 + dev: false + + /rc-form@2.4.12: + resolution: {integrity: sha512-sHfyWRrnjCHkeCYfYAGop2GQBUC6CKMPcJF9h/gL/vTmZB/RN6fNOGKjXrXjFbwFwKXUWBoPtIDDDmXQW9xNdw==} + peerDependencies: + prop-types: ^15.0 + 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 + rc-util: 4.21.1 + react-is: 16.13.1 + warning: 4.0.3 + dev: false + + /rc-gesture@0.0.22: + resolution: {integrity: sha512-6G6qrCE0MUTXyjh/powj91XkjRjoFL4HiJLPU5lALXHvGX+/efcUjGYUrHrrw0mwQdmrmg4POqnY/bibns+G3g==} + dependencies: + babel-runtime: 6.26.0 + dev: false + + /rc-image@5.13.0: + resolution: {integrity: sha512-iZTOmw5eWo2+gcrJMMcnd7SsxVHl3w5xlyCgsULUdJhJbnuI8i/AL0tVOsE7aLn9VfOh1qgDT3mC2G75/c7mqg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + '@rc-component/portal': 1.1.2 + classnames: 2.5.1 + rc-dialog: 9.0.4 + rc-motion: 2.9.5 + rc-util: 5.44.4 + dev: false + + /rc-image@7.11.1: + resolution: {integrity: sha512-XuoWx4KUXg7hNy5mRTy1i8c8p3K8boWg6UajbHpDXS5AlRVucNfTi5YxTtPBTBzegxAZpvuLfh3emXFt6ybUdA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + '@rc-component/portal': 1.1.2 + classnames: 2.5.1 + rc-dialog: 9.6.0 + rc-motion: 2.9.5 + rc-util: 5.44.4 + dev: false + + /rc-input-number@7.3.11: + resolution: {integrity: sha512-aMWPEjFeles6PQnMqP5eWpxzsvHm9rh1jQOWXExUEIxhX62Fyl/ptifLHOn17+waDG1T/YUb6flfJbvwRhHrbA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /rc-input-number@9.4.0: + resolution: {integrity: sha512-Tiy4DcXcFXAf9wDhN8aUAyMeCLHJUHA/VA/t7Hj8ZEx5ETvxG7MArDOSE6psbiSCo+vJPm4E3fGN710ITVn6GA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + '@rc-component/mini-decimal': 1.1.0 + classnames: 2.5.1 + rc-input: 1.7.3 + rc-util: 5.44.4 + dev: false + + /rc-input@0.1.4: + resolution: {integrity: sha512-FqDdNz+fV2dKNgfXzcSLKvC+jEs1709t7nD+WdfjrdSaOcefpgc7BUJYadc3usaING+b7ediMTfKxuJBsEFbXA==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /rc-input@1.7.3: + resolution: {integrity: sha512-A5w4egJq8+4JzlQ55FfQjDnPvOaAbzwC3VLOAdOytyek3TboSOP9qxN+Gifup+shVXfvecBLBbWBpWxmk02SWQ==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /rc-mentions@1.13.1: + resolution: {integrity: sha512-FCkaWw6JQygtOz0+Vxz/M/NWqrWHB9LwqlY2RtcuFqWJNFK9njijOOzTSsBGANliGufVUzx/xuPHmZPBV0+Hgw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-menu: 9.8.4 + rc-textarea: 0.4.7 + rc-trigger: 5.3.4 + rc-util: 5.44.4 + dev: false + + /rc-mentions@2.19.1: + resolution: {integrity: sha512-KK3bAc/bPFI993J3necmaMXD2reZTzytZdlTvkeBbp50IGH1BDPDvxLdHDUrpQx2b2TGaVJsn+86BvYa03kGqA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + '@rc-component/trigger': 2.2.6 + classnames: 2.5.1 + rc-input: 1.7.3 + rc-menu: 9.16.1 + rc-textarea: 1.9.0 + rc-util: 5.44.4 + dev: false + + /rc-menu@9.16.1: + resolution: {integrity: sha512-ghHx6/6Dvp+fw8CJhDUHFHDJ84hJE3BXNCzSgLdmNiFErWSOaZNsihDAsKq9ByTALo/xkNIwtDFGIl6r+RPXBg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + '@rc-component/trigger': 2.2.6 + classnames: 2.5.1 + rc-motion: 2.9.5 + rc-overflow: 1.4.1 + rc-util: 5.44.4 + dev: false + + /rc-menu@9.8.4: + resolution: {integrity: sha512-lmw2j8I2fhdIzHmC9ajfImfckt0WDb2KVJJBBRIsxPEw2kGkEfjLMUoB1NgiNT/Q5cC8PdjGOGQjHJIJMwyNMw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-motion: 2.9.5 + rc-overflow: 1.4.1 + rc-trigger: 5.3.4 + rc-util: 5.44.4 + dev: false + + /rc-motion@2.9.5: + resolution: {integrity: sha512-w+XTUrfh7ArbYEd2582uDrEhmBHwK1ZENJiSJVb7uRxdE7qJSYjbO2eksRXmndqyKqKoYPc9ClpPh5242mV1vA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /rc-notification@4.6.1: + resolution: {integrity: sha512-NSmFYwrrdY3+un1GvDAJQw62Xi9LNMSsoQyo95tuaYrcad5Bn9gJUL8AREufRxSQAQnr64u3LtP3EUyLYT6bhw==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-motion: 2.9.5 + rc-util: 5.44.4 + dev: false + + /rc-notification@5.6.3: + resolution: {integrity: sha512-42szwnn8VYQoT6GnjO00i1iwqV9D1TTMvxObWsuLwgl0TsOokzhkYiufdtQBsJMFjJravS1hfDKVMHLKLcPE4g==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-motion: 2.9.5 + rc-util: 5.44.4 + dev: false + + /rc-overflow@1.4.1: + resolution: {integrity: sha512-3MoPQQPV1uKyOMVNd6SZfONi+f3st0r8PksexIdBTeIYbMX0Jr+k7pHEDvsXtR4BpCv90/Pv2MovVNhktKrwvw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-resize-observer: 1.4.3 + rc-util: 5.44.4 + dev: false + + /rc-pagination@3.2.0: + resolution: {integrity: sha512-5tIXjB670WwwcAJzAqp2J+cOBS9W3cH/WU1EiYwXljuZ4vtZXKlY2Idq8FZrnYBz8KhN3vwPo9CoV/SJS6SL1w==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + dev: false + + /rc-pagination@5.1.0: + resolution: {integrity: sha512-8416Yip/+eclTFdHXLKTxZvn70duYVGTvUUWbckCCZoIl3jagqke3GLsFrMs0bsQBikiYpZLD9206Ej4SOdOXQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /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' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + date-fns: 2.30.0 + dayjs: 1.11.13 + moment: 2.30.1 + rc-trigger: 5.3.4 + rc-util: 5.44.4 + shallowequal: 1.1.0 + dev: false + + /rc-picker@4.11.3(dayjs@1.11.13)(moment@2.30.1): + 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 + dependencies: + '@babel/runtime': 7.26.10 + '@rc-component/trigger': 2.2.6 + classnames: 2.5.1 + dayjs: 1.11.13 + moment: 2.30.1 + rc-overflow: 1.4.1 + rc-resize-observer: 1.4.3 + rc-util: 5.44.4 + dev: false + + /rc-progress@3.4.2: + resolution: {integrity: sha512-iAGhwWU+tsayP+Jkl9T4+6rHeQTG9kDz8JAHZk4XtQOcYN5fj9H34NXNEdRdZx94VUDHMqCb1yOIvi8eJRh67w==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /rc-progress@4.0.0: + resolution: {integrity: sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /rc-rate@2.13.1: + resolution: {integrity: sha512-QUhQ9ivQ8Gy7mtMZPAjLbxBt5y9GRp65VcUyGUMF3N3fhiftivPHdpuDIaWIMOTEprAjZPC08bls1dQB+I1F2Q==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /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' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /rc-resize-observer@0.2.6: + resolution: {integrity: sha512-YX6nYnd6fk7zbuvT6oSDMKiZjyngjHoy+fz+vL3Tez38d/G5iGdaDJa2yE7345G6sc4Mm1IGRUIwclvltddhmA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + resize-observer-polyfill: 1.5.1 + dev: false + + /rc-resize-observer@1.4.3: + resolution: {integrity: sha512-YZLjUbyIWox8E9i9C3Tm7ia+W7euPItNWSPX5sCcQTYbnwDb5uNpnLHQCG1f22oZWUhLw4Mv2tFmeWe68CDQRQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + resize-observer-polyfill: 1.5.1 + dev: false + + /rc-segmented@2.3.0: + resolution: {integrity: sha512-I3FtM5Smua/ESXutFfb8gJ8ZPcvFR+qUgeeGFQHBOvRiRKyAk4aBE5nfqrxXx+h8/vn60DQjOt6i4RNtrbOobg==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-motion: 2.9.5 + rc-util: 5.44.4 + dev: false + + /rc-segmented@2.7.0: + resolution: {integrity: sha512-liijAjXz+KnTRVnxxXG2sYDGd6iLL7VpGGdR8gwoxAXy2KglviKCxLWZdjKYJzYzGSUwKDSTdYk8brj54Bn5BA==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-motion: 2.9.5 + rc-util: 5.44.4 + dev: false + + /rc-select@14.1.18: + resolution: {integrity: sha512-4JgY3oG2Yz68ECMUSCON7mtxuJvCSj+LJpHEg/AONaaVBxIIrmI/ZTuMJkyojall/X50YdBe5oMKqHHPNiPzEg==} + engines: {node: '>=8.x'} + peerDependencies: + react: '*' + react-dom: '*' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-motion: 2.9.5 + rc-overflow: 1.4.1 + rc-trigger: 5.3.4 + rc-util: 5.44.4 + rc-virtual-list: 3.18.4 + dev: false + + /rc-select@14.16.6: + resolution: {integrity: sha512-YPMtRPqfZWOm2XGTbx5/YVr1HT0vn//8QS77At0Gjb3Lv+Lbut0IORJPKLWu1hQ3u4GsA0SrDzs7nI8JG7Zmyg==} + engines: {node: '>=8.x'} + peerDependencies: + react: '*' + react-dom: '*' + dependencies: + '@babel/runtime': 7.26.10 + '@rc-component/trigger': 2.2.6 + classnames: 2.5.1 + rc-motion: 2.9.5 + rc-overflow: 1.4.1 + rc-util: 5.44.4 + rc-virtual-list: 3.18.4 + dev: false + + /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' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + shallowequal: 1.1.0 + dev: false + + /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' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /rc-slider@8.2.0: + resolution: {integrity: sha512-rnO36M3VhMoPWh1kRuCeJoluT4duAW7+5aLaAn9oLu2pKEKsuOFUh5DmA2kEo88UmvPV6nr7HHDeZuC8SNM/lA==} + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + prop-types: 15.8.1 + rc-tooltip: 3.7.3 + rc-util: 4.21.1 + shallowequal: 1.1.0 + warning: 3.0.0 + transitivePeerDependencies: + - react + - react-dom + dev: false + + /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' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /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' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /rc-swipeout@2.0.11: + resolution: {integrity: sha512-d37Lgn4RX4OOQyuA2BFo0rGlUwrmZk5q83srH3ixJ1Y1jidr2GKjgJDbNeGUVZPNfYBL91Elu6+xfVGftWf4Lg==} + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + rc-gesture: 0.0.22 + react-native-swipeout: 2.3.6 + dev: false + + /rc-switch@3.2.2: + resolution: {integrity: sha512-+gUJClsZZzvAHGy1vZfnwySxj+MjLlGRyXKXScrtCTcmiYNPzxDFOxdQ/3pK1Kt/0POvwJ/6ALOR8gwdXGhs+A==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /rc-switch@4.1.0: + resolution: {integrity: sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /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' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-resize-observer: 1.4.3 + rc-util: 5.44.4 + shallowequal: 1.1.0 + dev: false + + /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' + dependencies: + '@babel/runtime': 7.26.10 + '@rc-component/context': 1.4.0 + classnames: 2.5.1 + rc-resize-observer: 1.4.3 + rc-util: 5.44.4 + rc-virtual-list: 3.18.4 + dev: false + + /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' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-dropdown: 4.0.1 + rc-menu: 9.8.4 + rc-motion: 2.9.5 + rc-resize-observer: 1.4.3 + rc-util: 5.44.4 + dev: false + + /rc-tabs@15.5.1: + resolution: {integrity: sha512-yiWivLAjEo5d1v2xlseB2dQocsOhkoVSfo1krS8v8r+02K+TBUjSjXIf7dgyVSxp6wRIPv5pMi5hanNUlQMgUA==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-dropdown: 4.2.1 + rc-menu: 9.16.1 + rc-motion: 2.9.5 + rc-resize-observer: 1.4.3 + rc-util: 5.44.4 + dev: false + + /rc-textarea@0.4.7: + resolution: {integrity: sha512-IQPd1CDI3mnMlkFyzt2O4gQ2lxUsnBAeJEoZGJnkkXgORNqyM9qovdrCj9NzcRfpHgLdzaEbU3AmobNFGUznwQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-resize-observer: 1.4.3 + rc-util: 5.44.4 + shallowequal: 1.1.0 + dev: false + + /rc-textarea@1.9.0: + resolution: {integrity: sha512-dQW/Bc/MriPBTugj2Kx9PMS5eXCCGn2cxoIaichjbNvOiARlaHdI99j4DTxLl/V8+PIfW06uFy7kjfUIDDKyxQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-input: 1.7.3 + rc-resize-observer: 1.4.3 + rc-util: 5.44.4 + dev: false + + /rc-tooltip@3.7.3: + resolution: {integrity: sha512-dE2ibukxxkrde7wH9W8ozHKUO4aQnPZ6qBHtrTH9LoO836PjDdiaWO73fgPB05VfJs9FbZdmGPVEbXCeOP99Ww==} + dependencies: + babel-runtime: 6.26.0 + prop-types: 15.8.1 + rc-trigger: 2.6.5 + transitivePeerDependencies: + - react + - react-dom + dev: false + + /rc-tooltip@5.2.2: + resolution: {integrity: sha512-jtQzU/18S6EI3lhSGoDYhPqNpWajMtS5VV/ld1LwyfrDByQpYmw/LW6U7oFXXLukjfDHQ7Ju705A82PRNFWYhg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-trigger: 5.3.4 + dev: false + + /rc-tooltip@6.4.0: + resolution: {integrity: sha512-kqyivim5cp8I5RkHmpsp1Nn/Wk+1oeloMv9c7LXNgDxUpGm+RbXJGL+OPvDlcRnx9DBeOe4wyOIl4OKUERyH1g==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + '@rc-component/trigger': 2.2.6 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /rc-tree-select@5.27.0: + resolution: {integrity: sha512-2qTBTzwIT7LRI1o7zLyrCzmo5tQanmyGbSaGTIf7sYimCklAToVVfpMC6OAldSKolcnjorBYPNSKQqJmN3TCww==} + peerDependencies: + react: '*' + react-dom: '*' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-select: 14.16.6 + rc-tree: 5.13.1 + rc-util: 5.44.4 + dev: false + + /rc-tree-select@5.5.5: + resolution: {integrity: sha512-k2av7jF6tW9bIO4mQhaVdV4kJ1c54oxV3/hHVU+oD251Gb5JN+m1RbJFTMf1o0rAFqkvto33rxMdpafaGKQRJw==} + peerDependencies: + react: '*' + react-dom: '*' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-select: 14.1.18 + rc-tree: 5.7.12 + rc-util: 5.44.4 + dev: false + + /rc-tree@5.13.1: + resolution: {integrity: sha512-FNhIefhftobCdUJshO7M8uZTA9F4OPGVXqGfZkkD/5soDeOhwO06T/aKTrg0WD8gRg/pyfq+ql3aMymLHCTC4A==} + engines: {node: '>=10.x'} + peerDependencies: + react: '*' + react-dom: '*' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-motion: 2.9.5 + rc-util: 5.44.4 + rc-virtual-list: 3.18.4 + dev: false + + /rc-tree@5.7.12: + resolution: {integrity: sha512-LXA5nY2hG5koIAlHW5sgXgLpOMz+bFRbnZZ+cCg0tQs4Wv1AmY7EDi1SK7iFXhslYockbqUerQan82jljoaItg==} + engines: {node: '>=10.x'} + peerDependencies: + react: '*' + react-dom: '*' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-motion: 2.9.5 + rc-util: 5.44.4 + rc-virtual-list: 3.18.4 + dev: false + + /rc-trigger@2.6.5: + resolution: {integrity: sha512-m6Cts9hLeZWsTvWnuMm7oElhf+03GOjOLfTuU0QmdB9ZrW7jR2IpI5rpNM7i9MvAAlMAmTx5Zr7g3uu/aMvZAw==} + 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 + rc-util: 4.21.1 + react-lifecycles-compat: 3.0.4 + transitivePeerDependencies: + - react + - react-dom + dev: false + + /rc-trigger@5.3.4: + resolution: {integrity: sha512-mQv+vas0TwKcjAO2izNPkqR4j86OemLRmvL2nOzdP9OWNWA1ivoTt5hzFqYNW9zACwmTezRiN8bttrC7cZzYSw==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-align: 4.0.15 + rc-motion: 2.9.5 + rc-util: 5.44.4 + dev: false + + /rc-upload@4.3.6: + resolution: {integrity: sha512-Bt7ESeG5tT3IY82fZcP+s0tQU2xmo1W6P3S8NboUUliquJLQYLkUcsaExi3IlBVr43GQMCjo30RA2o0i70+NjA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /rc-upload@4.8.1: + resolution: {integrity: sha512-toEAhwl4hjLAI1u8/CgKWt30BR06ulPa4iGQSMvSXoHzO88gPCslxqV/mnn4gJU7PDoltGIC9Eh+wkeudqgHyw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-util: 5.44.4 + dev: false + + /rc-util@4.21.1: + resolution: {integrity: sha512-Z+vlkSQVc1l8O2UjR3WQ+XdWlhj5q9BMQNLk2iOBch75CqPfrJyGtcWMcnhRlNuDu0Ndtt4kLVO8JI8BrABobg==} + 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 + dev: false + + /rc-util@5.44.4: + resolution: {integrity: sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + react-is: 18.3.1 + dev: false + + /rc-virtual-list@3.18.4: + resolution: {integrity: sha512-qkurwgc4Je4xJaYe1DprDl2fwtfEZcuC4UhsJRiX2YZ6wSZAUPQXH/lIX+ZRtNEWmz3pzSBQ7NX3Csjp0wCtcg==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.26.10 + classnames: 2.5.1 + rc-resize-observer: 1.4.3 + rc-util: 5.44.4 + dev: false + + /react-app-polyfill@3.0.0: + resolution: {integrity: sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w==} + engines: {node: '>=14'} + 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 + dev: false + + /react-base16-styling@0.6.0: + resolution: {integrity: sha512-yvh/7CArceR/jNATXOKDlvTnPKPmGZz7zsenQ3jUwLzHkNUR0CvY3yGYJbWJ/nnxsL8Sgmt5cO3/SILVuPO6TQ==} + dependencies: + base16: 1.0.0 + lodash.curry: 4.1.1 + lodash.flow: 3.5.0 + pure-color: 1.3.0 + dev: false + + /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 + dependencies: + '@babel/runtime-corejs2': 7.26.10 + css-box-model: 1.2.1 + memoize-one: 5.2.1 + raf-schd: 4.0.3 + react-redux: 7.2.9 + redux: 4.2.1 + use-memo-one: 1.1.3 + transitivePeerDependencies: + - react-native + dev: false + + /react-color@2.17.1: + resolution: {integrity: sha512-S+I6TkUKJaqfALLkAIfiCZ/MANQyy7dKkf7g9ZU5GTUy2rf8c2Rx62otyvADAviWR+6HRkzdf2vL1Qvz9goCLQ==} + peerDependencies: + react: '*' + dependencies: + '@icons/material': 0.2.4 + lodash: 4.17.21 + material-colors: 1.2.6 + prop-types: 15.8.1 + reactcss: 1.2.3 + tinycolor2: 1.6.0 + dev: false + + /react-color@2.17.3: + resolution: {integrity: sha512-1dtO8LqAVotPIChlmo6kLtFS1FP89ll8/OiA8EcFRDR+ntcK+0ukJgByuIQHRtzvigf26dV5HklnxDIvhON9VQ==} + peerDependencies: + react: '*' + dependencies: + '@icons/material': 0.2.4 + lodash: 4.17.21 + material-colors: 1.2.6 + prop-types: 15.8.1 + reactcss: 1.2.3 + tinycolor2: 1.6.0 + dev: false + + /react-content-loader@5.1.4: + resolution: {integrity: sha512-hTq7pZi2GKCK6a9d3u6XStozm0QGCEjw8cSqQReiWnh2up6IwCha5R5TF0o6SY5qUDpByloEZEZtnFxpJyENFw==} + engines: {node: '>=10'} + peerDependencies: + react: '>=16.0.0' + dev: false + + /react-copy-to-clipboard@5.1.0: + resolution: {integrity: sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==} + peerDependencies: + react: ^15.3.0 || 16 || 17 || 18 + dependencies: + copy-to-clipboard: 3.3.3 + prop-types: 15.8.1 + dev: false + + /react-dev-utils@12.0.1(eslint@9.22.0)(typescript@4.9.5)(webpack@5.98.0): + resolution: {integrity: sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=2.7' + webpack: '>=4' + peerDependenciesMeta: + typescript: + optional: true + 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.22.0)(typescript@4.9.5)(webpack@5.98.0) + 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 + typescript: 4.9.5 + webpack: 5.98.0 + transitivePeerDependencies: + - eslint + - supports-color + - vue-template-compiler + dev: false + + /react-dom@16.14.0(react@16.14.0): + resolution: {integrity: sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==} + peerDependencies: + 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 + dev: false + + /react-error-overlay@6.1.0: + resolution: {integrity: sha512-SN/U6Ytxf1QGkw/9ve5Y+NxBbZM6Ht95tuXNMKs8EJyFa/Vy/+Co3stop3KBHARfn/giv+Lj1uUnTfOJ3moFEQ==} + dev: false + + /react-fast-compare@3.2.2: + resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} + dev: false + + /react-helmet@6.1.0: + resolution: {integrity: sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==} + peerDependencies: + react: '>=16.3.0' + dependencies: + object-assign: 4.1.1 + prop-types: 15.8.1 + react-fast-compare: 3.2.2 + react-side-effect: 2.1.2 + dev: false + + /react-intl@3.12.1: + resolution: {integrity: sha512-cgumW29mwROIqyp8NXStYsoIm27+8FqnxykiLSawWjOxGIBeLuN/+p2srei5SRIumcJefOkOIHP+NDck05RgHg==} + peerDependencies: + react: ^16.3.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 + shallow-equal: 1.2.1 + dev: false + + /react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + dev: false + + /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==} + dev: false + + /react-json-view@1.21.3(@types/react@17.0.52): + 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 + dependencies: + flux: 4.0.4 + react-base16-styling: 0.6.0 + react-lifecycles-compat: 3.0.4 + react-textarea-autosize: 8.5.8(@types/react@17.0.52) + transitivePeerDependencies: + - '@types/react' + - encoding + dev: false + + /react-lifecycles-compat@3.0.4: + resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==} + dev: false + + /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 + dependencies: + create-react-class: 15.7.0 + prop-types: 15.8.1 + react-tween-state: 0.1.5 + dev: false + + /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 + dependencies: + '@babel/runtime': 7.26.10 + '@types/react-redux': 7.1.34 + hoist-non-react-statics: 3.3.2 + loose-envify: 1.4.0 + prop-types: 15.8.1 + react-is: 17.0.2 + dev: false + + /react-refresh@0.10.0: + resolution: {integrity: sha512-PgidR3wST3dDYKr6b4pJoqQFpPGNKDSCDx4cZoshjXipw3LzO7mG1My2pwEzz2JVkF+inx3xRpDeQLFQGH/hsQ==} + engines: {node: '>=0.10.0'} + dev: false + + /react-refresh@0.11.0: + resolution: {integrity: sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==} + engines: {node: '>=0.10.0'} + dev: false + + /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 + dependencies: + lodash: 4.17.21 + dev: false + + /react-router-config@5.1.1(react-router@5.2.0)(react@16.14.0): + resolution: {integrity: sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==} + peerDependencies: + react: '>=15' + react-router: '>=5' + dependencies: + '@babel/runtime': 7.26.10 + react: 16.14.0 + react-router: 5.2.0(react@16.14.0) + dev: false + + /react-router-config@5.1.1(react@16.14.0): + resolution: {integrity: sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==} + peerDependencies: + react: '>=15' + react-router: '>=5' + dependencies: + '@babel/runtime': 7.26.10 + react: 16.14.0 + dev: false + + /react-router-dom@5.2.0(react@16.14.0): + resolution: {integrity: sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==} + peerDependencies: + react: '>=15' + dependencies: + '@babel/runtime': 7.26.10 + 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 + dev: false + + /react-router-dom@5.3.4: + resolution: {integrity: sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==} + peerDependencies: + react: '>=15' + dependencies: + '@babel/runtime': 7.26.10 + history: 4.10.1 + loose-envify: 1.4.0 + prop-types: 15.8.1 + react-router: 5.3.4 + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + dev: false + + /react-router@5.2.0(react@16.14.0): + resolution: {integrity: sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==} + peerDependencies: + react: '>=15' + dependencies: + '@babel/runtime': 7.26.10 + 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 + dev: false + + /react-router@5.3.4: + resolution: {integrity: sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==} + peerDependencies: + react: '>=15' + dependencies: + '@babel/runtime': 7.26.10 + 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-is: 16.13.1 + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + dev: false + + /react-scripts@5.0.1(eslint@9.22.0)(typescript@4.9.5): + 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 + dependencies: + '@babel/core': 7.26.10 + '@pmmmwh/react-refresh-webpack-plugin': 0.5.15(react-refresh@0.11.0)(webpack-dev-server@4.15.2)(webpack@5.98.0) + '@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.98.0) + 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.98.0) + css-minimizer-webpack-plugin: 3.4.1(webpack@5.98.0) + dotenv: 10.0.0 + dotenv-expand: 5.1.0 + eslint: 9.22.0 + eslint-config-react-app: 7.0.1(eslint@9.22.0)(jest@27.5.1)(typescript@4.9.5) + eslint-webpack-plugin: 3.2.0(eslint@9.22.0)(webpack@5.98.0) + file-loader: 6.2.0(webpack@5.98.0) + fs-extra: 10.1.0 + html-webpack-plugin: 5.6.3(webpack@5.98.0) + identity-obj-proxy: 3.0.0 + jest: 27.5.1 + jest-resolve: 27.5.1 + jest-watch-typeahead: 1.1.0(jest@27.5.1) + mini-css-extract-plugin: 2.9.2(webpack@5.98.0) + 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.98.0) + 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-app-polyfill: 3.0.0 + react-dev-utils: 12.0.1(eslint@9.22.0)(typescript@4.9.5)(webpack@5.98.0) + react-refresh: 0.11.0 + resolve: 1.22.10 + resolve-url-loader: 4.0.0 + sass-loader: 12.6.0(webpack@5.98.0) + semver: 7.7.1 + source-map-loader: 3.0.2(webpack@5.98.0) + style-loader: 3.3.4(webpack@5.98.0) + tailwindcss: 3.4.17 + terser-webpack-plugin: 5.3.14(webpack@5.98.0) + typescript: 4.9.5 + webpack: 5.98.0 + webpack-dev-server: 4.15.2(webpack@5.98.0) + webpack-manifest-plugin: 4.1.1(webpack@5.98.0) + workbox-webpack-plugin: 6.6.0(webpack@5.98.0) + optionalDependencies: + fsevents: 2.3.3 + 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 + dev: false + + /react-side-effect@2.1.2: + resolution: {integrity: sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==} + peerDependencies: + react: ^16.3.0 || ^17.0.0 || ^18.0.0 + dev: false + + /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 + dependencies: + prop-types: 15.8.1 + react-lifecycles-compat: 3.0.4 + react-style-proptype: 3.2.2 + dev: false + + /react-sticky-mouse-tooltip@0.0.1: + resolution: {integrity: sha512-nuKyvolX3Zsu48uoGXkEvEE8oAwl7jaUvJrA/SxCSmBmbzmECNBQp03Z60L6/1ImLUzLFUHh2Wul3GpkEffrPw==} + peerDependencies: + react: ^16.1.0 + react-dom: ^16.1.0 + dev: false + + /react-style-proptype@3.2.2: + resolution: {integrity: sha512-ywYLSjNkxKHiZOqNlso9PZByNEY+FTyh3C+7uuziK0xFXu9xzdyfHwg4S9iyiRRoPCR4k2LqaBBsWVmSBwCWYQ==} + dependencies: + prop-types: 15.8.1 + dev: false + + /react-textarea-autosize@8.5.8(@types/react@17.0.52): + resolution: {integrity: sha512-iUiIj70JefrTuSJ4LbVFiSqWiHHss5L63L717bqaWHMgkm9sz6eEvro4vZ3uQfGJbevzwT6rHOszHKA8RkhRMg==} + engines: {node: '>=10'} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + dependencies: + '@babel/runtime': 7.26.10 + use-composed-ref: 1.4.0(@types/react@17.0.52) + use-latest: 1.3.0(@types/react@17.0.52) + transitivePeerDependencies: + - '@types/react' + dev: false + + /react-tween-state@0.1.5: + resolution: {integrity: sha512-sJQpjsdn0wjlDIUpfpb7jQGnOG8hAEW2e8k0KPA+xmf5KFa6Xat2JldbmxBhaqP0S/uIXhVE5ymKyH/b9X8nYA==} + dependencies: + raf: 3.4.1 + tween-functions: 1.2.0 + dev: false + + /react-universal-interface@0.6.2(tslib@2.8.1): + resolution: {integrity: sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==} + peerDependencies: + react: '*' + tslib: '*' + dependencies: + tslib: 2.8.1 + dev: false + + /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 + 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-universal-interface: 0.6.2(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 + dev: false + + /react@16.14.0: + resolution: {integrity: sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==} + engines: {node: '>=0.10.0'} + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + prop-types: 15.8.1 + dev: false + + /reactcss@1.2.3: + resolution: {integrity: sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==} + peerDependencies: + react: '*' + dependencies: + lodash: 4.17.21 + dev: false + + /read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + dependencies: + pify: 2.3.0 + dev: false + + /read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + + /read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + 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: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + 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: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: false + + /readdirp@2.2.1: + resolution: {integrity: sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==} + engines: {node: '>=0.10'} + requiresBuild: true + dependencies: + graceful-fs: 4.2.11 + micromatch: 3.1.10 + readable-stream: 2.3.8 + transitivePeerDependencies: + - supports-color + dev: true + optional: true + + /readdirp@3.5.0: + resolution: {integrity: sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: false + + /recompose@0.22.0: + resolution: {integrity: sha512-QjNK/CgNg6wa7sqaQelgkRdl7ktIYbOV4xp0m2n8TexmHI5h3gjOc5a6nNQhtH3Js63hGZ1HfvJ3DUErrvZ2yg==} + peerDependencies: + react: ^0.14.0 || ^15.0.0 + dependencies: + change-emitter: 0.1.6 + fbjs: 0.8.18 + hoist-non-react-statics: 1.2.0 + symbol-observable: 1.2.0 + dev: false + + /recursive-readdir@2.2.3: + resolution: {integrity: sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==} + engines: {node: '>=6.0.0'} + dependencies: + minimatch: 3.1.2 + dev: false + + /redux-saga@0.16.2: + resolution: {integrity: sha512-iIjKnRThI5sKPEASpUvySemjzwqwI13e3qP7oLub+FycCRDysLSAOwt958niZW6LhxfmS6Qm1BzbU70w/Koc4w==} + dev: false + + /redux@4.2.1: + resolution: {integrity: sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==} + dependencies: + '@babel/runtime': 7.26.10 + dev: false + + /reflect-metadata@0.1.14: + resolution: {integrity: sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==} + dev: false + + /reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==} + + /regenerate-unicode-properties@10.0.1: + resolution: {integrity: sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==} + engines: {node: '>=4'} + dependencies: + regenerate: 1.4.2 + + /regenerate-unicode-properties@10.2.0: + resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==} + engines: {node: '>=4'} + dependencies: + regenerate: 1.4.2 + dev: false + + /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==} + dev: true + + /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==} + dev: false + + /regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + + /regenerator-transform@0.10.1: + resolution: {integrity: sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==} + dependencies: + babel-runtime: 6.26.0 + babel-types: 6.26.0 + private: 0.1.8 + dev: true + + /regenerator-transform@0.15.2: + resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} + dependencies: + '@babel/runtime': 7.26.10 + dev: false + + /regex-cache@0.4.4: + resolution: {integrity: sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + is-equal-shallow: 0.1.3 + dev: true + optional: true + + /regex-not@1.0.2: + resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + extend-shallow: 3.0.2 + safe-regex: 1.1.0 + + /regex-parser@2.3.1: + resolution: {integrity: sha512-yXLRqatcCuKtVHsWrNg0JL3l1zGfdXeEvDa0bdu4tCDQw0RpMDZsqbkyRTUnKMR0tXF627V2oEWjBEaEdqTwtQ==} + dev: false + + /regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.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: + resolution: {integrity: sha512-tJ9+S4oKjxY8IZ9jmjnp/mtytu1u3iyIQAfmI51IKWH6bFf7XR1ybtaO6j7INhZKXOTYADk7V5qxaqLkmNxiZQ==} + dependencies: + regenerate: 1.4.2 + regjsgen: 0.2.0 + regjsparser: 0.1.5 + dev: true + + /regexpu-core@6.2.0: + resolution: {integrity: sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==} + engines: {node: '>=4'} + 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 + dev: false + + /regjsgen@0.2.0: + resolution: {integrity: sha512-x+Y3yA24uF68m5GA+tBjbGYo64xXVJpbToBaWCoSNSc1hdk6dfctaRWrNFTVJZIIhL5GxW8zwjoixbnifnK59g==} + dev: true + + /regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} + dev: false + + /regjsparser@0.1.5: + resolution: {integrity: sha512-jlQ9gYLfk2p3V5Ag5fYhA7fv7OHzd1KUH0PRP46xc3TgwjwgROIW572AfYg/X9kaNq/LJnu6oJcFRXlIrGoTRw==} + hasBin: true + dependencies: + jsesc: 0.5.0 + dev: true + + /regjsparser@0.12.0: + resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} + hasBin: true + dependencies: + jsesc: 3.0.2 + dev: false + + /regl@1.6.1: + resolution: {integrity: sha512-7Z9rmpEqmLNwC9kCYCyfyu47eWZaQWeNpwZfwz99QueXN8B/Ow40DB0N+OeUeM/yu9pZAB01+JgJ+XghGveVoA==} + dev: false + + /regl@1.7.0: + resolution: {integrity: sha512-bEAtp/qrtKucxXSJkD4ebopFZYP0q1+3Vb2WECWv/T8yQEgKxDxJ7ztO285tAMaYZVR6mM1GgI6CCn8FROtL1w==} + dev: false + + /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==} + requiresBuild: true + + /renderkid@2.0.7: + resolution: {integrity: sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==} + dependencies: + css-select: 4.3.0 + dom-converter: 0.2.0 + htmlparser2: 6.1.0 + lodash: 4.17.21 + strip-ansi: 3.0.1 + dev: true + + /renderkid@3.0.0: + resolution: {integrity: sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==} + dependencies: + css-select: 4.3.0 + dom-converter: 0.2.0 + htmlparser2: 6.1.0 + lodash: 4.17.21 + strip-ansi: 6.0.1 + dev: false + + /repeat-element@1.1.4: + resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + + /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'} + dependencies: + is-finite: 1.1.0 + dev: true + + /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'} + dev: false + + /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==} + dev: false + + /resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + dependencies: + resolve-from: 5.0.0 + + /resolve-from@3.0.0: + resolution: {integrity: sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==} + engines: {node: '>=4'} + dev: false + + /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==} + dev: false + + /resolve-protobuf-schema@2.1.0: + resolution: {integrity: sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==} + dependencies: + protocol-buffers-schema: 3.6.0 + dev: false + + /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 + 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 + dev: false + + /resolve-url@0.2.1: + resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} + deprecated: https://github.com/lydell/resolve-url#deprecated + requiresBuild: true + + /resolve.exports@1.1.1: + resolution: {integrity: sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==} + engines: {node: '>=10'} + dev: false + + /resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} + hasBin: true + 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: + resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} + hasBin: true + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: false + + /restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + dev: true + + /ret@0.1.15: + resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} + engines: {node: '>=0.12'} + requiresBuild: true + + /ret@0.2.2: + resolution: {integrity: sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==} + engines: {node: '>=4'} + dev: false + + /retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + dev: false + + /reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: false + + /rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + dev: true + + /right-align@0.1.3: + resolution: {integrity: sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==} + engines: {node: '>=0.10.0'} + dependencies: + align-text: 0.1.4 + dev: false + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + dependencies: + glob: 7.2.3 + + /ripemd160@2.0.2: + resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} + dependencies: + hash-base: 3.0.5 + inherits: 2.0.4 + dev: false + + /rmc-align@1.0.0: + resolution: {integrity: sha512-3gEa5/+hqqoEVoeQ25KoRc8DOsXIdSaVpaBq1zQFaV941LR3xvZIRTlxTDT/IagYwoGM1KZea/jd7cNMYP34Rg==} + dependencies: + babel-runtime: 6.26.0 + dom-align: 1.12.4 + rc-util: 4.21.1 + dev: false + + /rmc-calendar@1.1.4: + resolution: {integrity: sha512-xxQZaPFDnpHt4IFO8mukYrXSgC1W8LcNVp+EoX4iyeOJFimungOKB/iP5/cy+st8yXq8lUgk9TXsHNtM6Xo6ZA==} + dependencies: + babel-runtime: 6.26.0 + rc-animate: 2.11.1 + rmc-date-picker: 6.0.10 + transitivePeerDependencies: + - react + - react-dom + dev: false + + /rmc-cascader@5.0.3: + resolution: {integrity: sha512-PxDhMjWViDdG4SMZqoXtAthGwgDyYnyxxZEE17IDDYsiCHpWtOhoIL8nsI+/hZ212UT/XF2LpqCsOlMoJiYk+w==} + dependencies: + array-tree-filter: 2.1.0 + babel-runtime: 6.26.0 + rmc-picker: 5.0.10 + transitivePeerDependencies: + - react + - react-dom + dev: false + + /rmc-date-picker@6.0.10: + resolution: {integrity: sha512-/9+I6lm3EDEl6M7862V6++zFuxwsM0UEq8wSHbotYIPPmyB/65gx1cviblghOv2QfB0O9+U2w3qEJlRP/WsMrA==} + dependencies: + babel-runtime: 6.26.0 + rmc-picker: 5.0.10 + transitivePeerDependencies: + - react + - react-dom + dev: false + + /rmc-dialog@1.1.1: + resolution: {integrity: sha512-28aJqtPTX6v13Z/aU1WBy1AFIXkE74PxZXde7JvtEIy9hQDTjH8fqOi822BpzAbXCyNE7jF9iFomy3H2ClsDJA==} + dependencies: + babel-runtime: 6.26.0 + rc-animate: 2.11.1 + transitivePeerDependencies: + - react + - react-dom + dev: false + + /rmc-drawer@0.4.11: + resolution: {integrity: sha512-YfB9XEJ8iM0MMuLWAK4313uOxSM8NAljC8Cqun1KamXutglYTuRviUuTLNSOzV8HHPp5kNpsVduvPCGLWXvThw==} + engines: {node: '>=4.0.0'} + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + prop-types: 15.8.1 + dev: false + + /rmc-feedback@2.0.0: + resolution: {integrity: sha512-5PWOGOW7VXks/l3JzlOU9NIxRpuaSS8d9zA3UULUCuTKnpwBHNvv1jSJzxgbbCQeYzROWUpgKI4za3X4C/mKmQ==} + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + dev: false + + /rmc-input-number@1.0.5: + resolution: {integrity: sha512-prPkEtoOVde77GnEnEaBeWjBobMOPgGqU5bd0gxfp1kt1pUN740mMpVAcH7uxpJjVfmw+kuGWtiz4S7CueagSg==} + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + rmc-feedback: 2.0.0 + dev: false + + /rmc-list-view@0.11.5: + resolution: {integrity: sha512-eMOC5394tLNawcdEEhF7boMpQgpjJGDdL5lS+LblAWdBec7Q4EYkUdnrKNbt+O9k5RGM6nSLAGZK5oB4FN85Lg==} + 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 + dev: false + + /rmc-notification@1.0.0: + resolution: {integrity: sha512-9sPxjltFvtRLt2v312Hu7OXwk53pHkBYgINRDmnJ3A5NF1qtJeCCcdN0Xr0fzJ6sbQvtGju822tWHdzYA9u7Vw==} + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + prop-types: 15.8.1 + rc-animate: 2.11.1 + rc-util: 4.21.1 + transitivePeerDependencies: + - react + - react-dom + dev: false + + /rmc-nuka-carousel@3.0.1: + resolution: {integrity: sha512-w2EPTERMUUZqcUSKFuejjin7xsMlhrLrtS0A/igTXpFJGq3kemDKcRi7q3pSYDuZBHYBl5iV4UqsLLkjdFtrYA==} + dependencies: + exenv: 1.2.2 + raf: 3.4.1 + dev: false + + /rmc-picker@5.0.10: + resolution: {integrity: sha512-KZ70+WjcaZHnG5GyCxWCPFWAZ12s6NqyrbW73LeqH0WEqaTMMs0sOrk2f4mQAZ/CGT0XcFN6VZLw7Ozoxfn7LA==} + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + rmc-dialog: 1.1.1 + rmc-feedback: 2.0.0 + transitivePeerDependencies: + - react + - react-dom + dev: false + + /rmc-pull-to-refresh@1.0.13: + resolution: {integrity: sha512-iYLsURiR7G/sKmRA6p2kq6ZXicn7Hyeo6VQFljssV1eMW+fzDgihhaz0kv5mza0f88vphGJvjOihT9E6+xGb6Q==} + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + dev: false + + /rmc-steps@1.0.1: + resolution: {integrity: sha512-8ijtwp4D1CYTtI2yerXJYqCv+GQbiBc9T12nrFngd/vM0y+58CnznGphTAueF6IWf7qbxBwcjTrcFgg7bP2YGA==} + dependencies: + babel-runtime: 6.26.0 + classnames: 2.5.1 + dev: false + + /rmc-tabs@1.2.29: + resolution: {integrity: sha512-wiJS9WSJi9JH9GQO+FqncX+zaHP31qHa/S8nDW9UXUx0qbCX294QcJEnvfB+WmsfUws7rXjs6sOQp5EDiObnHg==} + dependencies: + babel-runtime: 6.26.0 + rc-gesture: 0.0.22 + dev: false + + /rmc-tooltip@1.0.1: + resolution: {integrity: sha512-fSDArf2BlMVrHExmBiqb2TkCRJHshvXFJQ/7tMraLellwaJLNiwrxtWpW329k3S+zTtoVG8UxFS1TjBGEsMzRg==} + dependencies: + babel-runtime: 6.26.0 + rmc-trigger: 1.0.12 + transitivePeerDependencies: + - react + - react-dom + dev: false + + /rmc-trigger@1.0.12: + resolution: {integrity: sha512-AccQniX7PX7Pm8hBhHEsnf3JU6CA61Xc7fAt2WbO+oXrGaI/jqN8C3COhhOXG54S5iTOjLS26j858zshwAxR9A==} + dependencies: + babel-runtime: 6.26.0 + rc-animate: 2.11.1 + rc-util: 4.21.1 + rmc-align: 1.0.0 + transitivePeerDependencies: + - react + - react-dom + dev: false + + /robust-predicates@3.0.2: + resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} + dev: false + + /rollup-plugin-terser@7.0.2(rollup@2.79.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 + 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 + dev: false + + /rollup@0.25.8: + resolution: {integrity: sha512-a2S4Bh3bgrdO4BhKr2E4nZkjTvrJ2m2bWjMTzVYtoqSCn0HnuxosXnaJUHrMEziOWr3CzL9GjilQQKcyCQpJoA==} + hasBin: true + dependencies: + chalk: 1.1.3 + minimist: 1.2.8 + source-map-support: 0.3.3 + dev: false + + /rollup@2.79.2: + resolution: {integrity: sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==} + engines: {node: '>=10.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.3 + dev: false + + /rsvp@4.8.5: + resolution: {integrity: sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==} + engines: {node: 6.* || >= 7.*} + + /rtl-css-js@1.16.1: + resolution: {integrity: sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==} + dependencies: + '@babel/runtime': 7.26.10 + dev: false + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: false + + /runscript@1.6.0: + resolution: {integrity: sha512-lI0ybcwtdC5Wz3aiVtMAK6U5jcTDeLseEBSXcz6ABtQeMmQGpj35dmzpmpy2C9Bn0k2wTjTRLZoya0NFt8Mxsg==} + engines: {node: '>=4.2.3'} + dependencies: + is-type-of: 1.4.0 + dev: true + + /rw@1.3.3: + resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} + dev: false + + /rxjs@6.6.7: + resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} + engines: {npm: '>=2.0.0'} + dependencies: + tslib: 1.14.1 + dev: false + + /rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + dependencies: + tslib: 2.8.1 + dev: true + + /safe-array-concat@1.1.3: + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} + engines: {node: '>=0.4'} + 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: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + requiresBuild: true + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + + /safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + /safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + /safe-regex@1.1.0: + resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} + requiresBuild: true + dependencies: + ret: 0.1.15 + + /safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + dev: false + + /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 + 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: + resolution: {integrity: sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==} + dev: false + + /sass-loader@12.6.0(webpack@5.98.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 + dependencies: + klona: 2.0.6 + neo-async: 2.6.2 + webpack: 5.98.0 + dev: false + + /sax@1.2.4: + resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} + dev: false + + /saxes@5.0.1: + resolution: {integrity: sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==} + engines: {node: '>=10'} + dependencies: + xmlchars: 2.2.0 + + /scheduler@0.19.1: + resolution: {integrity: sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==} + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + dev: false + + /schema-utils@1.0.0: + resolution: {integrity: sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==} + engines: {node: '>= 4'} + dependencies: + ajv: 6.12.6 + ajv-errors: 1.0.1(ajv@6.12.6) + ajv-keywords: 3.5.2(ajv@6.12.6) + dev: false + + /schema-utils@2.7.0: + resolution: {integrity: sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==} + engines: {node: '>= 8.9.0'} + dependencies: + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + dev: false + + /schema-utils@2.7.1: + resolution: {integrity: sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==} + engines: {node: '>= 8.9.0'} + dependencies: + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + dev: false + + /schema-utils@3.3.0: + resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} + engines: {node: '>= 10.13.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.0: + resolution: {integrity: sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/json-schema': 7.0.15 + ajv: 8.17.1 + ajv-formats: 2.1.1 + ajv-keywords: 5.1.0(ajv@8.17.1) + dev: false + + /screenfull@5.2.0: + resolution: {integrity: sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==} + engines: {node: '>=0.10.0'} + dev: false + + /screenfull@6.0.2: + resolution: {integrity: sha512-AQdy8s4WhNvUZ6P8F6PB21tSPIYKniic+Ogx0AacBMjKP1GUHN2E9URxQHtCusiwxudnCKkdy4GrHXPPJSkCCw==} + engines: {node: ^14.13.1 || >=16.0.0} + dev: false + + /script-ext-html-webpack-plugin@2.1.5(html-webpack-plugin@4.5.2): + 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 + dependencies: + debug: 4.4.0 + html-webpack-plugin: 4.5.2 + transitivePeerDependencies: + - supports-color + dev: true + + /scroll-into-view-if-needed@2.2.31: + resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==} + dependencies: + compute-scroll-into-view: 1.0.20 + dev: false + + /scroll-into-view-if-needed@3.1.0: + resolution: {integrity: sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==} + dependencies: + compute-scroll-into-view: 3.1.1 + dev: false + + /scroll-into-view@1.16.2: + resolution: {integrity: sha512-vyTE0i27o6eldt9xinjHec41Dw05y+faoI+s2zNKJAVOdbA5M2XZrYq/obJ8E+QDQulJ2gDjgui9w9m9RZSRng==} + dev: false + + /seamless-immutable@7.1.4: + resolution: {integrity: sha512-XiUO1QP4ki4E2PHegiGAlu6r82o5A+6tRh7IkGGTVg/h+UoeX4nFBeCGPOhb4CYjvkqsfm/TUtvOMYC1xmV30A==} + dev: false + + /select-hose@2.0.0: + resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} + dev: false + + /selfsigned@2.4.1: + resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} + engines: {node: '>=10'} + dependencies: + '@types/node-forge': 1.3.11 + node-forge: 1.3.1 + dev: false + + /semver-compare@1.0.0: + resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} + dev: true + + /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'} + 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 + dev: false + + /serialize-javascript@4.0.0: + resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==} + dependencies: + randombytes: 2.1.0 + dev: false + + /serialize-javascript@6.0.2: + resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + dependencies: + randombytes: 2.1.0 + dev: false + + /serve-index@1.9.1: + resolution: {integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==} + engines: {node: '>= 0.8.0'} + 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 + dev: false + + /serve-static@1.16.2: + resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.0 + transitivePeerDependencies: + - supports-color + dev: false + + /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'} + 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: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==} + engines: {node: '>=6.9'} + dev: false + + /set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + + /set-value@2.0.1: + resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} + engines: {node: '>=0.10.0'} + requiresBuild: true + 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: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + dev: false + + /setprototypeof@1.1.0: + resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==} + dev: false + + /setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + dev: false + + /sha.js@2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /shallow-equal@1.2.1: + resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==} + dev: false + + /shallowequal@1.1.0: + resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} + dev: false + + /shebang-command@1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + dependencies: + shebang-regex: 1.0.0 + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + + /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'} + dev: false + + /shellwords@0.1.1: + resolution: {integrity: sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==} + requiresBuild: true + optional: true + + /should-equal@2.0.0: + resolution: {integrity: sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==} + dependencies: + should-type: 1.4.0 + + /should-format@3.0.3: + resolution: {integrity: sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==} + dependencies: + should-type: 1.4.0 + should-type-adaptors: 1.1.0 + + /should-type-adaptors@1.1.0: + resolution: {integrity: sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==} + dependencies: + should-type: 1.4.0 + should-util: 1.0.1 + + /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==} + 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: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + /side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: false + + /simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + dependencies: + is-arrayish: 0.3.2 + dev: false + + /sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + /size-sensor@1.0.2: + resolution: {integrity: sha512-2NCmWxY7A9pYKGXNBfteo4hy14gWu47rg5692peVMst6lQLPKrVjhY+UTEsPI5ceFRJSl3gVgMYaUi/hKuaiKw==} + dev: false + + /slash@1.0.0: + resolution: {integrity: sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==} + engines: {node: '>=0.10.0'} + dev: true + + /slash@2.0.0: + resolution: {integrity: sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==} + engines: {node: '>=6'} + dev: false + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + /slash@4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} + dev: false + + /slice-ansi@3.0.0: + resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: true + + /slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: true + + /snapdragon-node@2.1.1: + resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + define-property: 1.0.0 + isobject: 3.0.1 + snapdragon-util: 3.0.1 + + /snapdragon-util@3.0.1: + resolution: {integrity: sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + kind-of: 3.2.2 + + /snapdragon@0.8.2: + resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} + engines: {node: '>=0.10.0'} + requiresBuild: true + 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: + resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} + dependencies: + faye-websocket: 0.11.4 + uuid: 8.3.2 + websocket-driver: 0.7.4 + dev: false + + /sort-asc@0.2.0: + resolution: {integrity: sha512-umMGhjPeHAI6YjABoSTrFp2zaBtXBej1a0yKkuMUyjjqu6FJsTF+JYwCswWDg+zJfk/5npWUUbd33HH/WLzpaA==} + engines: {node: '>=0.10.0'} + dev: false + + /sort-desc@0.2.0: + resolution: {integrity: sha512-NqZqyvL4VPW+RAxxXnB8gvE1kyikh8+pR+T+CXLksVRN9eiQqkQlPwqWYU0mF9Jm7UnctShlxLyAt1CaBOTL1w==} + engines: {node: '>=0.10.0'} + dev: false + + /sort-keys@1.1.2: + resolution: {integrity: sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==} + engines: {node: '>=0.10.0'} + dependencies: + is-plain-obj: 1.1.0 + dev: false + + /sort-object@3.0.3: + resolution: {integrity: sha512-nK7WOY8jik6zaG9CRwZTaD5O7ETWDLZYMM12pqY8htll+7dYeqGfEUPcUBHOpSJg2vJOrvFIY2Dl5cX2ih1hAQ==} + engines: {node: '>=0.10.0'} + 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 + dev: false + + /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(webpack@5.98.0): + resolution: {integrity: sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + dependencies: + abab: 2.0.6 + iconv-lite: 0.6.3 + source-map-js: 1.2.1 + webpack: 5.98.0 + dev: false + + /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 + requiresBuild: true + 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: + resolution: {integrity: sha512-9O4+y9n64RewmFoKUZ/5Tx9IHIcXM6Q+RTSw6ehnqybUz4a7iwR3Eaw80uLtqqQ5D0C+5H03D4KKGo9PdP33Gg==} + dependencies: + source-map: 0.1.32 + dev: false + + /source-map-support@0.4.18: + resolution: {integrity: sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==} + dependencies: + source-map: 0.5.7 + dev: true + + /source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + /source-map-url@0.4.1: + resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} + deprecated: See https://github.com/lydell/source-map-url#deprecated + requiresBuild: true + + /source-map@0.1.32: + resolution: {integrity: sha512-htQyLrrRLkQ87Zfrir4/yN+vAUd6DNjVayEjTSHXu29AYQJw57I4/xEL/M6p6E/woPNJwvZt6rVlzc7gFEJccQ==} + engines: {node: '>=0.8.0'} + dependencies: + amdefine: 1.0.1 + dev: false + + /source-map@0.5.6: + resolution: {integrity: sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==} + engines: {node: '>=0.10.0'} + dev: false + + /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'} + dependencies: + whatwg-url: 7.1.0 + dev: false + + /sourcemap-codec@1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead + dev: false + + /spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.21 + + /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==} + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.21 + + /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==} + 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 + dev: false + + /spdy@4.0.2: + resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} + engines: {node: '>=6.0.0'} + 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 + dev: false + + /splaytree@3.1.2: + resolution: {integrity: sha512-4OM2BJgC5UzrhVnnJA4BkHKGtjXNzzUfpQjCO8I05xYPsfS/VuQDwjCGGMi8rYQilHEV4j8NBqTFbls/PZEE7A==} + dev: false + + /split-on-first@1.1.0: + resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==} + engines: {node: '>=6'} + dev: false + + /split-on-first@3.0.0: + resolution: {integrity: sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==} + engines: {node: '>=12'} + dev: false + + /split-string@3.1.0: + resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + extend-shallow: 3.0.2 + + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + /sql-formatter@2.3.4: + resolution: {integrity: sha512-CajWtvzYoBJbD5PQeVe3E7AOHAIYvRQEPOKgF9kfKNeY8jtjBiiA6pDzkMuAID8jJMluoPvyKveLigSaA5tKQQ==} + dependencies: + lodash: 4.17.21 + dev: false + + /ssf@0.11.2: + resolution: {integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==} + engines: {node: '>=0.8'} + dependencies: + frac: 1.1.2 + dev: false + + /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' + dev: false + + /stack-generator@2.0.10: + resolution: {integrity: sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==} + dependencies: + stackframe: 1.3.4 + dev: false + + /stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + dependencies: + escape-string-regexp: 2.0.0 + + /stackframe@1.3.4: + resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} + dev: false + + /stacktrace-gps@3.1.2: + resolution: {integrity: sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==} + dependencies: + source-map: 0.5.6 + stackframe: 1.3.4 + dev: false + + /stacktrace-js@2.0.2: + resolution: {integrity: sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==} + dependencies: + error-stack-parser: 2.1.4 + stack-generator: 2.0.10 + stacktrace-gps: 3.1.2 + dev: false + + /static-eval@2.0.2: + resolution: {integrity: sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==} + dependencies: + escodegen: 1.14.3 + dev: false + + /static-extend@0.1.2: + resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + define-property: 0.2.5 + object-copy: 0.1.0 + + /statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + dev: false + + /statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + dev: false + + /stream-browserify@2.0.2: + resolution: {integrity: sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==} + dependencies: + inherits: 2.0.4 + readable-stream: 2.3.8 + dev: false + + /stream-http@2.8.3: + resolution: {integrity: sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==} + 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 + dev: false + + /strict-uri-encode@1.1.0: + resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==} + engines: {node: '>=0.10.0'} + dev: false + + /strict-uri-encode@2.0.0: + resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} + engines: {node: '>=4'} + dev: false + + /string-argv@0.3.1: + resolution: {integrity: sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==} + engines: {node: '>=0.6.19'} + dev: true + + /string-convert@0.2.1: + resolution: {integrity: sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==} + dev: false + + /string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + + /string-length@5.0.1: + resolution: {integrity: sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==} + engines: {node: '>=12.20'} + dependencies: + char-regex: 2.0.2 + strip-ansi: 7.1.0 + dev: false + + /string-natural-compare@3.0.1: + resolution: {integrity: sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==} + dev: false + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + dev: false + + /string.prototype.includes@2.0.1: + resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + dev: false + + /string.prototype.matchall@4.0.12: + resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} + engines: {node: '>= 0.4'} + 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 + dev: false + + /string.prototype.repeat@1.0.0: + resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} + dependencies: + define-properties: 1.2.1 + es-abstract: 1.23.9 + dev: false + + /string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + /string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + requiresBuild: true + dependencies: + safe-buffer: 5.1.2 + + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /stringify-object@3.3.0: + resolution: {integrity: sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==} + engines: {node: '>=4'} + dependencies: + get-own-enumerable-property-symbols: 3.0.2 + is-obj: 1.0.1 + is-regexp: 1.0.0 + + /strip-ansi@3.0.1: + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-regex: 2.1.1 + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.1.0 + dev: false + + /strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + dev: false + + /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'} + dev: false + + /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'} + dev: true + + /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==} + dependencies: + clean-css: 4.2.4 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + dev: true + + /style-loader@3.3.4(webpack@5.98.0): + resolution: {integrity: sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + dependencies: + webpack: 5.98.0 + dev: false + + /stylehacks@5.1.1(postcss@8.5.3): + resolution: {integrity: sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + browserslist: 4.24.4 + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + dev: false + + /stylis@4.2.0: + resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} + dev: false + + /stylis@4.3.6: + resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} + dev: false + + /sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + 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.6 + ts-interface-checker: 0.1.13 + dev: false + + /supercluster@7.1.5: + resolution: {integrity: sha512-EulshI3pGUM66o6ZdH3ReiFcvHpM3vAigyK+vcxdjpJyEbIIrtbmBdY23mGgnI24uXiGFvrGq9Gkum/8U7vJWg==} + dependencies: + kdbush: 3.0.0 + dev: false + + /supercluster@8.0.1: + resolution: {integrity: sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==} + dependencies: + kdbush: 4.0.2 + dev: false + + /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'} + dependencies: + has-flag: 1.0.0 + dev: true + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: false + + /supports-color@6.1.0: + resolution: {integrity: sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==} + engines: {node: '>=6'} + dependencies: + has-flag: 3.0.0 + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + + /supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + dev: false + + /supports-hyperlinks@2.3.0: + resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + + /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==} + dev: false + + /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 + 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 + dev: false + + /svgo@2.8.0: + resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==} + engines: {node: '>=10.13.0'} + hasBin: true + 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 + dev: false + + /swagger-ui-dist@4.19.1: + resolution: {integrity: sha512-n/gFn+R7G/BXWwl5UZLw6F1YgWOlf3zkwGlsPhTMhNtAAolBGKg0JS5b2RKt5NI6/hSopVaSrki2wTIMUDDy2w==} + dev: false + + /swagger2openapi@7.0.8: + resolution: {integrity: sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==} + hasBin: true + dependencies: + call-me-maybe: 1.0.2 + node-fetch: 2.7.0 + 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: + resolution: {integrity: sha512-dshNvs3ExOqtZ6kJBaAsabhPdHyeY4P2cKwRCniDVifBMoG/SVI7tfLWqPXriVspf2Rg4tPzXJTnwaihIeFw2A==} + peerDependencies: + react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + dependencies: + dequal: 2.0.3 + use-sync-external-store: 1.4.0 + dev: false + + /symbol-observable@1.2.0: + resolution: {integrity: sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==} + engines: {node: '>=0.10.0'} + dev: false + + /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 + 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) + 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 + dev: false + + /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'} + dev: false + + /tape@4.17.0: + resolution: {integrity: sha512-KCuXjYxCZ3ru40dmND+oCLsXyuA8hoseu2SS404Px5ouyS0A99v8X/mdiLqsR5MTAyamMBN7PRwt2Dv3+xGIxw==} + hasBin: true + 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 + dev: false + + /temp-dir@2.0.0: + resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} + engines: {node: '>=8'} + dev: false + + /tempy@0.6.0: + resolution: {integrity: sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==} + engines: {node: '>=10'} + dependencies: + is-stream: 2.0.1 + temp-dir: 2.0.0 + type-fest: 0.16.0 + unique-string: 2.0.0 + dev: false + + /terminal-link@2.1.1: + resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} + engines: {node: '>=8'} + dependencies: + ansi-escapes: 4.3.2 + supports-hyperlinks: 2.3.0 + + /terser-webpack-plugin@5.3.14(webpack@5.98.0): + 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 + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + jest-worker: 27.5.1 + schema-utils: 4.3.0 + serialize-javascript: 6.0.2 + terser: 5.39.0 + webpack: 5.98.0 + dev: false + + /terser@4.8.1: + resolution: {integrity: sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + acorn: 8.14.1 + commander: 2.20.3 + source-map: 0.6.1 + source-map-support: 0.5.21 + dev: true + + /terser@5.14.2: + resolution: {integrity: sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + '@jridgewell/source-map': 0.3.6 + acorn: 8.14.1 + commander: 2.20.3 + source-map-support: 0.5.21 + dev: false + + /terser@5.39.0: + resolution: {integrity: sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==} + engines: {node: '>=10'} + hasBin: true + dependencies: + '@jridgewell/source-map': 0.3.6 + acorn: 8.14.1 + commander: 2.20.3 + source-map-support: 0.5.21 + dev: false + + /test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: false + + /thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + dependencies: + thenify: 3.3.1 + dev: false + + /thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + dependencies: + any-promise: 1.3.0 + dev: false + + /throat@5.0.0: + resolution: {integrity: sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==} + + /throat@6.0.2: + resolution: {integrity: sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==} + dev: false + + /throttle-debounce@3.0.1: + resolution: {integrity: sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==} + engines: {node: '>=10'} + dev: false + + /throttle-debounce@5.0.2: + resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==} + engines: {node: '>=12.22'} + dev: false + + /through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + dev: true + + /thunky@1.1.0: + resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} + dev: false + + /timers-browserify@2.0.12: + resolution: {integrity: sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==} + engines: {node: '>=0.6.0'} + dependencies: + setimmediate: 1.0.5 + dev: false + + /timers-ext@0.1.8: + resolution: {integrity: sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==} + engines: {node: '>=0.12'} + dependencies: + es5-ext: 0.10.64 + next-tick: 1.1.0 + + /tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + dev: false + + /tiny-pinyin@1.3.2: + resolution: {integrity: sha512-uHNGu4evFt/8eNLldazeAM1M8JrMc1jshhJJfVRARTN3yT8HEEibofeQ7QETWQ5ISBjd6fKtTVBCC/+mGS6FpA==} + + /tiny-warning@1.0.3: + resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + dev: false + + /tinycolor2@1.6.0: + resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} + dev: false + + /tinyqueue@2.0.3: + resolution: {integrity: sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==} + dev: false + + /tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + + /to-arraybuffer@1.0.1: + resolution: {integrity: sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==} + dev: false + + /to-fast-properties@1.0.3: + resolution: {integrity: sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==} + engines: {node: '>=0.10.0'} + dev: true + + /to-object-path@0.3.0: + resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + kind-of: 3.2.2 + + /to-regex-range@2.1.1: + resolution: {integrity: sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + is-number: 3.0.0 + repeat-string: 1.6.1 + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + + /to-regex@3.0.2: + resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} + engines: {node: '>=0.10.0'} + requiresBuild: true + 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: + resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} + dev: false + + /toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + dev: false + + /topojson-client@3.1.0: + resolution: {integrity: sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==} + hasBin: true + dependencies: + commander: 2.20.3 + dev: false + + /toposort@2.0.2: + resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==} + dev: false + + /tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + engines: {node: '>=6'} + dependencies: + psl: 1.15.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + /tr46@1.0.1: + resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + dependencies: + punycode: 2.3.1 + dev: false + + /tr46@2.1.0: + resolution: {integrity: sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==} + engines: {node: '>=8'} + dependencies: + punycode: 2.3.1 + + /trim-right@1.0.1: + resolution: {integrity: sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw==} + engines: {node: '>=0.10.0'} + dev: true + + /tryer@1.0.1: + resolution: {integrity: sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==} + dev: false + + /ts-easing@0.2.0: + resolution: {integrity: sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==} + dev: false + + /ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + dev: false + + /ts-node@10.9.2(@types/node@18.19.80)(typescript@4.9.5): + 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 + 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.80 + 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 + dev: true + + /tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: false + + /tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: false + + /tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + /tsutils@3.21.0(typescript@4.9.5): + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + dependencies: + tslib: 1.14.1 + typescript: 4.9.5 + dev: false + + /tty-browserify@0.0.0: + resolution: {integrity: sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==} + dev: false + + /tween-functions@1.2.0: + resolution: {integrity: sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==} + dev: false + + /type-check@0.3.2: + resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.1.2 + dev: false + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + + /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'} + dev: false + + /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'} + dev: false + + /type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + dev: false + + /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'} + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + /typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 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: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} + dependencies: + is-typedarray: 1.0.0 + + /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==} + dev: false + + /typewise@1.0.3: + resolution: {integrity: sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ==} + dependencies: + typewise-core: 1.2.0 + dev: false + + /ua-parser-js@0.7.40: + resolution: {integrity: sha512-us1E3K+3jJppDBa3Tl0L3MOJiGhe1C6P0+nIvQAFYbxlMAx0h81eOwLmU57xgqToduDDPx3y5QsdjPfDu+FgOQ==} + hasBin: true + dev: false + + /ua-parser-js@1.0.40: + resolution: {integrity: sha512-z6PJ8Lml+v3ichVojCiB8toQJBuwR42ySM4ezjXIqXK3M0HczmKQ3LF4rhU55PfD99KEEXQG6yb7iOMyvYuHew==} + hasBin: true + dev: false + + /uglify-js@2.8.29: + resolution: {integrity: sha512-qLq/4y2pjcU3vhlhseXGGJ7VbFO4pBANu0kwl8VCa9KEI0V8VfZIx2Fy3w01iSTA/pGwKZSmu/+I4etLNDdt5w==} + engines: {node: '>=0.8.0'} + hasBin: true + dependencies: + source-map: 0.5.7 + yargs: 3.10.0 + optionalDependencies: + uglify-to-browserify: 1.0.2 + dev: false + + /uglify-to-browserify@1.0.2: + resolution: {integrity: sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==} + requiresBuild: true + dev: false + optional: true + + /umi-request@1.4.0: + resolution: {integrity: sha512-OknwtQZddZHi0Ggi+Vr/olJ7HNMx4AzlywyK0W3NZBT7B0stjeZ9lcztA85dBgdAj3KVk8uPJPZSnGaDjELhrA==} + dependencies: + isomorphic-fetch: 2.2.1 + qs: 6.14.0 + dev: false + + /umi@3.5.43: + resolution: {integrity: sha512-WWusH/o3MTGIJ+S6MiUquz5OwOAQKVdgGHD0CwYBBXcUmwodeZ1mpQSfj8u7VO/OLgVfCmBw8ENsdaWEK6OMtw==} + hasBin: true + dependencies: + '@umijs/bundler-webpack': 3.5.43(react-dom@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) + '@umijs/runtime': 3.5.43(react@16.14.0) + '@umijs/types': 3.5.43(react-dom@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 + dev: false + + /unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==} + dev: false + + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: true + + /undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + + /unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} + engines: {node: '>=4'} + dev: false + + /unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.1 + unicode-property-aliases-ecmascript: 2.1.0 + dev: false + + /unicode-match-property-value-ecmascript@2.2.0: + resolution: {integrity: sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==} + engines: {node: '>=4'} + dev: false + + /unicode-property-aliases-ecmascript@2.1.0: + resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} + engines: {node: '>=4'} + dev: false + + /union-value@1.0.1: + resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} + engines: {node: '>=0.10.0'} + 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: + resolution: {integrity: sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==} + dev: false + + /unique-string@2.0.0: + resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} + engines: {node: '>=8'} + dependencies: + crypto-random-string: 2.0.0 + dev: false + + /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'} + dev: false + + /unquote@1.1.1: + resolution: {integrity: sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==} + dev: false + + /unset-value@1.0.0: + resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dependencies: + has-value: 0.3.1 + isobject: 3.0.1 + + /upath@1.2.0: + resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} + engines: {node: '>=4'} + dev: false + + /update-browserslist-db@1.1.3(browserslist@4.24.4): + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.24.4 + escalade: 3.2.0 + picocolors: 1.1.1 + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.1 + + /urix@0.1.0: + resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==} + deprecated: Please see https://github.com/lydell/urix#deprecated + requiresBuild: true + + /url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + + /url@0.11.4: + resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==} + engines: {node: '>= 0.4'} + dependencies: + punycode: 1.4.1 + qs: 6.14.0 + dev: false + + /use-composed-ref@1.4.0(@types/react@17.0.52): + 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 + dependencies: + '@types/react': 17.0.52 + dev: false + + /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' + dependencies: + '@babel/runtime': 7.26.10 + dequal: 2.0.3 + dev: false + + /use-isomorphic-layout-effect@1.2.0(@types/react@17.0.52): + 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 + dependencies: + '@types/react': 17.0.52 + dev: false + + /use-latest@1.3.0(@types/react@17.0.52): + 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 + dependencies: + '@types/react': 17.0.52 + use-isomorphic-layout-effect: 1.2.0(@types/react@17.0.52) + dev: false + + /use-memo-one@1.1.3: + resolution: {integrity: sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dev: false + + /use-merge-value@1.2.0: + resolution: {integrity: sha512-DXgG0kkgJN45TcyoXL49vJnn55LehnrmoHc7MbKi+QDBvr8dsesqws8UlyIWGHMR+JXgxc1nvY+jDGMlycsUcw==} + peerDependencies: + react: '>= 16.x' + dev: false + + /use-resize-observer@9.1.0: + resolution: {integrity: sha512-R25VqO9Wb3asSD4eqtcxk8sJalvIOYBqS8MNZlpDSQ4l4xMQxC/J7Id9HoTqPq8FwULIn0PVW+OAqF2dyYbjow==} + peerDependencies: + react: 16.8.0 - 18 + react-dom: 16.8.0 - 18 + dependencies: + '@juggle/resize-observer': 3.4.0 + dev: false + + /use-subscription@1.5.1(react@16.14.0): + resolution: {integrity: sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 + dependencies: + object-assign: 4.1.1 + react: 16.14.0 + dev: false + + /use-sync-external-store@1.4.0: + resolution: {integrity: sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + dev: false + + /use@3.1.1: + resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + + /user-home@1.1.1: + resolution: {integrity: sha512-aggiKfEEubv3UwRNqTzLInZpAOmKzwdHqEBmW/hBA/mt99eg+b4VrX6i+IRLxU8+WJYfa33rGwRseg4eElUgsQ==} + engines: {node: '>=0.10.0'} + hasBin: true + dev: true + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + /util.promisify@1.0.0: + resolution: {integrity: sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==} + dependencies: + define-properties: 1.2.1 + object.getownpropertydescriptors: 2.1.8 + dev: true + + /util.promisify@1.0.1: + resolution: {integrity: sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==} + dependencies: + define-properties: 1.2.1 + es-abstract: 1.23.9 + has-symbols: 1.1.0 + object.getownpropertydescriptors: 2.1.8 + dev: false + + /util@0.10.4: + resolution: {integrity: sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==} + dependencies: + inherits: 2.0.3 + dev: false + + /util@0.11.1: + resolution: {integrity: sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==} + dependencies: + inherits: 2.0.3 + dev: false + + /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'} + dev: false + + /utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + dev: false + + /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==} + dev: true + + /v8-compile-cache@2.3.0: + resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} + dev: false + + /v8-to-istanbul@7.1.2: + resolution: {integrity: sha512-TxNb7YEUwkLXCQYeudi6lgQ/SZrzNO4kMdlqVxaZPUIUjCv6iSSypUQX70kNBSERpQ8fk48+d61FXk+tgqcWow==} + engines: {node: '>=10.10.0'} + 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: + resolution: {integrity: sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==} + engines: {node: '>=10.12.0'} + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 1.9.0 + source-map: 0.7.4 + dev: false + + /v8flags@2.1.1: + resolution: {integrity: sha512-SKfhk/LlaXzvtowJabLZwD4K6SGRYeoxA7KJeISlUMAB/NT4CBkZjMq3WceX2Ckm4llwqYVo8TICgsDYCBU2tA==} + engines: {node: '>= 0.10.0'} + dependencies: + user-home: 1.1.1 + dev: true + + /validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + + /validator@13.12.0: + resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==} + engines: {node: '>= 0.10'} + dev: false + + /value-equal@1.0.1: + resolution: {integrity: sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==} + dev: false + + /vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: false + + /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. + dependencies: + '@babel/runtime': 7.26.10 + gl-matrix: 3.4.3 + dev: false + + /vm-browserify@1.1.2: + resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} + dev: false + + /vt-pbf@3.1.3: + resolution: {integrity: sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==} + dependencies: + '@mapbox/point-geometry': 0.1.0 + '@mapbox/vector-tile': 1.3.1 + pbf: 3.3.0 + dev: false + + /w3c-hr-time@1.0.2: + resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} + deprecated: Use your platform's native performance.now() and performance.timeOrigin. + dependencies: + browser-process-hrtime: 1.0.0 + + /w3c-xmlserializer@2.0.0: + resolution: {integrity: sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==} + engines: {node: '>=10'} + dependencies: + xml-name-validator: 3.0.0 + + /walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + dependencies: + makeerror: 1.0.12 + + /warning@3.0.0: + resolution: {integrity: sha512-jMBt6pUrKn5I+OGgtQ4YZLdhIeJmObddh6CsibPxyQ5yPZm1XExSyzC1LCNX7BzhxWgiHmizBWJTHJIjMjTQYQ==} + dependencies: + loose-envify: 1.4.0 + dev: false + + /warning@4.0.3: + resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} + dependencies: + loose-envify: 1.4.0 + dev: false + + /watchpack@2.4.2: + resolution: {integrity: sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==} + engines: {node: '>=10.13.0'} + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + dev: false + + /wbuf@1.7.3: + resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==} + dependencies: + minimalistic-assert: 1.0.1 + dev: false + + /web-worker-helper@0.0.3: + resolution: {integrity: sha512-/TllNPjGenDwjE67M16TD9ALwuY847/zIoH7r+e5rSeG4kEa3HiMTAsUDj80yzIzhtshkv215KfsnQ/RXR3nVA==} + dev: false + + /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==} + dev: false + + /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. + dependencies: + deepmerge: 1.5.2 + javascript-stringify: 2.1.0 + dev: false + + /webpack-dev-middleware@5.3.4(webpack@5.98.0): + resolution: {integrity: sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + dependencies: + colorette: 2.0.20 + memfs: 3.5.3 + mime-types: 2.1.35 + range-parser: 1.2.1 + schema-utils: 4.3.0 + webpack: 5.98.0 + dev: false + + /webpack-dev-server@4.15.2(webpack@5.98.0): + 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 + 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.0 + 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.5.2 + http-proxy-middleware: 2.0.7(@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.0 + selfsigned: 2.4.1 + serve-index: 1.9.1 + sockjs: 0.3.24 + spdy: 4.0.2 + webpack: 5.98.0 + webpack-dev-middleware: 5.3.4(webpack@5.98.0) + ws: 8.18.1 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + dev: false + + /webpack-manifest-plugin@4.1.1(webpack@5.98.0): + resolution: {integrity: sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==} + engines: {node: '>=12.22.0'} + peerDependencies: + webpack: ^4.44.2 || ^5.47.0 + dependencies: + tapable: 2.2.1 + webpack: 5.98.0 + webpack-sources: 2.3.1 + dev: false + + /webpack-sources@1.4.3: + resolution: {integrity: sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==} + dependencies: + source-list-map: 2.0.1 + source-map: 0.6.1 + + /webpack-sources@2.3.1: + resolution: {integrity: sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==} + engines: {node: '>=10.13.0'} + dependencies: + source-list-map: 2.0.1 + source-map: 0.6.1 + dev: false + + /webpack-sources@3.2.3: + resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} + engines: {node: '>=10.13.0'} + dev: false + + /webpack@5.98.0: + resolution: {integrity: sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.6 + '@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.6.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.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.14(webpack@5.98.0) + watchpack: 2.4.2 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + dev: false + + /websocket-driver@0.7.4: + resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} + engines: {node: '>=0.8.0'} + dependencies: + http-parser-js: 0.5.9 + safe-buffer: 5.2.1 + websocket-extensions: 0.1.4 + dev: false + + /websocket-extensions@0.1.4: + resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} + engines: {node: '>=0.8.0'} + dev: false + + /whatwg-encoding@1.0.5: + resolution: {integrity: sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==} + dependencies: + iconv-lite: 0.4.24 + + /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==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + /whatwg-url@7.1.0: + resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + dev: false + + /whatwg-url@8.7.0: + resolution: {integrity: sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==} + engines: {node: '>=10'} + dependencies: + lodash: 4.17.21 + tr46: 2.1.0 + webidl-conversions: 6.1.0 + + /which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + + /which-typed-array@1.1.19: + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} + engines: {node: '>= 0.4'} + 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: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + dependencies: + isexe: 2.0.0 + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + + /window-size@0.1.0: + resolution: {integrity: sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg==} + engines: {node: '>= 0.8.0'} + dev: false + + /wmf@1.0.2: + resolution: {integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==} + engines: {node: '>=0.8'} + dev: false + + /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'} + dev: false + + /wordwrap@0.0.2: + resolution: {integrity: sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q==} + engines: {node: '>=0.4.0'} + dev: false + + /workbox-background-sync@6.6.0: + resolution: {integrity: sha512-jkf4ZdgOJxC9u2vztxLuPT/UjlH7m/nWRQ/MgGL0v8BJHoZdVGJd18Kck+a0e55wGXdqyHO+4IQTk0685g4MUw==} + dependencies: + idb: 7.1.1 + workbox-core: 6.6.0 + dev: false + + /workbox-broadcast-update@6.6.0: + resolution: {integrity: sha512-nm+v6QmrIFaB/yokJmQ/93qIJ7n72NICxIwQwe5xsZiV2aI93MGGyEyzOzDPVz5THEr5rC3FJSsO3346cId64Q==} + dependencies: + workbox-core: 6.6.0 + dev: false + + /workbox-build@6.6.0: + resolution: {integrity: sha512-Tjf+gBwOTuGyZwMz2Nk/B13Fuyeo0Q84W++bebbVsfr9iLkDSo6j6PST8tET9HYA58mlRXwlMGpyWO8ETJiXdQ==} + engines: {node: '>=10.0.0'} + 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.26.10 + '@rollup/plugin-babel': 5.3.1(@babel/core@7.26.10)(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 + dev: false + + /workbox-cacheable-response@6.6.0: + resolution: {integrity: sha512-JfhJUSQDwsF1Xv3EV1vWzSsCOZn4mQ38bWEBR3LdvOxSPgB65gAM6cS2CX8rkkKHRgiLrN7Wxoyu+TuH67kHrw==} + deprecated: workbox-background-sync@6.6.0 + dependencies: + workbox-core: 6.6.0 + dev: false + + /workbox-core@6.6.0: + resolution: {integrity: sha512-GDtFRF7Yg3DD859PMbPAYPeJyg5gJYXuBQAC+wyrWuuXgpfoOrIQIvFRZnQ7+czTIQjIr1DhLEGFzZanAT/3bQ==} + dev: false + + /workbox-expiration@6.6.0: + resolution: {integrity: sha512-baplYXcDHbe8vAo7GYvyAmlS4f6998Jff513L4XvlzAOxcl8F620O91guoJ5EOf5qeXG4cGdNZHkkVAPouFCpw==} + dependencies: + idb: 7.1.1 + workbox-core: 6.6.0 + dev: false + + /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 + dependencies: + workbox-background-sync: 6.6.0 + workbox-core: 6.6.0 + workbox-routing: 6.6.0 + workbox-strategies: 6.6.0 + dev: false + + /workbox-navigation-preload@6.6.0: + resolution: {integrity: sha512-utNEWG+uOfXdaZmvhshrh7KzhDu/1iMHyQOV6Aqup8Mm78D286ugu5k9MFD9SzBT5TcwgwSORVvInaXWbvKz9Q==} + dependencies: + workbox-core: 6.6.0 + dev: false + + /workbox-precaching@6.6.0: + resolution: {integrity: sha512-eYu/7MqtRZN1IDttl/UQcSZFkHP7dnvr/X3Vn6Iw6OsPMruQHiVjjomDFCNtd8k2RdjLs0xiz9nq+t3YVBcWPw==} + dependencies: + workbox-core: 6.6.0 + workbox-routing: 6.6.0 + workbox-strategies: 6.6.0 + dev: false + + /workbox-range-requests@6.6.0: + resolution: {integrity: sha512-V3aICz5fLGq5DpSYEU8LxeXvsT//mRWzKrfBOIxzIdQnV/Wj7R+LyJVTczi4CQ4NwKhAaBVaSujI1cEjXW+hTw==} + dependencies: + workbox-core: 6.6.0 + dev: false + + /workbox-recipes@6.6.0: + resolution: {integrity: sha512-TFi3kTgYw73t5tg73yPVqQC8QQjxJSeqjXRO4ouE/CeypmP2O/xqmB/ZFBBQazLTPxILUQ0b8aeh0IuxVn9a6A==} + 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 + dev: false + + /workbox-routing@6.6.0: + resolution: {integrity: sha512-x8gdN7VDBiLC03izAZRfU+WKUXJnbqt6PG9Uh0XuPRzJPpZGLKce/FkOX95dWHRpOHWLEq8RXzjW0O+POSkKvw==} + dependencies: + workbox-core: 6.6.0 + dev: false + + /workbox-strategies@6.6.0: + resolution: {integrity: sha512-eC07XGuINAKUWDnZeIPdRdVja4JQtTuc35TZ8SwMb1ztjp7Ddq2CJ4yqLvWzFWGlYI7CG/YGqaETntTxBGdKgQ==} + dependencies: + workbox-core: 6.6.0 + dev: false + + /workbox-streams@6.6.0: + resolution: {integrity: sha512-rfMJLVvwuED09CnH1RnIep7L9+mj4ufkTyDPVaXPKlhi9+0czCu+SJggWCIFbPpJaAZmp2iyVGLqS3RUmY3fxg==} + dependencies: + workbox-core: 6.6.0 + workbox-routing: 6.6.0 + dev: false + + /workbox-sw@6.6.0: + resolution: {integrity: sha512-R2IkwDokbtHUE4Kus8pKO5+VkPHD2oqTgl+XJwh4zbF1HyjAbgNmK/FneZHVU7p03XUt9ICfuGDYISWG9qV/CQ==} + dev: false + + /workbox-webpack-plugin@6.6.0(webpack@5.98.0): + resolution: {integrity: sha512-xNZIZHalboZU66Wa7x1YkjIqEy1gTR+zPM+kjrYJzqN7iurYZBctBLISyScjhkJKYuRrZUP0iqViZTh8rS0+3A==} + engines: {node: '>=10.0.0'} + peerDependencies: + webpack: ^4.4.0 || ^5.9.0 + dependencies: + fast-json-stable-stringify: 2.1.0 + pretty-bytes: 5.6.0 + upath: 1.2.0 + webpack: 5.98.0 + webpack-sources: 1.4.3 + workbox-build: 6.6.0 + transitivePeerDependencies: + - '@types/babel__core' + - supports-color + dev: false + + /workbox-window@6.6.0: + resolution: {integrity: sha512-L4N9+vka17d16geaJXXRjENLFldvkWy7JyGxElRD0JvBxvFEd8LOhr+uXCcar/NzAmIBRv9EZ+M+Qr4mOoBITw==} + dependencies: + '@types/trusted-types': 2.0.7 + workbox-core: 6.6.0 + dev: false + + /wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + dev: false + + /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==} + 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: + 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 + dev: false + + /xlsx@0.17.5: + resolution: {integrity: sha512-lXNU0TuYsvElzvtI6O7WIVb9Zar1XYw7Xb3VAx2wn8N/n0whBYrCnHMxtFyIiUU1Wjf09WzmLALDfBO5PqTb1g==} + engines: {node: '>=0.8'} + hasBin: true + 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 + dev: false + + /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'} + dev: false + + /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==} + dev: true + + /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.0: + resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==} + engines: {node: '>= 14'} + hasBin: true + dev: false + + /yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + + /yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + dev: false + + /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'} + 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: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + 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 + dev: false + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + 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: + resolution: {integrity: sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A==} + dependencies: + camelcase: 1.2.1 + cliui: 2.1.0 + decamelize: 1.2.0 + window-size: 0.1.0 + dev: false + + /yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + dev: true + + /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'} + requiresBuild: true + dependencies: + execa: 0.8.0 + is-ci: 1.2.1 + normalize-path: 1.0.0 + strip-indent: 2.0.0 + dev: true + + /zscroller@0.4.8: + resolution: {integrity: sha512-G5NiNLKx2+QhhvZi2yV1jjVXY50otktxkseX2hG2N/eixohOUk0AY8ZpbAxNqS9oJS/NxItCsowupy2tsXxAMw==} + dependencies: + babel-runtime: 6.26.0 + dev: false diff --git a/frontend/public/assets/badge/default.svg b/frontend/public/assets/badge/default.svg new file mode 100644 index 00000000..6d546454 --- /dev/null +++ b/frontend/public/assets/badge/default.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + \ 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..ae7b765c --- /dev/null +++ b/frontend/public/assets/badge/error.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + \ 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..36215999 --- /dev/null +++ b/frontend/public/assets/badge/processing.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + \ 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..a0f6e181 --- /dev/null +++ b/frontend/public/assets/badge/success.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + \ 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..0721dccb --- /dev/null +++ b/frontend/public/assets/badge/warning.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + \ 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..dc0f4b7a --- /dev/null +++ b/frontend/public/assets/cluster/abandoned.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..871e2a12 --- /dev/null +++ b/frontend/public/assets/cluster/cluster.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + \ 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..8c07167a --- /dev/null +++ b/frontend/public/assets/cluster/creating.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..42e04bda --- /dev/null +++ b/frontend/public/assets/cluster/deleted.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..c75b1c1b --- /dev/null +++ b/frontend/public/assets/cluster/deleting.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..dc0f4b7a --- /dev/null +++ b/frontend/public/assets/cluster/error.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..dca17d56 --- /dev/null +++ b/frontend/public/assets/cluster/failover.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..dca17d56 --- /dev/null +++ b/frontend/public/assets/cluster/movingout.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..dca17d56 --- /dev/null +++ b/frontend/public/assets/cluster/operating.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..c75b1c1b --- /dev/null +++ b/frontend/public/assets/cluster/restarting.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..62f273c3 --- /dev/null +++ b/frontend/public/assets/cluster/running.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..c75b1c1b --- /dev/null +++ b/frontend/public/assets/cluster/starting.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..42e04bda --- /dev/null +++ b/frontend/public/assets/cluster/stopped.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..c75b1c1b --- /dev/null +++ b/frontend/public/assets/cluster/stopping.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..dca17d56 --- /dev/null +++ b/frontend/public/assets/cluster/switchover.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..8c07167a --- /dev/null +++ b/frontend/public/assets/cluster/takingover.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..dc0f4b7a --- /dev/null +++ b/frontend/public/assets/cluster/unavailable.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..dca17d56 --- /dev/null +++ b/frontend/public/assets/cluster/upgrading.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..98cdae2c --- /dev/null +++ b/frontend/public/assets/common/403.svg @@ -0,0 +1,517 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..51765a45 --- /dev/null +++ b/frontend/public/assets/common/404.svg @@ -0,0 +1,323 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..0042638a --- /dev/null +++ b/frontend/public/assets/common/500.svg @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..f9db923e --- /dev/null +++ b/frontend/public/assets/common/crash.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..af2eea95 --- /dev/null +++ b/frontend/public/assets/common/empty.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..d3995857 --- /dev/null +++ b/frontend/public/assets/common/guide.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..deb75b43 --- /dev/null +++ b/frontend/public/assets/common/no_auth.svg @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..0cc5fd6d --- /dev/null +++ b/frontend/public/assets/icon/client.svg @@ -0,0 +1,25 @@ + + + + + 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..5f924e36 --- /dev/null +++ b/frontend/public/assets/icon/close.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + \ 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..22289537 --- /dev/null +++ b/frontend/public/assets/icon/ellipsis.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ 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..02083a10 --- /dev/null +++ b/frontend/public/assets/icon/fit_canvas.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + \ 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..a45c56ad --- /dev/null +++ b/frontend/public/assets/icon/more.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..6d87c148 --- /dev/null +++ b/frontend/public/assets/icon/obproxy.svg @@ -0,0 +1,26 @@ + + + + + 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..50b0cb2b --- /dev/null +++ b/frontend/public/assets/icon/reset.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + \ 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..e2750330 --- /dev/null +++ b/frontend/public/assets/icon/settings.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..e40ca5c4 --- /dev/null +++ b/frontend/public/assets/icon/success.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..93cefcb7 --- /dev/null +++ b/frontend/public/assets/icon/warning.svg @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..52e0fbd3 --- /dev/null +++ b/frontend/public/assets/login/background_img.svg @@ -0,0 +1,42 @@ + + + + + 编组 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..841049db --- /dev/null +++ b/frontend/public/assets/logo/oceanbase_logo.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..076a255f --- /dev/null +++ b/frontend/public/assets/logo/ocp_express_favicon.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ 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..75afc0c4 --- /dev/null +++ b/frontend/public/assets/logo/ocp_express_icon.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + \ 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..6176610e --- /dev/null +++ b/frontend/public/assets/logo/ocp_express_logo_en.svg @@ -0,0 +1,51 @@ + + + + + 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..9d061b98 --- /dev/null +++ b/frontend/public/assets/logo/ocp_express_logo_zh.svg @@ -0,0 +1,49 @@ + + + + + 编组 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..b6a7b8f8 --- /dev/null +++ b/frontend/public/assets/logo/ocp_express_simple_logo_en.svg @@ -0,0 +1,50 @@ + + + + + 编组 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..cd3f8517 --- /dev/null +++ b/frontend/public/assets/logo/ocp_express_simple_logo_zh.svg @@ -0,0 +1,68 @@ + + + + + 编组 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..e76c6910 --- /dev/null +++ b/frontend/public/assets/logo/ocp_express_simple_logo_zh_dark.svg @@ -0,0 +1,68 @@ + + + + + 编组 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..dfab0e7f --- /dev/null +++ b/frontend/public/assets/overview/obproxy.svg @@ -0,0 +1,40 @@ + + + + + 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..00d54c30 --- /dev/null +++ b/frontend/public/assets/overview/tenant.svg @@ -0,0 +1,89 @@ + + + + + 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..cb550f10 --- /dev/null +++ b/frontend/public/assets/server/creating.svg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..78ef262b --- /dev/null +++ b/frontend/public/assets/server/deleted.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..d4a7e13b --- /dev/null +++ b/frontend/public/assets/server/deleting.svg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..78ef262b --- /dev/null +++ b/frontend/public/assets/server/disabled.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..46690ac6 --- /dev/null +++ b/frontend/public/assets/server/error.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..78ef262b --- /dev/null +++ b/frontend/public/assets/server/process_stopped.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..d4a7e13b --- /dev/null +++ b/frontend/public/assets/server/process_stopping.svg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..d4a7e13b --- /dev/null +++ b/frontend/public/assets/server/restarting.svg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..1230b9f4 --- /dev/null +++ b/frontend/public/assets/server/running.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..12b33a9b --- /dev/null +++ b/frontend/public/assets/server/server.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + \ 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..78ef262b --- /dev/null +++ b/frontend/public/assets/server/service_stopped.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..d4a7e13b --- /dev/null +++ b/frontend/public/assets/server/service_stopping.svg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..d4a7e13b --- /dev/null +++ b/frontend/public/assets/server/starting.svg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..78ef262b --- /dev/null +++ b/frontend/public/assets/server/stopped.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..d4a7e13b --- /dev/null +++ b/frontend/public/assets/server/stopping.svg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..46690ac6 --- /dev/null +++ b/frontend/public/assets/server/unavailable.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..275e992b --- /dev/null +++ b/frontend/public/assets/server/warning.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..ebec83e7 --- /dev/null +++ b/frontend/public/assets/task/subtask_failed.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + \ 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..4e127dd9 --- /dev/null +++ b/frontend/public/assets/task/subtask_pending.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + \ 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..4e127dd9 --- /dev/null +++ b/frontend/public/assets/task/subtask_ready.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + \ 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..316b6b87 --- /dev/null +++ b/frontend/public/assets/task/subtask_running.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..9cb34690 --- /dev/null +++ b/frontend/public/assets/task/subtask_successful.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + \ 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..456537ce --- /dev/null +++ b/frontend/public/assets/tenant/deadlock.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + \ 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..ebea492d --- /dev/null +++ b/frontend/public/assets/tenant/no_deadlock.svg @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..fd999773 --- /dev/null +++ b/frontend/public/assets/tenant/no_deadlock_data.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..641c2753 --- /dev/null +++ b/frontend/public/assets/tenant/polyline.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + \ 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..f6ecf5c2 --- /dev/null +++ b/frontend/public/assets/tenant/tenant.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + \ 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..86112404 --- /dev/null +++ b/frontend/public/assets/unit/cpu.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ 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..44cff0ad --- /dev/null +++ b/frontend/public/assets/unit/disk.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ 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..9487e5c3 --- /dev/null +++ b/frontend/public/assets/unit/memory.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + \ 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..bf0191db --- /dev/null +++ b/frontend/public/assets/unit/region.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ 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..861d31cc --- /dev/null +++ b/frontend/public/assets/unit/replica.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + \ 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..25cc85f6 --- /dev/null +++ b/frontend/public/assets/unit/server.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + \ 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..67e5b0df --- /dev/null +++ b/frontend/public/assets/unit/tenant.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ 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..cdffcf62 --- /dev/null +++ b/frontend/public/assets/unit/unit.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ 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..b1ba4571 --- /dev/null +++ b/frontend/public/assets/unit/zone.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ 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..2345a998 --- /dev/null +++ b/frontend/public/assets/zone/creating.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..5c0f79e8 --- /dev/null +++ b/frontend/public/assets/zone/deleted.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..5b9ebcaf --- /dev/null +++ b/frontend/public/assets/zone/deleting.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..5c0f79e8 --- /dev/null +++ b/frontend/public/assets/zone/disabled.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..b636e0ff --- /dev/null +++ b/frontend/public/assets/zone/error.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..ecea75d1 --- /dev/null +++ b/frontend/public/assets/zone/operating.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..5b9ebcaf --- /dev/null +++ b/frontend/public/assets/zone/restarting.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..7fd6878c --- /dev/null +++ b/frontend/public/assets/zone/running.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..5c0f79e8 --- /dev/null +++ b/frontend/public/assets/zone/service_stopped.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..5b9ebcaf --- /dev/null +++ b/frontend/public/assets/zone/starting.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..5c0f79e8 --- /dev/null +++ b/frontend/public/assets/zone/stopped.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..5b9ebcaf --- /dev/null +++ b/frontend/public/assets/zone/stopping.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..b636e0ff --- /dev/null +++ b/frontend/public/assets/zone/unavailable.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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/tsconfig.json b/frontend/tsconfig.json new file mode 100644 index 00000000..54a96301 --- /dev/null +++ b/frontend/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "outDir": "build/dist", + "module": "esnext", + "target": "esnext", + "lib": ["esnext", "dom"], + "sourceMap": true, + "baseUrl": ".", + "jsx": "react", + "allowSyntheticDefaultImports": true, + "moduleResolution": "node", + "forceConsistentCasingInFileNames": true, + "noImplicitReturns": true, + "suppressImplicitAnyIndexErrors": true, + "noUnusedLocals": true, + "allowJs": true, + "experimentalDecorators": true, + "strict": true, + "paths": { + "@/*": ["./src/*"], + "@@/*": ["./src/.umi/*"] + }, + "typeRoots": ["./", "./src/typing/env", "./src/service/ocp-express"] + }, + "exclude": ["node_modules", "build", "dist"] +} diff --git a/frontend/tslint.json b/frontend/tslint.json new file mode 100644 index 00000000..4a0e93c5 --- /dev/null +++ b/frontend/tslint.json @@ -0,0 +1,25 @@ +{ + "extends": ["tslint:latest", "tslint-react", "tslint-config-prettier"], + "rules": { + "no-empty": false, + "no-unused-variable": true, + "no-var-requires": false, + "no-submodule-imports": false, + "object-literal-sort-keys": false, + "jsx-no-lambda": false, + "no-implicit-dependencies": false, + "ordered-imports": false, + "no-empty-interface": false, + "interface-name": false + }, + "jsRules": { + "no-empty": false, + "object-literal-sort-keys": false + }, + "linterOptions": { + "exclude": ["src/locale"] + }, + "globals": { + "__": true + } +} diff --git a/frontend/typings.d.ts b/frontend/typings.d.ts new file mode 100644 index 00000000..8953d801 --- /dev/null +++ b/frontend/typings.d.ts @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +import type { ButtonProps } from '@oceanbase/design/es/button'; +import type { PopconfirmProps } from '@oceanbase/design/es/popconfirm'; +import type { TooltipProps } from '@oceanbase/design/es/tooltip'; + +declare module '*.less'; +declare module '@/config/*'; + +declare global { + namespace NodeJS { + interface ProcessEnv { + NODE_ENV?: 'development' | 'production'; + OBSHELL_PROXY?: string; + } + } + + interface Window { + __OCP_REPORT_DATA?: any; + __OCP_REPORT_LOCALE?: 'zh-CN' | 'en-US'; + Tracert: any; + } + + namespace Global { + interface AppInfo { + buildVersion: string; + buildTime: string; + } + + interface ChartDataItem { + value?: number; + [key: string]: any; + } + + type ChartData = ChartDataItem[]; + + type AccessibleField = ''; + + type MonitorApp = 'OB' | 'ODP' | 'HOST'; + + type MonitorScope = + | 'app' + | 'obregion' + | 'ob_cluster_id' + | 'obproxy_cluster' + | 'obproxy_cluster_id' + | 'tenant_name' + | 'obzone' + | 'svr_ip' + | 'mount_point' + | 'mount_label' + | 'task_type' + | 'process' + | 'device' + | 'cpu'; + + interface OperationItem { + value: string; + label: string; + modalTitle?: string; + divider?: boolean; + isDanger?: boolean; + accessibleField?: + | 'readAccessible' + | 'createAccessible' + | 'updateAccessible' + | 'deleteAccessible' + // 下载主机日志,属于主机的通用权限 + | 'readHostAccessible' + // 查看任务详情,属于任务的通用权限 + | 'readTaskAccessible'; + buttonProps?: ButtonProps; + tooltip?: Omit; + popconfirm?: PopconfirmProps; + } + + interface StatusItem { + value: string | boolean; + label: string; + badgeStatus?: 'success' | 'processing' | 'error' | 'default' | 'warning'; + tagColor?: string; + color?: string; + operations?: OperationItem[]; + [key: string]: any; + } + } +} From deae4d0453b78a8a7ade09e0d0be14e142416e1e Mon Sep 17 00:00:00 2001 From: obdev Date: Fri, 18 Apr 2025 03:02:54 +0000 Subject: [PATCH 031/113] =?UTF-8?q?PullRequest:=20387=20chore():=20?= =?UTF-8?q?=E5=89=8D=E7=AB=AF=E4=BB=A3=E7=A0=81/2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/app.ts | 54 ++ frontend/src/asset/drag_icon.svg | 27 + frontend/src/asset/drilldown.svg | 25 + frontend/src/asset/fail.svg | 30 ++ frontend/src/asset/monitor.svg | 33 ++ frontend/src/asset/sqlDigest.svg | 24 + frontend/src/asset/success.svg | 76 +++ frontend/src/component/Access.tsx | 103 ++++ frontend/src/component/Chart/index.tsx | 143 ++++++ .../src/component/CheckboxPopover/index.less | 19 + .../component/CheckboxPopover/index.style.ts | 10 + .../src/component/CheckboxPopover/index.tsx | 168 ++++++ .../component/ComparisonMetricChart/Item.tsx | 167 ++++++ .../component/ComparisonMetricChart/index.tsx | 67 +++ .../src/component/ContentWithIcon/index.less | 38 ++ .../component/ContentWithIcon/index.style.ts | 23 + .../src/component/ContentWithIcon/index.tsx | 96 ++++ .../src/component/ContentWithInfo/index.less | 28 + .../component/ContentWithInfo/index.style.ts | 18 + .../src/component/ContentWithInfo/index.tsx | 35 ++ .../component/ContentWithQuestion/index.tsx | 58 +++ .../PrivilegesCheckbox.tsx | 132 +++++ .../DatabasePrivilegeTransfer/index.less | 126 +++++ .../DatabasePrivilegeTransfer/index.style.ts | 89 ++++ .../DatabasePrivilegeTransfer/index.tsx | 394 ++++++++++++++ frontend/src/component/Empty/index.less | 44 ++ frontend/src/component/Empty/index.style.ts | 26 + frontend/src/component/Empty/index.tsx | 78 +++ frontend/src/component/ErrorBoundary.tsx | 102 ++++ .../src/component/FilterDropdown/index.less | 242 +++++++++ .../component/FilterDropdown/index.style.ts | 43 ++ .../src/component/FilterDropdown/index.tsx | 190 +++++++ .../src/component/FormEditTable/EditCell.tsx | 153 ++++++ .../src/component/FormEditTable/EditRow.tsx | 25 + .../src/component/FormEditTable/index.less | 150 ++++++ .../component/FormEditTable/index.style.ts | 69 +++ .../src/component/FormEditTable/index.tsx | 482 ++++++++++++++++++ .../FormEditZoneReplicaTable/index.tsx | 301 +++++++++++ .../src/component/FormPrimaryZone/index.less | 107 ++++ .../component/FormPrimaryZone/index.style.ts | 73 +++ .../src/component/FormPrimaryZone/index.tsx | 354 +++++++++++++ frontend/src/component/FormTable/index.less | 15 + .../src/component/FormTable/index.style.ts | 10 + frontend/src/component/FormTable/index.tsx | 182 +++++++ frontend/src/component/FrameBox.tsx | 36 ++ frontend/src/component/HostMonitorSearch.tsx | 120 +++++ frontend/src/component/IconFont.tsx | 67 +++ .../src/component/ModifyUserPasswordModal.tsx | 289 +++++++++++ frontend/src/component/MouseTooltip.tsx | 93 ++++ frontend/src/component/MyDropdown.tsx | 125 +++++ frontend/src/component/MyInput.tsx | 40 ++ frontend/src/component/MySelect.tsx | 35 ++ frontend/src/component/OCPLogo.tsx | 49 ++ frontend/src/component/PackageSelect.tsx | 230 +++++++++ frontend/src/component/Password.tsx | 53 ++ .../src/component/RenderConnectionString.tsx | 64 +++ .../src/component/SelectAllAndClearRender.tsx | 55 ++ .../src/component/SelectAndInputGroup.tsx | 86 ++++ .../src/component/SelectDropdownRender.tsx | 49 ++ .../component/StartParamSelectAndInput.tsx | 188 +++++++ .../src/component/common/ServerDropdown.tsx | 121 +++++ .../src/component/common/ServerSelect.tsx | 135 +++++ .../src/component/common/TenantDropdown.tsx | 99 ++++ .../src/component/common/TenantSelect.tsx | 83 +++ frontend/src/component/common/UserSelect.tsx | 57 +++ 65 files changed, 6703 insertions(+) create mode 100644 frontend/src/app.ts create mode 100644 frontend/src/asset/drag_icon.svg create mode 100644 frontend/src/asset/drilldown.svg create mode 100644 frontend/src/asset/fail.svg create mode 100644 frontend/src/asset/monitor.svg create mode 100644 frontend/src/asset/sqlDigest.svg create mode 100644 frontend/src/asset/success.svg create mode 100644 frontend/src/component/Access.tsx create mode 100644 frontend/src/component/Chart/index.tsx create mode 100644 frontend/src/component/CheckboxPopover/index.less create mode 100644 frontend/src/component/CheckboxPopover/index.style.ts create mode 100644 frontend/src/component/CheckboxPopover/index.tsx create mode 100644 frontend/src/component/ComparisonMetricChart/Item.tsx create mode 100644 frontend/src/component/ComparisonMetricChart/index.tsx create mode 100644 frontend/src/component/ContentWithIcon/index.less create mode 100644 frontend/src/component/ContentWithIcon/index.style.ts create mode 100644 frontend/src/component/ContentWithIcon/index.tsx create mode 100644 frontend/src/component/ContentWithInfo/index.less create mode 100644 frontend/src/component/ContentWithInfo/index.style.ts create mode 100644 frontend/src/component/ContentWithInfo/index.tsx create mode 100644 frontend/src/component/ContentWithQuestion/index.tsx create mode 100644 frontend/src/component/DatabasePrivilegeTransfer/PrivilegesCheckbox.tsx create mode 100644 frontend/src/component/DatabasePrivilegeTransfer/index.less create mode 100644 frontend/src/component/DatabasePrivilegeTransfer/index.style.ts create mode 100644 frontend/src/component/DatabasePrivilegeTransfer/index.tsx create mode 100644 frontend/src/component/Empty/index.less create mode 100644 frontend/src/component/Empty/index.style.ts create mode 100644 frontend/src/component/Empty/index.tsx create mode 100644 frontend/src/component/ErrorBoundary.tsx create mode 100644 frontend/src/component/FilterDropdown/index.less create mode 100644 frontend/src/component/FilterDropdown/index.style.ts create mode 100644 frontend/src/component/FilterDropdown/index.tsx create mode 100644 frontend/src/component/FormEditTable/EditCell.tsx create mode 100644 frontend/src/component/FormEditTable/EditRow.tsx create mode 100644 frontend/src/component/FormEditTable/index.less create mode 100644 frontend/src/component/FormEditTable/index.style.ts create mode 100644 frontend/src/component/FormEditTable/index.tsx create mode 100644 frontend/src/component/FormEditZoneReplicaTable/index.tsx create mode 100644 frontend/src/component/FormPrimaryZone/index.less create mode 100644 frontend/src/component/FormPrimaryZone/index.style.ts create mode 100644 frontend/src/component/FormPrimaryZone/index.tsx create mode 100644 frontend/src/component/FormTable/index.less create mode 100644 frontend/src/component/FormTable/index.style.ts create mode 100644 frontend/src/component/FormTable/index.tsx create mode 100644 frontend/src/component/FrameBox.tsx create mode 100644 frontend/src/component/HostMonitorSearch.tsx create mode 100644 frontend/src/component/IconFont.tsx create mode 100644 frontend/src/component/ModifyUserPasswordModal.tsx create mode 100644 frontend/src/component/MouseTooltip.tsx create mode 100644 frontend/src/component/MyDropdown.tsx create mode 100644 frontend/src/component/MyInput.tsx create mode 100644 frontend/src/component/MySelect.tsx create mode 100644 frontend/src/component/OCPLogo.tsx create mode 100644 frontend/src/component/PackageSelect.tsx create mode 100644 frontend/src/component/Password.tsx create mode 100644 frontend/src/component/RenderConnectionString.tsx create mode 100644 frontend/src/component/SelectAllAndClearRender.tsx create mode 100644 frontend/src/component/SelectAndInputGroup.tsx create mode 100644 frontend/src/component/SelectDropdownRender.tsx create mode 100644 frontend/src/component/StartParamSelectAndInput.tsx create mode 100644 frontend/src/component/common/ServerDropdown.tsx create mode 100644 frontend/src/component/common/ServerSelect.tsx create mode 100644 frontend/src/component/common/TenantDropdown.tsx create mode 100644 frontend/src/component/common/TenantSelect.tsx create mode 100644 frontend/src/component/common/UserSelect.tsx diff --git a/frontend/src/app.ts b/frontend/src/app.ts new file mode 100644 index 00000000..e93ef1a5 --- /dev/null +++ b/frontend/src/app.ts @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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/drag_icon.svg b/frontend/src/asset/drag_icon.svg new file mode 100644 index 00000000..31f061c5 --- /dev/null +++ b/frontend/src/asset/drag_icon.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + \ 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..abc3d980 --- /dev/null +++ b/frontend/src/asset/drilldown.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + \ 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..2f1c83bc --- /dev/null +++ b/frontend/src/asset/fail.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + \ 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..aa981c76 --- /dev/null +++ b/frontend/src/asset/monitor.svg @@ -0,0 +1,33 @@ + + + + + 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..07418ec3 --- /dev/null +++ b/frontend/src/asset/sqlDigest.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + \ 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..2f62ecbb --- /dev/null +++ b/frontend/src/asset/success.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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..aba24a8d --- /dev/null +++ b/frontend/src/component/Access.tsx @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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/Chart/index.tsx b/frontend/src/component/Chart/index.tsx new file mode 100644 index 00000000..8f8b3cd1 --- /dev/null +++ b/frontend/src/component/Chart/index.tsx @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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..550fe56b --- /dev/null +++ b/frontend/src/component/CheckboxPopover/index.less @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +.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..f14b9686 --- /dev/null +++ b/frontend/src/component/CheckboxPopover/index.tsx @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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/ComparisonMetricChart/Item.tsx b/frontend/src/component/ComparisonMetricChart/Item.tsx new file mode 100644 index 00000000..2cedf99c --- /dev/null +++ b/frontend/src/component/ComparisonMetricChart/Item.tsx @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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..bd50361f --- /dev/null +++ b/frontend/src/component/ComparisonMetricChart/index.tsx @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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..8b8d51df --- /dev/null +++ b/frontend/src/component/ContentWithIcon/index.less @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +.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..1251fbb2 --- /dev/null +++ b/frontend/src/component/ContentWithIcon/index.tsx @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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..c11b8fbc --- /dev/null +++ b/frontend/src/component/ContentWithInfo/index.less @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +@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..67fea050 --- /dev/null +++ b/frontend/src/component/ContentWithInfo/index.tsx @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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..682a0174 --- /dev/null +++ b/frontend/src/component/ContentWithQuestion/index.tsx @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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/DatabasePrivilegeTransfer/PrivilegesCheckbox.tsx b/frontend/src/component/DatabasePrivilegeTransfer/PrivilegesCheckbox.tsx new file mode 100644 index 00000000..aa41cc86 --- /dev/null +++ b/frontend/src/component/DatabasePrivilegeTransfer/PrivilegesCheckbox.tsx @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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..c7ad299d --- /dev/null +++ b/frontend/src/component/DatabasePrivilegeTransfer/index.less @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +@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..814d4736 --- /dev/null +++ b/frontend/src/component/DatabasePrivilegeTransfer/index.tsx @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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/Empty/index.less b/frontend/src/component/Empty/index.less new file mode 100644 index 00000000..090bd20a --- /dev/null +++ b/frontend/src/component/Empty/index.less @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +.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..59b5c128 --- /dev/null +++ b/frontend/src/component/Empty/index.tsx @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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..5dded931 --- /dev/null +++ b/frontend/src/component/ErrorBoundary.tsx @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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..fd7ea9b2 --- /dev/null +++ b/frontend/src/component/FilterDropdown/index.less @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +@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..e9492862 --- /dev/null +++ b/frontend/src/component/FilterDropdown/index.tsx @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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..33fafa3b --- /dev/null +++ b/frontend/src/component/FormEditTable/EditCell.tsx @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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..3e03d64e --- /dev/null +++ b/frontend/src/component/FormEditTable/EditRow.tsx @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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..69efd8e0 --- /dev/null +++ b/frontend/src/component/FormEditTable/index.less @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +.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..eb362d14 --- /dev/null +++ b/frontend/src/component/FormEditTable/index.tsx @@ -0,0 +1,482 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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.handleCancel(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..822f93a5 --- /dev/null +++ b/frontend/src/component/FormEditZoneReplicaTable/index.tsx @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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; + zones: any[]; + 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, zones, 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(zones || [], 'name', record.name); + + console.log(zones, 'fieldComponent zones'); + // TODO: 待后端添加字段进行修改 + let idleCpuCore, idleMemoryInBytes; + if (zoneData?.servers?.length > 0 && zoneData?.servers[0]?.stats) { + const { idleCpuCoreTotal, idleMemoryInBytesTotal } = getUnitSpecLimit( + zoneData?.servers[0]?.stats + ); + + idleCpuCore = idleCpuCoreTotal; + idleMemoryInBytes = idleMemoryInBytesTotal; + } + + 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 / 8); + + 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..780212b7 --- /dev/null +++ b/frontend/src/component/FormPrimaryZone/index.less @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +@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..4e20537b --- /dev/null +++ b/frontend/src/component/FormPrimaryZone/index.tsx @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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..b2e6ea2b --- /dev/null +++ b/frontend/src/component/FormTable/index.less @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +.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..3570d6fc --- /dev/null +++ b/frontend/src/component/FormTable/index.tsx @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +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/FrameBox.tsx b/frontend/src/component/FrameBox.tsx new file mode 100644 index 00000000..6f33d134 --- /dev/null +++ b/frontend/src/component/FrameBox.tsx @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 OceanBase + * OCP Express is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +import React from 'react'; + +interface Props { + data: string; + title: string; +} + +/** + * 使用 iframe 用于展示后端返回的文件内容,例如 ASH、AWR 报告文件 + */ +const FrameBox: React.FC = ({ title, data }) => { + return ( +