From 8fb32e0d928be56307ac6e1aeea6ea037e9a64af Mon Sep 17 00:00:00 2001 From: Rongfeng Fu Date: Wed, 29 Nov 2023 15:51:41 +0800 Subject: [PATCH] V2.4.0 (#184) --- _cmd.py | 105 +- _deploy.py | 26 +- _environ.py | 8 +- _errno.py | 31 +- _mirror.py | 31 +- _plugin.py | 1 + _rpm.py | 3 + _types.py | 7 +- core.py | 204 +- example/all-components-min.yaml | 9 +- example/all-components.yaml | 9 +- example/autodeploy/all-components.yaml | 7 +- example/autodeploy/default-example.yaml | 7 +- example/autodeploy/distributed-example.yaml | 7 +- ...uted-with-obproxy-and-obagent-example.yaml | 7 +- .../distributed-with-obproxy-example.yaml | 7 +- example/autodeploy/single-example.yaml | 7 +- .../single-with-obproxy-example.yaml | 7 +- example/default-components-min.yaml | 9 +- example/default-components.yaml | 9 +- example/distributed-example.yaml | 9 +- example/distributed-with-obproxy-example.yaml | 9 +- ...omponents-with-prometheus-and-grafana.yaml | 9 +- example/local-example.yaml | 9 +- example/mini-distributed-example.yaml | 9 +- ...mini-distributed-with-obproxy-example.yaml | 9 +- example/mini-local-example.yaml | 9 +- example/mini-single-example.yaml | 9 +- example/mini-single-with-obproxy-example.yaml | 9 +- ...with-obproxy-and-configserver-example.yaml | 9 +- ...uted-with-obproxy-and-obagent-example.yaml | 9 +- .../distributed-with-obproxy-example.yaml | 9 +- .../oceanbase-3.x/distributed-example.yaml | 3 - ...uted-with-obproxy-and-obagent-example.yaml | 3 - .../distributed-with-obproxy-example.yaml | 3 - example/oceanbase-3.x/local-example.yaml | 3 - .../mini-distributed-example.yaml | 3 - ...mini-distributed-with-obproxy-example.yaml | 3 - example/oceanbase-3.x/mini-local-example.yaml | 3 - .../oceanbase-3.x/mini-single-example.yaml | 3 - .../mini-single-with-obproxy-example.yaml | 3 - example/oceanbase-3.x/single-example.yaml | 3 - .../single-with-obproxy-example.yaml | 3 - ...d-with-obagent-and-prometheus-example.yaml | 9 +- example/single-example.yaml | 9 +- example/single-with-obproxy-example.yaml | 9 +- init.sh | 2 + plugins/ob-configserver/1.0.0/display.py | 2 +- plugins/obproxy/3.1.0/ocp_check.py | 11 +- .../1.0/analyze_log.py | 105 + .../oceanbase-diagnostic-tool/1.0/checker.py | 96 + .../1.0/gather_all.py | 25 +- .../1.0/gather_clog.py | 25 +- .../1.0/gather_log.py | 25 +- .../1.0/gather_obproxy_log.py | 25 +- .../1.0/gather_perf.py | 14 +- .../1.0/gather_plan_monitor.py | 14 +- .../1.0/gather_slog.py | 25 +- .../1.0/gather_stack.py | 14 +- .../1.0/gather_sysstat.py | 14 +- .../1.0/generate_config.py | 16 +- .../1.0/pre_check.py | 4 +- plugins/oceanbase/3.1.0/connect.py | 5 + plugins/oceanbase/3.1.0/ocp_check.py | 16 +- plugins/oceanbase/3.1.0/reload.py | 4 + plugins/oceanbase/3.1.0/start_check.py | 274 +- plugins/oceanbase/4.0.0.0/start_check.py | 283 +- plugins/oceanbase/4.2.0.0/generate_config.py | 15 +- plugins/oceanbase/4.2.0.0/parameter.yaml | 8 + plugins/oceanbase/4.2.0.0/start.py | 42 +- plugins/oceanbase/4.2.0.0/start_check.py | 306 +- plugins/ocp-server/4.2.1/bootstrap.py | 25 + plugins/ocp-server/4.2.1/connect.py | 152 + plugins/ocp-server/4.2.1/destroy.py | 59 + plugins/ocp-server/4.2.1/display.py | 128 + plugins/ocp-server/4.2.1/file_map.yaml | 4 + plugins/ocp-server/4.2.1/generate_config.py | 64 + plugins/ocp-server/4.2.1/init.py | 162 + plugins/ocp-server/4.2.1/parameter.yaml | 363 ++ plugins/ocp-server/4.2.1/reload.py | 25 + plugins/ocp-server/4.2.1/restart.py | 157 + plugins/ocp-server/4.2.1/start.py | 715 +++ plugins/ocp-server/4.2.1/start_check.py | 590 ++ plugins/ocp-server/4.2.1/status.py | 39 + plugins/ocp-server/4.2.1/stop.py | 107 + plugins/ocp-server/4.2.1/takeover.py | 214 + plugins/ocp-server/4.2.1/takeover_precheck.py | 162 + plugins/ocp-server/4.2.1/upgrade.py | 78 + plugins/ocp-server/4.2.1/upgrade_check.py | 134 + profile/obd.sh | 11 +- rpm/ob-deploy.spec | 33 + service/api/response_utils.py | 1 + service/api/v1/installer.py | 66 + service/api/v1/metadb.py | 62 + service/api/v1/ocp_deployments.py | 368 ++ service/api/v1/service_info.py | 61 +- service/app.py | 12 +- service/common/const.py | 3 + service/common/core.py | 1 - service/common/task.py | 6 +- service/handler/base_handler.py | 5 +- service/handler/component_handler.py | 11 + service/handler/handler_utils.py | 14 + service/handler/metadb_handler.py | 907 +++ service/handler/ocp_handler.py | 1633 +++++ service/handler/service_info_handler.py | 282 +- service/middleware/ip_white.py | 41 + service/model/backup.py | 28 + service/model/database.py | 33 + service/model/deployments.py | 52 + service/model/metadb.py | 69 + service/model/ocp.py | 109 + service/model/parameter.py | 29 + service/model/resource.py | 61 + service/model/server.py | 36 + service/model/service_info.py | 5 + service/model/ssh.py | 38 + service/model/task.py | 76 + service/model/tenant.py | 42 + ssh.py | 74 +- tool.py | 149 +- web/.fast-spm-local.json | 102 + web/config/config.ts | 30 +- web/config/routes.ts | 61 + web/package.json | 18 +- web/public/assets/icon/client.svg | 13 + web/public/assets/icon/close.svg | 14 + web/public/assets/icon/ellipsis.svg | 22 + web/public/assets/icon/fit_canvas.svg | 14 + web/public/assets/icon/more.svg | 24 + web/public/assets/icon/new.svg | 1 + web/public/assets/icon/obproxy.svg | 14 + web/public/assets/icon/reset.svg | 14 + web/public/assets/icon/settings.svg | 29 + web/public/assets/icon/success.svg | 43 + web/public/assets/icon/warning.svg | 72 + web/public/assets/install/empty.png | Bin 0 -> 14913 bytes web/public/assets/install/failed.png | Bin 0 -> 55696 bytes web/public/assets/install/metadbFailed.png | Bin 0 -> 607171 bytes .../assets/install/metadbSuccessful.png | Bin 0 -> 698684 bytes web/public/assets/install/prechecked.svg | 242 + web/public/assets/install/successful.png | Bin 0 -> 56334 bytes web/public/assets/update/arrow.svg | 9 + web/public/assets/welcome/banner.png | Bin 0 -> 112413 bytes web/public/assets/welcome/new-db-selected.svg | 23 + .../assets/welcome/new-db-unselected.svg | 23 + web/public/assets/welcome/ob-selected.png | Bin 0 -> 1505 bytes web/public/assets/welcome/ob-unselected.png | Bin 0 -> 1539 bytes web/public/assets/welcome/ocp-selected.png | Bin 0 -> 2140 bytes web/public/assets/welcome/ocp-unselected.png | Bin 0 -> 2209 bytes web/public/assets/welcome/odc-selected.png | Bin 0 -> 769 bytes web/public/assets/welcome/odc-unselected.png | Bin 0 -> 794 bytes web/public/assets/welcome/old-db-selected.svg | 21 + .../assets/welcome/old-db-unselected.svg | 21 + web/public/assets/welcome/oms-selected.png | Bin 0 -> 960 bytes web/public/assets/welcome/oms-unselected.png | Bin 0 -> 984 bytes web/src/component/Access.tsx | 97 + web/src/component/AobException/index.less | 61 + web/src/component/AobException/index.tsx | 76 + web/src/component/Banner/index.less | 19 + web/src/component/Banner/index.tsx | 42 + web/src/component/CheckBadge/index.less | 63 + web/src/component/CheckBadge/index.tsx | 37 + web/src/component/ConnectConfig/index.less | 5 + web/src/component/ConnectConfig/index.tsx | 250 + web/src/component/ContentWithIcon/index.less | 26 + web/src/component/ContentWithIcon/index.tsx | 81 + web/src/component/ContentWithInfo/index.less | 16 + web/src/component/ContentWithInfo/index.tsx | 20 + .../component/ContentWithQuestion/index.tsx | 45 + web/src/component/CustomFooter/index.less | 18 + web/src/component/CustomFooter/index.tsx | 15 + .../component/CustomPasswordInput/index.tsx | 177 + web/src/component/DeployConfig/constants.ts | 82 + web/src/component/DeployConfig/index.less | 0 web/src/component/DeployConfig/index.tsx | 1039 ++++ web/src/component/EditText.tsx | 72 + web/src/component/Empty/index.less | 32 + web/src/component/Empty/index.tsx | 64 + .../EnvPreCheck/CheckFailuredItem.tsx | 240 + web/src/component/EnvPreCheck/CheckItem.tsx | 139 + web/src/component/EnvPreCheck/index.less | 61 + web/src/component/EnvPreCheck/index.tsx | 246 + web/src/component/ErrorBoundary.tsx | 87 + web/src/component/ErrorCompToolTip/index.less | 17 + web/src/component/ErrorCompToolTip/index.tsx | 19 + web/src/component/ExitBtn.tsx | 88 + web/src/component/ExitPageWrapper/index.tsx | 82 + web/src/component/FooterToolbar/index.less | 17 + web/src/component/FooterToolbar/index.tsx | 24 + web/src/component/Icon/ArrowIcon.tsx | 14 + web/src/component/Icon/ClusterIcon.tsx | 14 + web/src/component/Icon/NewIcon.tsx | 14 + web/src/component/Icon/Prechecked.tsx | 14 + web/src/component/InputPort/index.tsx | 62 + web/src/component/InsstallResult/index.less | 58 + web/src/component/InsstallResult/index.tsx | 559 ++ web/src/component/InstallProcess/index.less | 92 + web/src/component/InstallProcess/index.tsx | 462 ++ web/src/component/InstallProcessNew/index.tsx | 452 ++ web/src/component/InstallResult/index.less | 41 + web/src/component/InstallResult/index.tsx | 743 +++ .../component/MetaDBConfig/ClusterConfig.tsx | 337 + .../component/MetaDBConfig/ConfigTable.tsx | 72 + .../MetaDBConfig/DataBaseNodeConfig.tsx | 436 ++ web/src/component/MetaDBConfig/NodeConfig.tsx | 61 + .../component/MetaDBConfig/OBProxyConfig.tsx | 261 + web/src/component/MetaDBConfig/UserConfig.tsx | 278 + web/src/component/MetaDBConfig/helper.ts | 81 + web/src/component/MetaDBConfig/index.tsx | 304 + web/src/component/MetaDBConfig/indexEn.less | 0 web/src/component/MetaDBConfig/indexZh.less | 85 + .../ModifyOCPResourcePoolModal/index.tsx | 435 ++ web/src/component/MyCard/index.less | 17 + web/src/component/MyCard/index.tsx | 44 + web/src/component/MyDrawer/index.tsx | 97 + web/src/component/MyDropdown.tsx | 115 + web/src/component/MyInput.tsx | 28 + web/src/component/MySelect.tsx | 23 + web/src/component/NoAuth/index.tsx | 21 + web/src/component/OCPConfig/index.tsx | 681 ++ .../component/OCPConfigNew/ResourcePlan.tsx | 353 ++ .../component/OCPConfigNew/ServiceConfig.tsx | 297 + web/src/component/OCPConfigNew/UserConfig.tsx | 14 + web/src/component/OCPConfigNew/index.less | 8 + web/src/component/OCPConfigNew/index.tsx | 407 ++ web/src/component/OCPLogo.tsx | 37 + .../OCPPreCheck/CheckInfo/BasicInfo.tsx | 104 + .../OCPPreCheck/CheckInfo/ConfigInfo.tsx | 412 ++ .../OCPPreCheck/CheckInfo/ConnectInfo.tsx | 57 + .../OCPPreCheck/CheckInfo/ResourceInfo.tsx | 271 + .../OCPPreCheck/CheckInfo/index.less | 82 + .../component/OCPPreCheck/CheckInfo/index.tsx | 258 + .../component/OCPPreCheck/CheckInfo/type.ts | 78 + .../component/OCPPreCheck/PreCheck/index.tsx | 826 +++ web/src/component/OCPPreCheck/helper.ts | 60 + web/src/component/OCPPreCheck/index.less | 16 + web/src/component/OCPPreCheck/index.tsx | 19 + web/src/component/PageCard/index.less | 7 + web/src/component/PageCard/index.tsx | 23 + web/src/component/PageLoading/index.tsx | 11 + web/src/component/Password.tsx | 43 + web/src/component/PasswordCard/index.less | 9 + web/src/component/PasswordCard/index.tsx | 51 + web/src/component/Result/index.less | 5 + web/src/component/Result/index.tsx | 72 + .../component/SliderAndInputNumber/index.less | 18 + .../component/SliderAndInputNumber/index.tsx | 67 + web/src/component/Steps/index.tsx | 101 + web/src/constant/configuration.ts | 136 + web/src/constant/datetime.ts | 58 + web/src/constant/docs.ts | 19 + web/src/constant/envPresCheck.ts | 174 + web/src/constant/index.ts | 398 ++ web/src/constant/must-ignore.ts | 18 + web/src/i18n/strings/en-US.json | 602 +- web/src/i18n/strings/zh-CN.json | 602 +- web/src/models/global.ts | 174 +- web/src/models/ocpInstallData.ts | 91 + web/src/pages/Guide/index.less | 89 + web/src/pages/Guide/index.tsx | 270 + web/src/pages/Layout/index.tsx | 132 + web/src/pages/Obdeploy/CheckInfo.tsx | 658 ++ .../Obdeploy/ClusterConfig/ConfigTable.tsx | 142 + .../pages/Obdeploy/ClusterConfig/Footer.tsx | 81 + .../Obdeploy/ClusterConfig/Parameter.tsx | 244 + .../pages/Obdeploy/ClusterConfig/helper.ts | 50 + .../pages/Obdeploy/ClusterConfig/index.tsx | 815 +++ web/src/pages/Obdeploy/DeleteDeployModal.tsx | 259 + web/src/pages/Obdeploy/DeployType.tsx | 90 + web/src/pages/Obdeploy/ExitPage.tsx | 71 + web/src/pages/Obdeploy/InstallConfig.tsx | 1090 ++++ web/src/pages/Obdeploy/InstallFinished.tsx | 584 ++ web/src/pages/Obdeploy/InstallProcess.tsx | 312 + web/src/pages/Obdeploy/NodeConfig.tsx | 1109 ++++ web/src/pages/Obdeploy/PreCheck.tsx | 9 + web/src/pages/Obdeploy/PreCheckStatus.tsx | 813 +++ web/src/pages/Obdeploy/ProgressQuit.tsx | 36 + web/src/pages/Obdeploy/ServerTags.tsx | 157 + web/src/pages/Obdeploy/Steps.tsx | 121 + web/src/pages/Obdeploy/TooltipInput.tsx | 142 + web/src/pages/Obdeploy/Welcome.tsx | 111 + web/src/pages/Obdeploy/index.less | 66 + web/src/pages/Obdeploy/index.tsx | 310 + web/src/pages/Obdeploy/indexEn.less | 888 +++ web/src/pages/Obdeploy/indexZh.less | 890 +++ .../OcpInstaller/Configuration/index.tsx | 114 + web/src/pages/OcpInstaller/Error/403.tsx | 28 + web/src/pages/OcpInstaller/Error/404.tsx | 27 + web/src/pages/OcpInstaller/Index/index.less | 142 + web/src/pages/OcpInstaller/Index/index.tsx | 332 + .../Install/Component/MetadbDeployResult.tsx | 0 .../ModifyResourcePoolModal/index.less | 11 + .../ModifyResourcePoolModal/index.tsx | 476 ++ .../Install/Component/SystemConfig.tsx | 625 ++ web/src/pages/OcpInstaller/Install/index.less | 9 + web/src/pages/OcpInstaller/Install/index.tsx | 141 + .../Layout/BasicLayout/index.less | 10 + .../OcpInstaller/Layout/BasicLayout/index.tsx | 88 + .../Layout/BlankLayout/index.less | 15 + .../OcpInstaller/Layout/BlankLayout/index.tsx | 11 + web/src/pages/OcpInstaller/Layout/index.tsx | 42 + web/src/pages/OcpInstaller/Quit/index.less | 17 + web/src/pages/OcpInstaller/Quit/index.tsx | 72 + .../Component/ConnectionInfo/index.less | 33 + .../Update/Component/ConnectionInfo/index.tsx | 449 ++ .../Component/UpdatePreCheck/index.less | 62 + .../Update/Component/UpdatePreCheck/index.tsx | 373 ++ web/src/pages/OcpInstaller/Update/index.tsx | 536 ++ web/src/pages/OcpInstaller/Welcome/index.tsx | 88 + web/src/pages/constants/index.ts | 100 + web/src/pages/index.less | 66 - web/src/pages/index.tsx | 383 +- web/src/pages/type.ts | 8 + .../services/ocp_installer_backend/Info.ts | 19 + .../services/ocp_installer_backend/Metadb.ts | 427 ++ web/src/services/ocp_installer_backend/OCP.ts | 644 ++ .../services/ocp_installer_backend/Process.ts | 11 + .../services/ocp_installer_backend/User.ts | 11 + .../services/ocp_installer_backend/index.ts | 17 + .../ocp_installer_backend/typings.d.ts | 680 ++ web/src/typings/global.d.ts | 7 +- web/src/utils/helper.ts | 18 + web/src/utils/index.tsx | 283 +- web/yarn.lock | 5459 ++++++++++++----- 325 files changed, 44317 insertions(+), 2637 deletions(-) create mode 100644 plugins/oceanbase-diagnostic-tool/1.0/analyze_log.py create mode 100644 plugins/oceanbase-diagnostic-tool/1.0/checker.py create mode 100644 plugins/ocp-server/4.2.1/bootstrap.py create mode 100644 plugins/ocp-server/4.2.1/connect.py create mode 100644 plugins/ocp-server/4.2.1/destroy.py create mode 100644 plugins/ocp-server/4.2.1/display.py create mode 100644 plugins/ocp-server/4.2.1/file_map.yaml create mode 100644 plugins/ocp-server/4.2.1/generate_config.py create mode 100644 plugins/ocp-server/4.2.1/init.py create mode 100644 plugins/ocp-server/4.2.1/parameter.yaml create mode 100644 plugins/ocp-server/4.2.1/reload.py create mode 100644 plugins/ocp-server/4.2.1/restart.py create mode 100644 plugins/ocp-server/4.2.1/start.py create mode 100644 plugins/ocp-server/4.2.1/start_check.py create mode 100644 plugins/ocp-server/4.2.1/status.py create mode 100644 plugins/ocp-server/4.2.1/stop.py create mode 100644 plugins/ocp-server/4.2.1/takeover.py create mode 100644 plugins/ocp-server/4.2.1/takeover_precheck.py create mode 100644 plugins/ocp-server/4.2.1/upgrade.py create mode 100644 plugins/ocp-server/4.2.1/upgrade_check.py create mode 100644 service/api/v1/installer.py create mode 100644 service/api/v1/metadb.py create mode 100644 service/api/v1/ocp_deployments.py create mode 100644 service/handler/metadb_handler.py create mode 100644 service/handler/ocp_handler.py create mode 100644 service/middleware/ip_white.py create mode 100644 service/model/backup.py create mode 100644 service/model/database.py create mode 100644 service/model/metadb.py create mode 100644 service/model/ocp.py create mode 100644 service/model/parameter.py create mode 100644 service/model/resource.py create mode 100644 service/model/server.py create mode 100644 service/model/ssh.py create mode 100644 service/model/task.py create mode 100644 service/model/tenant.py create mode 100644 web/.fast-spm-local.json create mode 100644 web/config/routes.ts create mode 100644 web/public/assets/icon/client.svg create mode 100644 web/public/assets/icon/close.svg create mode 100644 web/public/assets/icon/ellipsis.svg create mode 100644 web/public/assets/icon/fit_canvas.svg create mode 100644 web/public/assets/icon/more.svg create mode 100644 web/public/assets/icon/new.svg create mode 100644 web/public/assets/icon/obproxy.svg create mode 100644 web/public/assets/icon/reset.svg create mode 100644 web/public/assets/icon/settings.svg create mode 100644 web/public/assets/icon/success.svg create mode 100644 web/public/assets/icon/warning.svg create mode 100644 web/public/assets/install/empty.png create mode 100644 web/public/assets/install/failed.png create mode 100644 web/public/assets/install/metadbFailed.png create mode 100644 web/public/assets/install/metadbSuccessful.png create mode 100644 web/public/assets/install/prechecked.svg create mode 100644 web/public/assets/install/successful.png create mode 100644 web/public/assets/update/arrow.svg create mode 100644 web/public/assets/welcome/banner.png create mode 100644 web/public/assets/welcome/new-db-selected.svg create mode 100644 web/public/assets/welcome/new-db-unselected.svg create mode 100644 web/public/assets/welcome/ob-selected.png create mode 100644 web/public/assets/welcome/ob-unselected.png create mode 100644 web/public/assets/welcome/ocp-selected.png create mode 100644 web/public/assets/welcome/ocp-unselected.png create mode 100644 web/public/assets/welcome/odc-selected.png create mode 100644 web/public/assets/welcome/odc-unselected.png create mode 100644 web/public/assets/welcome/old-db-selected.svg create mode 100644 web/public/assets/welcome/old-db-unselected.svg create mode 100644 web/public/assets/welcome/oms-selected.png create mode 100644 web/public/assets/welcome/oms-unselected.png create mode 100644 web/src/component/Access.tsx create mode 100644 web/src/component/AobException/index.less create mode 100644 web/src/component/AobException/index.tsx create mode 100644 web/src/component/Banner/index.less create mode 100644 web/src/component/Banner/index.tsx create mode 100644 web/src/component/CheckBadge/index.less create mode 100644 web/src/component/CheckBadge/index.tsx create mode 100644 web/src/component/ConnectConfig/index.less create mode 100644 web/src/component/ConnectConfig/index.tsx create mode 100644 web/src/component/ContentWithIcon/index.less create mode 100644 web/src/component/ContentWithIcon/index.tsx create mode 100644 web/src/component/ContentWithInfo/index.less create mode 100644 web/src/component/ContentWithInfo/index.tsx create mode 100644 web/src/component/ContentWithQuestion/index.tsx create mode 100644 web/src/component/CustomFooter/index.less create mode 100644 web/src/component/CustomFooter/index.tsx create mode 100644 web/src/component/CustomPasswordInput/index.tsx create mode 100644 web/src/component/DeployConfig/constants.ts create mode 100644 web/src/component/DeployConfig/index.less create mode 100644 web/src/component/DeployConfig/index.tsx create mode 100644 web/src/component/EditText.tsx create mode 100644 web/src/component/Empty/index.less create mode 100644 web/src/component/Empty/index.tsx create mode 100644 web/src/component/EnvPreCheck/CheckFailuredItem.tsx create mode 100644 web/src/component/EnvPreCheck/CheckItem.tsx create mode 100644 web/src/component/EnvPreCheck/index.less create mode 100644 web/src/component/EnvPreCheck/index.tsx create mode 100644 web/src/component/ErrorBoundary.tsx create mode 100644 web/src/component/ErrorCompToolTip/index.less create mode 100644 web/src/component/ErrorCompToolTip/index.tsx create mode 100644 web/src/component/ExitBtn.tsx create mode 100644 web/src/component/ExitPageWrapper/index.tsx create mode 100644 web/src/component/FooterToolbar/index.less create mode 100644 web/src/component/FooterToolbar/index.tsx create mode 100644 web/src/component/Icon/ArrowIcon.tsx create mode 100644 web/src/component/Icon/ClusterIcon.tsx create mode 100644 web/src/component/Icon/NewIcon.tsx create mode 100644 web/src/component/Icon/Prechecked.tsx create mode 100644 web/src/component/InputPort/index.tsx create mode 100644 web/src/component/InsstallResult/index.less create mode 100644 web/src/component/InsstallResult/index.tsx create mode 100644 web/src/component/InstallProcess/index.less create mode 100644 web/src/component/InstallProcess/index.tsx create mode 100644 web/src/component/InstallProcessNew/index.tsx create mode 100644 web/src/component/InstallResult/index.less create mode 100644 web/src/component/InstallResult/index.tsx create mode 100644 web/src/component/MetaDBConfig/ClusterConfig.tsx create mode 100644 web/src/component/MetaDBConfig/ConfigTable.tsx create mode 100644 web/src/component/MetaDBConfig/DataBaseNodeConfig.tsx create mode 100644 web/src/component/MetaDBConfig/NodeConfig.tsx create mode 100644 web/src/component/MetaDBConfig/OBProxyConfig.tsx create mode 100644 web/src/component/MetaDBConfig/UserConfig.tsx create mode 100644 web/src/component/MetaDBConfig/helper.ts create mode 100644 web/src/component/MetaDBConfig/index.tsx create mode 100644 web/src/component/MetaDBConfig/indexEn.less create mode 100644 web/src/component/MetaDBConfig/indexZh.less create mode 100644 web/src/component/ModifyOCPResourcePoolModal/index.tsx create mode 100644 web/src/component/MyCard/index.less create mode 100644 web/src/component/MyCard/index.tsx create mode 100644 web/src/component/MyDrawer/index.tsx create mode 100644 web/src/component/MyDropdown.tsx create mode 100644 web/src/component/MyInput.tsx create mode 100644 web/src/component/MySelect.tsx create mode 100644 web/src/component/NoAuth/index.tsx create mode 100644 web/src/component/OCPConfig/index.tsx create mode 100644 web/src/component/OCPConfigNew/ResourcePlan.tsx create mode 100644 web/src/component/OCPConfigNew/ServiceConfig.tsx create mode 100644 web/src/component/OCPConfigNew/UserConfig.tsx create mode 100644 web/src/component/OCPConfigNew/index.less create mode 100644 web/src/component/OCPConfigNew/index.tsx create mode 100644 web/src/component/OCPLogo.tsx create mode 100644 web/src/component/OCPPreCheck/CheckInfo/BasicInfo.tsx create mode 100644 web/src/component/OCPPreCheck/CheckInfo/ConfigInfo.tsx create mode 100644 web/src/component/OCPPreCheck/CheckInfo/ConnectInfo.tsx create mode 100644 web/src/component/OCPPreCheck/CheckInfo/ResourceInfo.tsx create mode 100644 web/src/component/OCPPreCheck/CheckInfo/index.less create mode 100644 web/src/component/OCPPreCheck/CheckInfo/index.tsx create mode 100644 web/src/component/OCPPreCheck/CheckInfo/type.ts create mode 100644 web/src/component/OCPPreCheck/PreCheck/index.tsx create mode 100644 web/src/component/OCPPreCheck/helper.ts create mode 100644 web/src/component/OCPPreCheck/index.less create mode 100644 web/src/component/OCPPreCheck/index.tsx create mode 100644 web/src/component/PageCard/index.less create mode 100644 web/src/component/PageCard/index.tsx create mode 100644 web/src/component/PageLoading/index.tsx create mode 100644 web/src/component/Password.tsx create mode 100644 web/src/component/PasswordCard/index.less create mode 100644 web/src/component/PasswordCard/index.tsx create mode 100644 web/src/component/Result/index.less create mode 100644 web/src/component/Result/index.tsx create mode 100644 web/src/component/SliderAndInputNumber/index.less create mode 100644 web/src/component/SliderAndInputNumber/index.tsx create mode 100644 web/src/component/Steps/index.tsx create mode 100644 web/src/constant/configuration.ts create mode 100644 web/src/constant/datetime.ts create mode 100644 web/src/constant/docs.ts create mode 100644 web/src/constant/envPresCheck.ts create mode 100644 web/src/constant/index.ts create mode 100644 web/src/constant/must-ignore.ts create mode 100644 web/src/models/ocpInstallData.ts create mode 100644 web/src/pages/Guide/index.less create mode 100644 web/src/pages/Guide/index.tsx create mode 100644 web/src/pages/Layout/index.tsx create mode 100644 web/src/pages/Obdeploy/CheckInfo.tsx create mode 100644 web/src/pages/Obdeploy/ClusterConfig/ConfigTable.tsx create mode 100644 web/src/pages/Obdeploy/ClusterConfig/Footer.tsx create mode 100644 web/src/pages/Obdeploy/ClusterConfig/Parameter.tsx create mode 100644 web/src/pages/Obdeploy/ClusterConfig/helper.ts create mode 100644 web/src/pages/Obdeploy/ClusterConfig/index.tsx create mode 100644 web/src/pages/Obdeploy/DeleteDeployModal.tsx create mode 100644 web/src/pages/Obdeploy/DeployType.tsx create mode 100644 web/src/pages/Obdeploy/ExitPage.tsx create mode 100644 web/src/pages/Obdeploy/InstallConfig.tsx create mode 100644 web/src/pages/Obdeploy/InstallFinished.tsx create mode 100644 web/src/pages/Obdeploy/InstallProcess.tsx create mode 100644 web/src/pages/Obdeploy/NodeConfig.tsx create mode 100644 web/src/pages/Obdeploy/PreCheck.tsx create mode 100644 web/src/pages/Obdeploy/PreCheckStatus.tsx create mode 100644 web/src/pages/Obdeploy/ProgressQuit.tsx create mode 100644 web/src/pages/Obdeploy/ServerTags.tsx create mode 100644 web/src/pages/Obdeploy/Steps.tsx create mode 100644 web/src/pages/Obdeploy/TooltipInput.tsx create mode 100644 web/src/pages/Obdeploy/Welcome.tsx create mode 100644 web/src/pages/Obdeploy/index.less create mode 100644 web/src/pages/Obdeploy/index.tsx create mode 100644 web/src/pages/Obdeploy/indexEn.less create mode 100644 web/src/pages/Obdeploy/indexZh.less create mode 100644 web/src/pages/OcpInstaller/Configuration/index.tsx create mode 100644 web/src/pages/OcpInstaller/Error/403.tsx create mode 100644 web/src/pages/OcpInstaller/Error/404.tsx create mode 100644 web/src/pages/OcpInstaller/Index/index.less create mode 100644 web/src/pages/OcpInstaller/Index/index.tsx create mode 100644 web/src/pages/OcpInstaller/Install/Component/MetadbDeployResult.tsx create mode 100644 web/src/pages/OcpInstaller/Install/Component/ModifyResourcePoolModal/index.less create mode 100644 web/src/pages/OcpInstaller/Install/Component/ModifyResourcePoolModal/index.tsx create mode 100644 web/src/pages/OcpInstaller/Install/Component/SystemConfig.tsx create mode 100644 web/src/pages/OcpInstaller/Install/index.less create mode 100644 web/src/pages/OcpInstaller/Install/index.tsx create mode 100644 web/src/pages/OcpInstaller/Layout/BasicLayout/index.less create mode 100644 web/src/pages/OcpInstaller/Layout/BasicLayout/index.tsx create mode 100644 web/src/pages/OcpInstaller/Layout/BlankLayout/index.less create mode 100644 web/src/pages/OcpInstaller/Layout/BlankLayout/index.tsx create mode 100644 web/src/pages/OcpInstaller/Layout/index.tsx create mode 100644 web/src/pages/OcpInstaller/Quit/index.less create mode 100644 web/src/pages/OcpInstaller/Quit/index.tsx create mode 100644 web/src/pages/OcpInstaller/Update/Component/ConnectionInfo/index.less create mode 100644 web/src/pages/OcpInstaller/Update/Component/ConnectionInfo/index.tsx create mode 100644 web/src/pages/OcpInstaller/Update/Component/UpdatePreCheck/index.less create mode 100644 web/src/pages/OcpInstaller/Update/Component/UpdatePreCheck/index.tsx create mode 100644 web/src/pages/OcpInstaller/Update/index.tsx create mode 100644 web/src/pages/OcpInstaller/Welcome/index.tsx create mode 100644 web/src/pages/type.ts create mode 100644 web/src/services/ocp_installer_backend/Info.ts create mode 100644 web/src/services/ocp_installer_backend/Metadb.ts create mode 100644 web/src/services/ocp_installer_backend/OCP.ts create mode 100644 web/src/services/ocp_installer_backend/Process.ts create mode 100644 web/src/services/ocp_installer_backend/User.ts create mode 100644 web/src/services/ocp_installer_backend/index.ts create mode 100644 web/src/services/ocp_installer_backend/typings.d.ts create mode 100644 web/src/utils/helper.ts diff --git a/_cmd.py b/_cmd.py index 36b82fd..df55e20 100644 --- a/_cmd.py +++ b/_cmd.py @@ -258,6 +258,15 @@ def do_command(self): def _do_command(self, obd): raise NotImplementedError + def get_white_ip_list(self): + if self.opts.white: + return self.opts.white.split(',') + ROOT_IO.warn("Security Risk: the whitelist is empty and anyone can request this program!") + if ROOT_IO.confirm("Do you want to continue?"): + return [] + wthite_ip_list = ROOT_IO.read("Please enter the whitelist, eq: '192.168.1.1'") + raise wthite_ip_list.split(',') + class MajorCommand(BaseCommand): @@ -690,6 +699,22 @@ def _do_command(self, obd): else: return self._show_help() +class ClusterExportToOCPCommand(ClusterMirrorCommand): + + def __init__(self): + super(ClusterExportToOCPCommand, self).__init__('export-to-ocp', 'Export obcluster to OCP') + self.parser.add_option('-a', '--address', type='string', help="OCP address, example http://127.0.0.1:8080, you can find it in OCP system parameters with Key='ocp.site.url'") + self.parser.add_option('-u', '--user', type='string', help="OCP user, this user should have create cluster privilege.") + self.parser.add_option('-p', '--password', type='string', help="OCP user password.") + self.parser.add_option('--host_type', type='string', help="Host type of observer, a host type will be created when there's no host type exists in ocp, the first host type will be used if this parameter is empty.", default="") + self.parser.add_option('--credential_name', type='string', help="Credential used to connect hosts, a credential will be created if credential_name is empty or no credential with this name exists in ocp.", default="") + + def _do_command(self, obd): + if self.cmds: + return obd.export_to_ocp(self.cmds[0]) + else: + return self._show_help() + class DemoCommand(ClusterMirrorCommand): @@ -718,14 +743,18 @@ class WebCommand(ObdCommand): def __init__(self): super(WebCommand, self).__init__('web', 'Start obd deploy application as web.') self.parser.add_option('-p', '--port', type='int', help="web server listen port", default=8680) + self.parser.add_option('-w', '--white', type='str', help="ip white list, eq: '127.0.0.1, 192.168.1.1'.", default='') def _do_command(self, obd): from service.app import OBDWeb + # white_ip_list = self.get_white_ip_list() + url = '/#/updateWelcome' if self.cmds and self.cmds[0] in ('upgrade', 'update') else '' + ROOT_IO.print('start OBD WEB in 0.0.0.0:%s' % self.opts.port) - ROOT_IO.print('please open http://{0}:{1}'.format(NetUtil.get_host_ip(), self.opts.port)) + ROOT_IO.print('please open http://{0}:{1}{2}'.format(NetUtil.get_host_ip(), self.opts.port, url)) try: COMMAND_ENV.set(ENV.ENV_DISABLE_PARALLER_EXTRACT, True, stdio=obd.stdio) - OBDWeb(obd, self.OBD_INSTALL_PATH).start(self.opts.port) + OBDWeb(obd, None, self.OBD_INSTALL_PATH).start(self.opts.port) except KeyboardInterrupt: ROOT_IO.print('Keyboard Interrupt') except BaseException as e: @@ -926,6 +955,7 @@ def __init__(self): def _do_command(self, obd): if self.cmds: + ROOT_IO.default_confirm = False return obd.edit_deploy_config(self.cmds[0]) else: return self._show_help() @@ -1137,6 +1167,7 @@ class ClusterMajorCommand(MajorCommand): def __init__(self): super(ClusterMajorCommand, self).__init__('cluster', 'Deploy and manage a cluster.') self.register_command(ClusterCheckForOCPChange()) + self.register_command(ClusterExportToOCPCommand()) self.register_command(ClusterConfigStyleChange()) self.register_command(ClusterAutoDeployCommand()) self.register_command(ClusterDeployCommand()) @@ -1525,6 +1556,8 @@ def __init__(self): super(ObdiagCommand, self).__init__('obdiag', 'Oceanbase Diagnostic Tool') self.register_command(ObdiagDeployCommand()) self.register_command(ObdiagGatherCommand()) + self.register_command(ObdiagAnalyzeCommand()) + self.register_command(ObdiagCheckCommand()) class ObdiagDeployCommand(ObdCommand): @@ -1549,7 +1582,7 @@ def init(self, cmd, args): def _do_command(self, obd): if self.cmds: - return obd.obdiag_gather(self.cmds[0], "gather_%s" % self.name, self.opts) + return obd.obdiag_online_func(self.cmds[0], "gather_%s" % self.name, self.opts) else: return self._show_help() @@ -1741,6 +1774,72 @@ def __init__(self): self.parser.add_option('--store_dir', type='string', help='the dir to store gather result, current dir by default.', default='./') self.parser.add_option('--obdiag_dir', type='string', help="obdiag install dir",default=OBDIAG_HOME_PATH) +class ObdiagAnalyzeMirrorCommand(ObdCommand): + + def init(self, cmd, args): + super(ObdiagAnalyzeMirrorCommand, self).init(cmd, args) + self.parser.set_usage('%s [options]' % self.prev_cmd) + return self + + def _do_command(self, obd): + offline_args_sign = '--files' + if self.args and (offline_args_sign in self.args): + return obd.obdiag_offline_func("analyze_%s" % self.name, self.opts) + if self.cmds: + return obd.obdiag_online_func(self.cmds[0], "analyze_%s" % self.name, self.opts) + else: + return self._show_help() + + +class ObdiagAnalyzeCommand(MajorCommand): + + def __init__(self): + super(ObdiagAnalyzeCommand, self).__init__('analyze', 'Analyze oceanbase diagnostic info') + self.register_command(ObdiagAnalyzeLogCommand()) + +class ObdiagAnalyzeLogCommand(ObdiagAnalyzeMirrorCommand): + + def init(self, cmd, args): + super(ObdiagAnalyzeLogCommand, self).init(cmd, args) + return self + + @property + def lock_mode(self): + return LockMode.NO_LOCK + + def __init__(self): + super(ObdiagAnalyzeLogCommand, self).__init__('log', 'Analyze oceanbase log from online observer machines or offline oceanbase log files') + self.parser.add_option('--from', type='string', help="specify the start of the time range. format: yyyy-mm-dd hh:mm:ss") + self.parser.add_option('--to', type='string', help="specify the end of the time range. format: yyyy-mm-dd hh:mm:ss") + self.parser.add_option('--since', type='string', help="Specify time range that from 'n' [d]ays, 'n' [h]ours or 'n' [m]inutes. before to now. format: . example: 1h.",default='30m') + self.parser.add_option('--scope', type='string', help="log type constrains, choices=[observer, election, rootservice, all]",default='all') + self.parser.add_option('--grep', type='string', help="specify keywords constrain") + self.parser.add_option('--log_level', type='string', help="oceanbase logs greater than or equal to this level will be analyze, choices=[DEBUG, TRACE, INFO, WDIAG, WARN, EDIAG, ERROR]") + self.parser.add_option('--files', type='string', help="specify files") + self.parser.add_option('--store_dir', type='string', help='the dir to store gather result, current dir by default.', default='./') + self.parser.add_option('--obdiag_dir', type='string', help="obdiag install dir",default=OBDIAG_HOME_PATH) + + +class ObdiagCheckCommand(ObdCommand): + + def __init__(self): + super(ObdiagCheckCommand, self).__init__('check', 'check oceanbase cluster') + self.parser.add_option('--cases', type='string', help="The name of the check task set that needs to be executed") + self.parser.add_option('--report_path', type='string', help='ouput report path', default='./check_report/') + self.parser.add_option('--obdiag_dir', type='string', help="obdiag install dir", default=OBDIAG_HOME_PATH) + + def init(self, cmd, args): + super(ObdiagCheckCommand, self).init(cmd, args) + self.parser.set_usage( + '%s [options]' % self.prev_cmd) + return self + + def _do_command(self, obd): + if len(self.cmds) > 0: + return obd.obdiag_online_func(self.cmds[0], "checker", self.opts) + else: + return self._show_help() + class MainCommand(MajorCommand): diff --git a/_deploy.py b/_deploy.py index 3be249f..5c519fb 100644 --- a/_deploy.py +++ b/_deploy.py @@ -942,10 +942,10 @@ class DeployInstallMode(object): class DeployInfo(object): - def __init__(self, name, status, components=OrderedDict(), config_status=DeployConfigStatus.UNCHNAGE): + def __init__(self, name, status, components=None, config_status=DeployConfigStatus.UNCHNAGE): self.status = status self.name = name - self.components = components + self.components = components if components else {} self.config_status = config_status def __str__(self): @@ -1012,24 +1012,28 @@ def set_auto_create_tenant(self, status): return self._dump() return True - def update_component_package_hash(self, component, package_hash, version=None): + def update_component_info(self, repository): + component = repository.name if component not in self.components: return False ori_data = self._src_data[component] src_data = deepcopy(ori_data) - src_data['package_hash'] = package_hash - if version: - src_data['version'] = version - elif 'version' in src_data: - del src_data['version'] + + if 'package_hash' in src_data: + src_data['package_hash'] = repository.hash + if 'version' in src_data: + src_data['version'] = repository.version + if 'release' in src_data: + src_data['release'] = repository.release if 'tag' in src_data: del src_data['tag'] self._src_data[component] = src_data if self._dump(): cluster_config = self.components[component] - cluster_config.package_hash = src_data.get('package_hash') - cluster_config.version = src_data.get('version') + cluster_config.package_hash = repository.hash + cluster_config.version = repository.version + cluster_config.release = repository.release cluster_config.tag = None return True self._src_data[component] = ori_data @@ -1446,7 +1450,7 @@ def update_upgrade_ctx(self, **uprade_ctx): return False def update_component_repository(self, repository): - if not self.deploy_config.update_component_package_hash(repository.name, repository.hash, repository.version): + if not self.deploy_config.update_component_info(repository): return False self.use_model(repository.name, repository) return True diff --git a/_environ.py b/_environ.py index 473658e..4df5f0c 100644 --- a/_environ.py +++ b/_environ.py @@ -44,4 +44,10 @@ TELEMETRY_LOG_MODE = "TELEMETRY_LOG_MODE" # ROOT IO DEFAULT CONFIRM. 0 - disable, 1 - enable. -ENV_DEFAULT_CONFIRM = "IO_DEFAULT_CONFIRM" \ No newline at end of file +ENV_DEFAULT_CONFIRM = "IO_DEFAULT_CONFIRM" + +# Disable ssh ALGORITHMS. 1 - disable algorithms, 0 - enable algorithms. +ENV_DISABLE_RSA_ALGORITHMS = 'OBD_DISABLE_RSA_ALGORITHMS' + +# set local connection when using host ip. {0/1} 0 - no local connection. 1 - local connection. +ENV_HOST_IP_MODE = "HOST_IP_MODE" \ No newline at end of file diff --git a/_errno.py b/_errno.py index 58830f3..796c08e 100644 --- a/_errno.py +++ b/_errno.py @@ -120,7 +120,7 @@ class InitDirFailedErrorMessage(object): EC_CONFIG_CONFLICT_DIR = OBDErrorCodeTemplate(1004, 'Configuration conflict {server1}: {path} is used for {server2}\'s {key}') EC_SOME_SERVER_STOPED = OBDErrorCodeTemplate(1005, 'Some of the servers in the cluster have been stopped') EC_FAIL_TO_CONNECT = OBDErrorCodeTemplate(1006, 'Failed to connect to {component}') -EC_ULIMIT_CHECK = OBDErrorCodeTemplate(1007, '({server}) {key} must not be less than {need} (Current value: {now})') +EC_ULIMIT_CHECK = OBDErrorCodeTemplate(1007, '({server}) The value of the ulimit parameter "{key}" must not be less than {need} (Current value: {now})') EC_FAILED_TO_GET_AIO_NR = OBDErrorCodeTemplate(1008, '({ip}) failed to get fs.aio-max-nr and fs.aio-nr') EC_NEED_CONFIG = OBDErrorCodeTemplate(1009, '{server} {component} need config: {miss_keys}') EC_NO_SUCH_NET_DEVICE = OBDErrorCodeTemplate(1010, '{server} No such net interface: {devname}') @@ -128,6 +128,8 @@ class InitDirFailedErrorMessage(object): EC_PARAM_CHECK = OBDErrorCodeTemplate(1012, '{errors}') EC_SSH_CONNECT = OBDErrorCodeTemplate(1013, '{user}@{ip} connect failed: {message}') EC_CHECK_STANDBY = OBDErrorCodeTemplate(1015, 'Unable to confirm the primary-standby relationship, rerun with "--ignore-standby" option if you want to proceed despite the risks.') +EC_FAILED_TO_GET_PARAM = OBDErrorCodeTemplate(1016, '({ip}) failed to get {key} using command "{cmd}"') +EC_PARAM_NOT_IN_NEED = OBDErrorCodeTemplate(1017, '({ip}) The value of the "{check_item}" must be {need} (Current value: {now}, Recommended value: {recommend})') # error code for observer EC_OBSERVER_NOT_ENOUGH_MEMORY = OBDErrorCodeTemplate(2000, '({ip}) not enough memory. (Free: {free}, Need: {need})') @@ -143,6 +145,7 @@ class InitDirFailedErrorMessage(object): EC_OBSERVER_FAILED_TO_REGISTER_WITH_DETAILS = OBDErrorCodeTemplate(2005, 'Failed to register cluster. {appname} may have been registered in {obconfig_url}.') EC_OBSERVER_MULTI_NET_DEVICE = OBDErrorCodeTemplate(2006, '{ip} has more than one network interface. Please set `devname` for ({server})') EC_OBSERVER_PING_FAILED = OBDErrorCodeTemplate(2007, '{ip1} {devname} fail to ping {ip2}. Please check configuration `devname`') +EC_OBSERVER_PING_FAILED_WITH_NO_DEVNAME = OBDErrorCodeTemplate(2007, '{ip1} fail to ping {ip2}. Please check your network') EC_OBSERVER_TIME_OUT_OF_SYNC = OBDErrorCodeTemplate(2008, 'Cluster clocks are out of sync') EC_OBSERVER_PRODUCTION_MODE_LIMIT = OBDErrorCodeTemplate(2009, '({server}): when production_mode is True, {key} can not be less then {limit}') EC_OBSERVER_SYS_MEM_TOO_LARGE = OBDErrorCodeTemplate(2010, '({server}): system_memory too large. system_memory must be less than memory_limit/memory_limit_percentage.') @@ -176,7 +179,23 @@ class InitDirFailedErrorMessage(object): EC_OCP_EXPRESS_META_DB_NOT_ENOUGH_LOG_DISK = OBDErrorCodeTemplate(4305, 'There is not enough log disk for ocp meta tenant.') EC_OCP_EXPRESS_META_DB_NOT_ENOUGH_MEM = OBDErrorCodeTemplate(4305, 'There is not enough memory for ocp meta tenant') EC_OCP_EXPRESS_ADMIN_PASSWD_ERROR = OBDErrorCodeTemplate(4306, '({ip}) ocp-express admin_passwd invalid.(Current :{current})') -# 4350-4399 had been used by ocp + + +# ocp-server +EC_OCP_SERVER_RUNNING_TASK = OBDErrorCodeTemplate(4350, 'The Server have running task') +EC_OCP_SERVER_MACHINE_STATUS = OBDErrorCodeTemplate(4351, 'The Server have gone') +EC_OCP_SERVER_METADB_VERSION = OBDErrorCodeTemplate(4352, 'Metadb version not fewer than V2.2.50') +EC_OCP_SERVER_TIME_SHIFT = OBDErrorCodeTemplate(4353, '{server}: Excessive deviation between machine time and ob time') +EC_OCP_SERVER_LAUNCH_USER_NOT_EXIST = OBDErrorCodeTemplate(4354, '{user}@{server}: Not exist') +EC_SUDO_NOPASSWD = OBDErrorCodeTemplate(4355, '{user}@{ip}: user {user} not in sudoers or sudoers file not exist') +EC_CONNECT_METADB = OBDErrorCodeTemplate(4356, 'failed to connect meta db') +EC_DB_NOT_IN_JDBC_URL = OBDErrorCodeTemplate(4357, 'database in jdbc_url is not exist') +EC_ERROR_JDBC_URL = OBDErrorCodeTemplate(4358, 'unmatched jdbc url, skip meta db connection check') +EC_OCP_SERVER_JAVA_VERSION_ERROR = OBDErrorCodeTemplate(4359, "{server}: ocp-server need java with version {version} and update release must greater than 161") +EC_OCP_SERVER_CLOCKDIFF_NOT_EXISTS = OBDErrorCodeTemplate(4360, "{server}: clockdiff not exists. Please install clockdiff manually") +EC_OCP_SERVER_TENANT_ALREADY_EXISTS = OBDErrorCodeTemplate(4361, "tenant({tenant_name}) alread exist") +EC_OCP_SERVER_DIR_ACCESS_FORBIDE = OBDErrorCodeTemplate(4362, "{server}:{path} access failed for current user, {server}:{cur_path} access succeed, please run `chmod -R 755 {cur_path}` ") + #ob-configserver EC_OBC_PROGRAM_START_ERROR = OBDErrorCodeTemplate(4401, 'Failed to start {server} ob-configserver.') @@ -188,7 +207,6 @@ class InitDirFailedErrorMessage(object): EC_OBC_DATABASE_CONNECT_ERROR = OBDErrorCodeTemplate(4404, 'ob-configserver connect to mysql failed: {server}: failed url to connect to database: {url}') - # sql EC_SQL_EXECUTE_FAILED = OBDErrorCodeTemplate(5000, "{sql} execute failed") @@ -196,6 +214,7 @@ class InitDirFailedErrorMessage(object): EC_OBDIAG_NOT_FOUND = OBDErrorCodeTemplate(6000, 'Failed to executable obdiag command, you may not have obdiag installed') EC_OBDIAG_NOT_CONTAIN_DEPEND_COMPONENT = OBDErrorCodeTemplate(6001, 'obdiag must contain depend components {components}') EC_OBDIAG_OPTIONS_FORMAT_ERROR = OBDErrorCodeTemplate(6002, 'obdiag options {option} format error, please check the value : {value}') +EC_OBDIAG_FUCYION_FAILED = OBDErrorCodeTemplate(6003, 'Failed to excute obdiag function {fuction}') # Unexpected exceptions code EC_UNEXPECTED_EXCEPTION = OBDErrorCodeTemplate(9999, 'Unexpected exception: need to be posted on "https://ask.oceanbase.com", and we will help you resolve them.') @@ -226,7 +245,7 @@ class InitDirFailedErrorMessage(object): SUG_GRAFANA_PWD = OBDErrorSuggestionTemplate('Grafana password length must be greater than 4 and not "admin"', True, [FixEval(FixEval.DEL, 'login_password', is_global=True)]) SUG_PARAM_CHECK = OBDErrorSuggestionTemplate('Please check your config') SUG_SSH_FAILED = OBDErrorSuggestionTemplate('Please check user config and network') -SUG_SYSCTL = OBDErrorSuggestionTemplate('Please execute `echo ‘{var}={value}’ >> /etc/sysctl.conf; sysctl -p` as root in {ip}.') +SUG_SYSCTL = OBDErrorSuggestionTemplate('Please execute `echo "{var}={value}" >> /etc/sysctl.conf; sysctl -p` as root in {ip}.') SUG_ULIMIT = OBDErrorSuggestionTemplate('Please execute `echo -e "* soft {name} {value}\\n* hard {name} {value}" >> /etc/security/limits.d/{name}.conf` as root in {ip}. if it dosen\'t work, please check whether UsePAM is yes in /etc/ssh/sshd_config.') SUG_CONNECT_EXCEPT = OBDErrorSuggestionTemplate('Connection exception or unsupported OS. Please retry or contact us.') SUG_UNSUPPORT_OS = OBDErrorSuggestionTemplate('It may be an unsupported OS, please contact us for assistance') @@ -245,4 +264,6 @@ class InitDirFailedErrorMessage(object): SUG_OCP_EXPRESS_COMP_VERSION = OBDErrorSuggestionTemplate('Please use {comp} with version {version} or above') SUG_OCP_EXPRESS_REDUCE_META_DB_MEM = OBDErrorSuggestionTemplate('Please reduce the `ocp_meta_tenant_memory_size`', fix_eval=[FixEval(FixEval.DEL, 'ocp_meta_tenant_memory_size')]) SUG_OCP_EXPRESS_REDUCE_META_DB_LOG_DISK = OBDErrorSuggestionTemplate('Please reduce the `ocp_meta_tenant_log_disk_size`', fix_eval=[FixEval(FixEval.DEL, 'ocp_meta_tenant_log_disk_size')]) -SUG_OCP_EXPRESS_EDIT_ADMIN_PASSWD_ERROR = OBDErrorSuggestionTemplate('Please edit the `admin_passwd`, must be 8 to 32 characters in length, and must contain at least two digits, two uppercase letters, two lowercase letters, and two of the following special characters:~!@#%^&*_-+=|(){{}}[]:;,.?/)', fix_eval=[FixEval(FixEval.DEL, 'admin_passwd')], auto_fix=True) \ No newline at end of file +SUG_OCP_EXPRESS_EDIT_ADMIN_PASSWD_ERROR = OBDErrorSuggestionTemplate('Please edit the `admin_passwd`, must be 8 to 32 characters in length, and must contain at least two digits, two uppercase letters, two lowercase letters, and two of the following special characters:~!@#%^&*_-+=|(){{}}[]:;,.?/)', fix_eval=[FixEval(FixEval.DEL, 'admin_passwd')], auto_fix=True) +SUG_OCP_SERVER_JDBC_URL_CONFIG_ERROR = OBDErrorSuggestionTemplate('Please ensure that the `jdbc_url` in the `config.yaml` configuration file is set correctly to establish a successful connection with your database') +SUG_SUDO_NOPASSWD = OBDErrorSuggestionTemplate('Please execute `bash -c \'echo "{user} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers`\' as root in {ip}.') diff --git a/_mirror.py b/_mirror.py index 2ac336d..5d26a3b 100644 --- a/_mirror.py +++ b/_mirror.py @@ -41,7 +41,7 @@ from configparser import ConfigParser from _arch import getArchList, getBaseArch -from _rpm import Package, PackageInfo +from _rpm import Version, Package, PackageInfo from tool import ConfigUtil, FileUtil, var_replace from _manager import Manager from tool import timeout @@ -50,14 +50,15 @@ _ARCH = getArchList() _RELEASE = None SUP_MAP = { - 'ubuntu': (([16], 7), ), - 'debian': (([9], 7), ), - 'opensuse-leap': (([15], 7), ), - 'sles': (([15, 2], 7), ), - 'fedora': (([33], 7), ), - 'uos': (([20], 8), ), - 'anolis': (([23], 7), ), - 'openEuler': (([22, 3], 7), ), + 'ubuntu': {'16': 7}, + 'debian': {'9': 7}, + 'opensuse-leap': {'15': 7}, + 'sles': {'15.2': 7}, + 'fedora': {'33': 7}, + 'uos': {'20': 8}, + 'anolis': {'23': 7}, + 'openEuler': {'22.03': 7}, + 'kylin': {'V10': 8}, } _SERVER_VARS = { 'basearch': getBaseArch(), @@ -938,12 +939,14 @@ def get_remote_mirrors(self, is_enabled=True): server_vars = deepcopy(_SERVER_VARS) linux_id = server_vars.get('ID') if linux_id in SUP_MAP: - version = [int(vnum) for vnum in server_vars.get('VERSION_ID', '').split('.')] - for vid, elvid in SUP_MAP[linux_id]: - if version < vid: + version_id = server_vars.get('VERSION_ID', '') + sorted_versions = sorted([Version(key) for key in SUP_MAP[linux_id]], reverse=True) + for version in sorted_versions: + if Version(version_id) >= version: + server_vars['releasever'] = SUP_MAP[linux_id][str(version)] break - server_vars['releasever'] = elvid - server_vars['releasever'] = str(elvid) + else: + server_vars['releasever'] = SUP_MAP[linux_id][str(version)] self.stdio and getattr(self.stdio, 'warn', print)('Use centos %s remote mirror repository for %s %s' % ( server_vars['releasever'], linux_id, server_vars.get('VERSION_ID'))) for mirror_section in self._get_sections(): diff --git a/_plugin.py b/_plugin.py index c1861b3..d9d253c 100644 --- a/_plugin.py +++ b/_plugin.py @@ -649,6 +649,7 @@ def file_map(self, package_info): 'name': package_info.name, 'version': package_info.version, 'release': package_info.release, + 'release_simple': package_info.release.simple(), 'arch': package_info.arch, 'md5': package_info.md5, } diff --git a/_rpm.py b/_rpm.py index 17cd2e1..edf9593 100644 --- a/_rpm.py +++ b/_rpm.py @@ -78,6 +78,9 @@ def __cmp_value__(self): m = re.search('(\d+)', self.__str__()) return int(m.group(0)) if m else -1 + def simple(self): + m = re.search('(\d+)', self.__str__()) + return m.group(0) if m else "" class PackageInfo(object): diff --git a/_types.py b/_types.py index 7656789..8f163c6 100644 --- a/_types.py +++ b/_types.py @@ -18,10 +18,13 @@ # along with OceanBase Deploy. If not, see . from __future__ import absolute_import, division, print_function + import re + __all__ = ("Moment", "Time", "Capacity", "CapacityMB", "StringList", "Dict", "List", "StringOrKvList", "Double", "Boolean", "Integer", "String") + class Null(object): def __init__(self): @@ -143,8 +146,8 @@ def _format(self): n = self._origin unit = self.UNITS['M'] else: - r = re.match('^(\d+)(\w)B?$', self._origin.upper()) - n, u = r.groups() + r = re.match('^(\d+)(\w)(I?B)?$', self._origin.upper()) + n, u, _ = r.groups() unit = self.UNITS.get(u.upper()) if unit: self._value = int(n) * unit diff --git a/core.py b/core.py index 885abf6..10e3e4b 100644 --- a/core.py +++ b/core.py @@ -32,7 +32,7 @@ from ssh import SshClient, SshConfig from tool import FileUtil, DirectoryUtil, YamlLoader, timeout, COMMAND_ENV, OrderedDict -from _stdio import MsgLevel +from _stdio import MsgLevel, FormtatText from _rpm import Version from _mirror import MirrorRepositoryManager, PackageInfo from _plugin import PluginManager, PluginType, InstallPlugin, PluginContextNamespace @@ -1081,6 +1081,77 @@ def genconfig(self, name): self.deploy_manager.remove_deploy_config(name) return False + def export_to_ocp(self, name): + # extract ocp info from options + ocp_address = getattr(self.options, 'address', '') + ocp_user = getattr(self.options, 'user', '') + ocp_password = getattr(self.options, 'password', '') + if ocp_address is None or ocp_address == '': + self._call_stdio('error', 'address is required, pass it using -a or --address') + return False + if ocp_user is None or ocp_user == '': + self._call_stdio('error', 'user is required, pass it using -u or --user') + return False + if ocp_password is None or ocp_password == '': + self._call_stdio('error', 'password is required, pass it using -p or --password') + return False + self._call_stdio('verbose', 'Get Deploy by name') + deploy = self.deploy_manager.get_deploy_config(name) + if not deploy: + self._call_stdio('error', 'No such deploy: %s.' % name) + return False + + deploy_info = deploy.deploy_info + self._call_stdio('verbose', 'Deploy status judge') + if deploy_info.status != DeployStatus.STATUS_RUNNING: + self._call_stdio('error', 'Deploy "%s" not RUNNING' % (name)) + return False + + deploy_config = deploy.deploy_config + if "oceanbase-ce" not in deploy_config.components: + self._call_stdio("error", "no oceanbase-ce in deployment %s" % name) + cluster_config = deploy_config.components["oceanbase-ce"] + repositories = self.load_local_repositories(deploy_info) + self.set_repositories(repositories) + ssh_clients = self.get_clients(deploy_config, repositories) + + self._call_stdio('verbose', 'get plugins by mocking an ocp repository.') + # search and get all related plugins using a mock ocp repository + mock_ocp_repository = Repository("ocp-server-ce", "/") + mock_ocp_repository.version = "4.2.1" + repositories = [mock_ocp_repository] + takeover_precheck_plugins = self.search_py_script_plugin(repositories, "takeover_precheck") + self._call_stdio('verbose', 'successfully get takeover precheck plugin.') + takeover_plugins = self.search_py_script_plugin(repositories, "takeover") + self._call_stdio('verbose', 'successfully get takeover plugin.') + + # do take over cluster by call takeover precheck plugins + self._call_stdio('print', 'precheck for export obcluster to ocp.') + precheck_ret = self.call_plugin(takeover_precheck_plugins[mock_ocp_repository], mock_ocp_repository, cluster_config=cluster_config, clients=ssh_clients) + if not precheck_ret: + self._call_stdio("error", precheck_ret.get_return('exception')) + return False + else: + # set version and component option + ocp_version = precheck_ret.get_return("ocp_version") + self.options._update_loose({"version": ocp_version, "components": "oceanbase-ce"}) + self._call_stdio('verbose', 'do takeover precheck by calling ocp finished') + # check obcluster can be takeover by ocp + check_ocp_result = self.check_for_ocp(name) + if not check_ocp_result: + self._call_stdio("error", "check obcluster to ocp takeover failed") + return False + self.set_deploy(None) + self.set_repositories(None) + takeover_ret = self.call_plugin(takeover_plugins[mock_ocp_repository], mock_ocp_repository, cluster_config=cluster_config, deploy_config = deploy_config, clients=ssh_clients) + if not takeover_ret: + self._call_stdio('error', 'export obcluster to ocp failed') + return False + else: + task_id = takeover_ret.get_return("task_id") + self._call_stdio("print", "takeover task successfully submitted to ocp, you can check task at %s/task/%d" % (ocp_address, task_id)) + return True + def check_for_ocp(self, name): self._call_stdio('verbose', 'Get Deploy by name') deploy = self.deploy_manager.get_deploy_config(name) @@ -1143,6 +1214,7 @@ def check_for_ocp(self, name): component_num = len(repositories) for repository in repositories: if repository.name not in components: + component_num -= 1 continue if repository not in ocp_check: component_num -= 1 @@ -1163,7 +1235,13 @@ def check_for_ocp(self, name): if self.call_plugin(ocp_check[repository], repository, cursor=cursor, ocp_version=version, new_cluster_config=new_cluster_config, new_clients=new_ssh_clients): component_num -= 1 self._call_stdio('print', '%s Check passed.' % repository.name) - + # search and install oceanbase-ce-utils, just log warning when failed since it can be installed after takeover + repositories_utils_map = self.get_repositories_utils(repositories) + if not repositories_utils_map: + self._call_stdio('warn', 'Failed to get utils package') + else: + if not self.install_utils_to_servers(repositories, repositories_utils_map): + self._call_stdio('warn', 'Failed to install utils to servers') return component_num == 0 def sort_repository_by_depend(self, repositories, deploy_config): @@ -1268,6 +1346,9 @@ def demo(self): self._call_stdio('error', 'Deploy "%s" is %s. You could not deploy an %s cluster.' % (name, deploy_info.status.value, deploy_info.status.value)) return False + if 'ocp-server' in getattr(self.options, 'components', ''): + self._call_stdio('error', 'Not support ocp-server.') + return components = set() for component_name in getattr(self.options, 'components', '').split(','): if component_name: @@ -2391,7 +2472,7 @@ def restart_cluster(self, name): sub_io = None if getattr(self.stdio, 'sub_io'): sub_io = self.stdio.sub_io(msg_lv=MsgLevel.ERROR) - obd = self.fork(options=Values({'without_parameter': True}), stdio=sub_io) + obd = self.fork(options=Values({'without_parameter': True, 'skip_create_tenant': 'True'}), stdio=sub_io) if not obd._start_cluster(deploy, repositories): if self.stdio: self._call_stdio('error', err.EC_SOME_SERVER_STOPED.format()) @@ -2421,6 +2502,11 @@ def restart_cluster(self, name): start_all = cluster_servers == cluster_config.servers update_deploy_status = update_deploy_status and start_all + ret = self.call_plugin(start_check_plugins[repository], repository, source_option='restart') + if not ret: + return False + + setattr(self.options, "skip_create_tenant", True) if self.call_plugin( restart_plugins[repository], repository, @@ -2491,7 +2577,7 @@ def redeploy_cluster(self, name, search_repo=True, need_confirm=False): self._call_stdio('error', 'No such deploy: %s.' % name) return False - if need_confirm and not self._call_stdio('confirm', 'Are you sure to destroy the "%s" cluster and rebuild it?' % name): + if need_confirm and not self._call_stdio('confirm', FormtatText.warning('Are you sure to destroy the "%s" cluster and rebuild it?' % name)): return False deploy_info = deploy.deploy_info @@ -2551,6 +2637,7 @@ def redeploy_cluster(self, name, search_repo=True, need_confirm=False): if not repositories or not install_plugins: return False self.set_repositories(repositories) + setattr(self.options, "skip_create_tenant", True) return self._deploy_cluster(deploy, repositories) and self._start_cluster(deploy, repositories) def destroy_cluster(self, name): @@ -2902,6 +2989,11 @@ def upgrade_cluster(self, name): self._call_stdio('print', '%s %s is stopped' % (server, repository.name)) return False + start_check_plugins = self.search_py_script_plugin(repositories, 'start_check') + ret = self.call_plugin(start_check_plugins[dest_repository], dest_repository, source_option='upgrade') + if not ret: + return False + route = [] use_images = [] upgrade_route_plugins = self.search_py_script_plugin([dest_repository], 'upgrade_route', no_found_act='warn') @@ -4244,7 +4336,7 @@ def telemetry_post(self, name): return self.call_plugin(telemetry_post_plugin, repository, spacename='telemetry') - def obdiag_gather(self, name, gather_type, opts): + def obdiag_online_func(self, name, fuction_type, opts): self._global_ex_lock() self._call_stdio('verbose', 'Get Deploy by name') deploy = self.deploy_manager.get_deploy_config(name, read_only=True) @@ -4261,7 +4353,7 @@ def obdiag_gather(self, name, gather_type, opts): return False allow_components = [] - if gather_type.startswith("gather_obproxy"): + if fuction_type.startswith("gather_obproxy") or fuction_type.startswith("analyze_obproxy"): allow_components = ['obproxy-ce', 'obproxy'] else: allow_components = ['oceanbase-ce', 'oceanbase'] @@ -4289,48 +4381,44 @@ def obdiag_gather(self, name, gather_type, opts): if repository.name == component_name: target_repository = repository break - if gather_type in ['gather_plan_monitor']: + if fuction_type in ['gather_plan_monitor']: setattr(opts, 'connect_cluster', True) - obdiag_path = getattr(opts, 'obdiag_dir', None) diagnostic_component_name = 'oceanbase-diagnostic-tool' - obdiag_version = '1.0' - pre_check_plugin = self.plugin_manager.get_best_py_script_plugin('pre_check', diagnostic_component_name, obdiag_version) - check_pass = self.call_plugin(pre_check_plugin, - target_repository, - gather_type = gather_type, - obdiag_path = obdiag_path, - version_check = True, - utils_work_dir_check = True) - if not check_pass: - # obdiag checker return False - if not check_pass.get_return('obdiag_found'): - if not self._call_stdio('confirm', 'Could not find the obdiag, please confirm whether to install it' ): - return False - self.obdiag_deploy(auto_deploy=True, install_prefix=obdiag_path) - # utils checker return False - if not check_pass.get_return('utils_status'): - repositories_utils_map = self.get_repositories_utils(repositories) - if repositories_utils_map is False: - self._call_stdio('error', 'Failed to get utils package') - else: - if not self._call_stdio('confirm', 'obdiag gather clog/slog need to install ob_admin\nDo you want to install ob_admin?'): - if not check_pass.get_return('skip'): - return False - else: - self._call_stdio('warn', 'Just skip gather clog/slog') - else: - if not self.install_utils_to_servers(repositories, repositories_utils_map): - self._call_stdio('error', 'Failed to install utils to servers') - obdiag_version = check_pass.get_return('obdiag_version') - generate_config_plugin = self.plugin_manager.get_best_py_script_plugin('generate_config', diagnostic_component_name, obdiag_version) - self.call_plugin(generate_config_plugin, target_repository, deploy_config=deploy_config) - self._call_stdio('generate_config', 'succeed') - obdiag_plugin = self.plugin_manager.get_best_py_script_plugin(gather_type, diagnostic_component_name, obdiag_version) - return self.call_plugin(obdiag_plugin, target_repository) + diagnostic_component_version = '1.0' + if fuction_type in ['analyze_log']: + diagnostic_component_version = '1.3' + elif fuction_type in ['checker']: + diagnostic_component_version = '1.4' + deployed = self.obdiag_deploy(auto_deploy=True, version=diagnostic_component_version) + if deployed: + generate_config_plugin = self.plugin_manager.get_best_py_script_plugin('generate_config', diagnostic_component_name, diagnostic_component_version) + self.call_plugin(generate_config_plugin, target_repository, deploy_config=deploy_config) + self._call_stdio('generate_config', 'succeed') + obdiag_plugin = self.plugin_manager.get_best_py_script_plugin(fuction_type, diagnostic_component_name, diagnostic_component_version) + return self.call_plugin(obdiag_plugin, target_repository) + else: + self._call_stdio('error', err.EC_OBDIAG_FUCYION_FAILED.format(fuction=fuction_type)) + return False - def obdiag_deploy(self, auto_deploy=False, install_prefix=None): + def obdiag_offline_func(self, fuction_type, opts): + component_name = 'oceanbase-diagnostic-tool' + pkg = self.mirror_manager.get_best_pkg(name=component_name) + if not pkg: + self._call_stdio('critical', '%s package not found' % component_name) + return False + repository = self.repository_manager.create_instance_repository(pkg.name, pkg.version, pkg.md5) + deployed = self.obdiag_deploy(auto_deploy=True, version='1.3') + if deployed: + obdiag_plugin = self.plugin_manager.get_best_py_script_plugin(fuction_type, component_name, ) + return self.call_plugin(obdiag_plugin, repository, clients={}) + else: + self._call_stdio('error', err.EC_OBDIAG_FUCYION_FAILED.format(fuction=fuction_type)) + return False + + + def obdiag_deploy(self, auto_deploy=False, install_prefix=None, version='1.3'): self._global_ex_lock() component_name = 'oceanbase-diagnostic-tool' if install_prefix is None: @@ -4341,29 +4429,29 @@ def obdiag_deploy(self, auto_deploy=False, install_prefix=None): return False plugin = self.plugin_manager.get_best_plugin(PluginType.INSTALL, component_name, pkg.version) self._call_stdio('print', 'obdiag plugin : %s' % plugin) - repository = self.repository_manager.create_instance_repository(pkg.name, pkg.version, pkg.md5) - check_plugin = self.plugin_manager.get_best_py_script_plugin('pre_check', component_name, pkg.version) - if not auto_deploy: - ret = self.call_plugin(check_plugin, - repository, - clients={}, - obdiag_path = install_prefix, - obdiag_new_version = pkg.version, - version_check = True) - if not ret and ret.get_return('obdiag_found'): + check_plugin = self.plugin_manager.get_best_py_script_plugin('pre_check', component_name, version) + obd = self.fork() + obd.set_deploy(deploy=None) + ret = obd.call_plugin(check_plugin, repository, clients={}, obdiag_path = install_prefix, obdiag_new_version = version, version_check = True) + if ret.get_return('obdiag_found'): + if ret.get_return('version_status'): self._call_stdio('print', 'No updates detected. obdiag is already up to date.') - return False - if not self._call_stdio('confirm', 'Found a higher version\n%s\nDo you want to use it?' % pkg): - return False + return True + else: + if not auto_deploy: + if not self._call_stdio('confirm', 'Found a higher version\n%s\nDo you want to use it?' % pkg): + return False self._call_stdio('start_loading', 'Get local repositories and plugins') + repository = self.repository_manager.create_instance_repository(pkg.name, pkg.version, pkg.md5) + plugin = self.plugin_manager.get_best_plugin(PluginType.INSTALL, component_name, pkg.version) repository.load_pkg(pkg, plugin) src_path = os.path.join(repository.repository_dir, component_name) if FileUtil.symlink(src_path, install_prefix, self.stdio): self._call_stdio('stop_loading', 'succeed') self._call_stdio('print', 'Deploy obdiag successful.\nCurrent version : %s. \nPath of obdiag : %s' % (pkg.version, install_prefix)) - return True - + return True + return False def get_repositories_utils(self, repositories): all_data = [] diff --git a/example/all-components-min.yaml b/example/all-components-min.yaml index d9f5587..5ece143 100644 --- a/example/all-components-min.yaml +++ b/example/all-components-min.yaml @@ -17,10 +17,11 @@ oceanbase-ce: - name: server3 ip: 172.19.33.4 global: - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: eth0 + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 cluster_id: 1 # please set memory limit to a suitable value which is matching resource. memory_limit: 6G # The maximum running memory for an observer diff --git a/example/all-components.yaml b/example/all-components.yaml index fb07a47..699cc92 100644 --- a/example/all-components.yaml +++ b/example/all-components.yaml @@ -17,10 +17,11 @@ oceanbase-ce: - name: server3 ip: 172.19.33.4 global: - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: eth0 + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 # if current hardware's memory capacity is smaller than 50G, please use the setting of "mini-single-example.yaml" and do a small adjustment. memory_limit: 64G # The maximum running memory for an observer # The reserved system memory. system_memory is reserved for general tenants. The default value is 30G. diff --git a/example/autodeploy/all-components.yaml b/example/autodeploy/all-components.yaml index 3aba9aa..540f2e4 100644 --- a/example/autodeploy/all-components.yaml +++ b/example/autodeploy/all-components.yaml @@ -21,9 +21,10 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. # devname: eth0 # External port for OceanBase Database. The default value is 2881. DO NOT change this value after the cluster is started. # mysql_port: 2881 diff --git a/example/autodeploy/default-example.yaml b/example/autodeploy/default-example.yaml index e080991..b332638 100644 --- a/example/autodeploy/default-example.yaml +++ b/example/autodeploy/default-example.yaml @@ -21,9 +21,10 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. # devname: eth0 # External port for OceanBase Database. The default value is 2881. DO NOT change this value after the cluster is started. # mysql_port: 2881 diff --git a/example/autodeploy/distributed-example.yaml b/example/autodeploy/distributed-example.yaml index 3999dde..84905f3 100644 --- a/example/autodeploy/distributed-example.yaml +++ b/example/autodeploy/distributed-example.yaml @@ -21,9 +21,10 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. # devname: eth0 # External port for OceanBase Database. The default value is 2881. DO NOT change this value after the cluster is started. # mysql_port: 2881 diff --git a/example/autodeploy/distributed-with-obproxy-and-obagent-example.yaml b/example/autodeploy/distributed-with-obproxy-and-obagent-example.yaml index f9691b4..a0604f2 100644 --- a/example/autodeploy/distributed-with-obproxy-and-obagent-example.yaml +++ b/example/autodeploy/distributed-with-obproxy-and-obagent-example.yaml @@ -21,9 +21,10 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. # devname: eth0 # External port for OceanBase Database. The default value is 2881. DO NOT change this value after the cluster is started. # mysql_port: 2881 diff --git a/example/autodeploy/distributed-with-obproxy-example.yaml b/example/autodeploy/distributed-with-obproxy-example.yaml index 203e9d8..811f3fc 100644 --- a/example/autodeploy/distributed-with-obproxy-example.yaml +++ b/example/autodeploy/distributed-with-obproxy-example.yaml @@ -21,9 +21,10 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. # devname: eth0 # External port for OceanBase Database. The default value is 2881.DO NOT change this value after the cluster is started. # mysql_port: 2881 diff --git a/example/autodeploy/single-example.yaml b/example/autodeploy/single-example.yaml index 7a94311..20ae863 100644 --- a/example/autodeploy/single-example.yaml +++ b/example/autodeploy/single-example.yaml @@ -16,9 +16,10 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. # devname: eth0 # External port for OceanBase Database. The default value is 2881. DO NOT change this value after the cluster is started. # mysql_port: 2881 diff --git a/example/autodeploy/single-with-obproxy-example.yaml b/example/autodeploy/single-with-obproxy-example.yaml index 185688d..bdc4b6d 100644 --- a/example/autodeploy/single-with-obproxy-example.yaml +++ b/example/autodeploy/single-with-obproxy-example.yaml @@ -16,9 +16,10 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. # devname: eth0 # External port for OceanBase Database. The default value is 2881. DO NOT change this value after the cluster is started. # mysql_port: 2881 diff --git a/example/default-components-min.yaml b/example/default-components-min.yaml index 39a7326..98bf9c6 100644 --- a/example/default-components-min.yaml +++ b/example/default-components-min.yaml @@ -15,10 +15,11 @@ oceanbase-ce: - name: server3 ip: 172.19.33.4 global: - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: eth0 + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 cluster_id: 1 # please set memory limit to a suitable value which is matching resource. memory_limit: 6G # The maximum running memory for an observer diff --git a/example/default-components.yaml b/example/default-components.yaml index f0db65b..65edfd2 100644 --- a/example/default-components.yaml +++ b/example/default-components.yaml @@ -15,10 +15,11 @@ oceanbase-ce: - name: server3 ip: 172.19.33.4 global: - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: eth0 + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 # if current hardware's memory capacity is smaller than 50G, please use the setting of "mini-single-example.yaml" and do a small adjustment. memory_limit: 64G # The maximum running memory for an observer # The reserved system memory. system_memory is reserved for general tenants. The default value is 30G. diff --git a/example/distributed-example.yaml b/example/distributed-example.yaml index be05ac5..06aefaa 100644 --- a/example/distributed-example.yaml +++ b/example/distributed-example.yaml @@ -15,10 +15,11 @@ oceanbase-ce: - name: server3 ip: 172.19.33.4 global: - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: eth0 + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 # if current hardware's memory capacity is smaller than 50G, please use the setting of "mini-single-example.yaml" and do a small adjustment. memory_limit: 64G # The maximum running memory for an observer # The reserved system memory. system_memory is reserved for general tenants. The default value is 30G. diff --git a/example/distributed-with-obproxy-example.yaml b/example/distributed-with-obproxy-example.yaml index 447237a..bd34782 100644 --- a/example/distributed-with-obproxy-example.yaml +++ b/example/distributed-with-obproxy-example.yaml @@ -15,10 +15,11 @@ oceanbase-ce: - name: server3 ip: 192.168.1.4 global: - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: eth0 + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 # if current hardware's memory capacity is smaller than 50G, please use the setting of "mini-single-example.yaml" and do a small adjustment. memory_limit: 64G # The maximum running memory for an observer # The reserved system memory. system_memory is reserved for general tenants. The default value is 30G. diff --git a/example/grafana/all-components-with-prometheus-and-grafana.yaml b/example/grafana/all-components-with-prometheus-and-grafana.yaml index 97f852e..2b3676c 100644 --- a/example/grafana/all-components-with-prometheus-and-grafana.yaml +++ b/example/grafana/all-components-with-prometheus-and-grafana.yaml @@ -21,10 +21,11 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: eth0 + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 cluster_id: 1 # please set memory limit to a suitable value which is matching resource. memory_limit: 6G # The maximum running memory for an observer diff --git a/example/local-example.yaml b/example/local-example.yaml index dd15e63..43d501c 100644 --- a/example/local-example.yaml +++ b/example/local-example.yaml @@ -9,10 +9,11 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: lo + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 mysql_port: 2881 # External port for OceanBase Database. The default value is 2881. DO NOT change this value after the cluster is started. rpc_port: 2882 # Internal port for OceanBase Database. The default value is 2882. DO NOT change this value after the cluster is started. zone: zone1 diff --git a/example/mini-distributed-example.yaml b/example/mini-distributed-example.yaml index fb5dd47..50b34fe 100644 --- a/example/mini-distributed-example.yaml +++ b/example/mini-distributed-example.yaml @@ -15,10 +15,11 @@ oceanbase-ce: - name: server3 ip: 172.19.33.4 global: - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: eth0 + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 cluster_id: 1 # please set memory limit to a suitable value which is matching resource. memory_limit: 6G # The maximum running memory for an observer diff --git a/example/mini-distributed-with-obproxy-example.yaml b/example/mini-distributed-with-obproxy-example.yaml index 60a0ce1..f9184bf 100644 --- a/example/mini-distributed-with-obproxy-example.yaml +++ b/example/mini-distributed-with-obproxy-example.yaml @@ -15,10 +15,11 @@ oceanbase-ce: - name: server3 ip: 192.168.1.4 global: - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: eth0 + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 cluster_id: 1 # please set memory limit to a suitable value which is matching resource. memory_limit: 6G # The maximum running memory for an observer diff --git a/example/mini-local-example.yaml b/example/mini-local-example.yaml index 0e9eac6..41f4380 100755 --- a/example/mini-local-example.yaml +++ b/example/mini-local-example.yaml @@ -9,10 +9,11 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: lo + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 mysql_port: 2881 # External port for OceanBase Database. The default value is 2881. DO NOT change this value after the cluster is started. rpc_port: 2882 # Internal port for OceanBase Database. The default value is 2882. DO NOT change this value after the cluster is started. zone: zone1 diff --git a/example/mini-single-example.yaml b/example/mini-single-example.yaml index a78b139..a97fe3f 100755 --- a/example/mini-single-example.yaml +++ b/example/mini-single-example.yaml @@ -16,10 +16,11 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: eth0 + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 mysql_port: 2881 # External port for OceanBase Database. The default value is 2881. DO NOT change this value after the cluster is started. rpc_port: 2882 # Internal port for OceanBase Database. The default value is 2882. DO NOT change this value after the cluster is started. zone: zone1 diff --git a/example/mini-single-with-obproxy-example.yaml b/example/mini-single-with-obproxy-example.yaml index 99adb29..16d2df4 100644 --- a/example/mini-single-with-obproxy-example.yaml +++ b/example/mini-single-with-obproxy-example.yaml @@ -16,10 +16,11 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: eth0 + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 mysql_port: 2881 # External port for OceanBase Database. The default value is 2881. DO NOT change this value after the cluster is started. rpc_port: 2882 # Internal port for OceanBase Database. The default value is 2882. DO NOT change this value after the cluster is started. zone: zone1 diff --git a/example/ob-configserver/distributed-with-obproxy-and-configserver-example.yaml b/example/ob-configserver/distributed-with-obproxy-and-configserver-example.yaml index 19188b0..0414d70 100644 --- a/example/ob-configserver/distributed-with-obproxy-and-configserver-example.yaml +++ b/example/ob-configserver/distributed-with-obproxy-and-configserver-example.yaml @@ -24,10 +24,11 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: eth0 + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 cluster_id: 1 # please set memory limit to a suitable value which is matching resource. memory_limit: 6G # The maximum running memory for an observer diff --git a/example/obagent/distributed-with-obproxy-and-obagent-example.yaml b/example/obagent/distributed-with-obproxy-and-obagent-example.yaml index 55d1b30..a4b1b36 100644 --- a/example/obagent/distributed-with-obproxy-and-obagent-example.yaml +++ b/example/obagent/distributed-with-obproxy-and-obagent-example.yaml @@ -15,10 +15,11 @@ oceanbase-ce: - name: server3 ip: 172.19.33.4 global: - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: eth0 + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 # if current hardware's memory capacity is smaller than 50G, please use the setting of "mini-single-example.yaml" and do a small adjustment. memory_limit: 64G # The maximum running memory for an observer # The reserved system memory. system_memory is reserved for general tenants. The default value is 30G. diff --git a/example/obproxy/distributed-with-obproxy-example.yaml b/example/obproxy/distributed-with-obproxy-example.yaml index 447237a..bd34782 100644 --- a/example/obproxy/distributed-with-obproxy-example.yaml +++ b/example/obproxy/distributed-with-obproxy-example.yaml @@ -15,10 +15,11 @@ oceanbase-ce: - name: server3 ip: 192.168.1.4 global: - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: eth0 + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 # if current hardware's memory capacity is smaller than 50G, please use the setting of "mini-single-example.yaml" and do a small adjustment. memory_limit: 64G # The maximum running memory for an observer # The reserved system memory. system_memory is reserved for general tenants. The default value is 30G. diff --git a/example/oceanbase-3.x/distributed-example.yaml b/example/oceanbase-3.x/distributed-example.yaml index fb109d7..eb07fba 100644 --- a/example/oceanbase-3.x/distributed-example.yaml +++ b/example/oceanbase-3.x/distributed-example.yaml @@ -16,9 +16,6 @@ oceanbase-ce: - name: server3 ip: 172.19.33.4 global: - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" devname: eth0 # if current hardware's memory capacity is smaller than 50G, please use the setting of "mini-single-example.yaml" and do a small adjustment. memory_limit: 64G # The maximum running memory for an observer diff --git a/example/oceanbase-3.x/distributed-with-obproxy-and-obagent-example.yaml b/example/oceanbase-3.x/distributed-with-obproxy-and-obagent-example.yaml index c8caf56..706bd18 100644 --- a/example/oceanbase-3.x/distributed-with-obproxy-and-obagent-example.yaml +++ b/example/oceanbase-3.x/distributed-with-obproxy-and-obagent-example.yaml @@ -16,9 +16,6 @@ oceanbase-ce: - name: server3 ip: 172.19.33.4 global: - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" devname: eth0 # if current hardware's memory capacity is smaller than 50G, please use the setting of "mini-single-example.yaml" and do a small adjustment. memory_limit: 64G # The maximum running memory for an observer diff --git a/example/oceanbase-3.x/distributed-with-obproxy-example.yaml b/example/oceanbase-3.x/distributed-with-obproxy-example.yaml index 07d59ef..ef783d1 100644 --- a/example/oceanbase-3.x/distributed-with-obproxy-example.yaml +++ b/example/oceanbase-3.x/distributed-with-obproxy-example.yaml @@ -16,9 +16,6 @@ oceanbase-ce: - name: server3 ip: 192.168.1.4 global: - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" devname: eth0 # if current hardware's memory capacity is smaller than 50G, please use the setting of "mini-single-example.yaml" and do a small adjustment. memory_limit: 64G # The maximum running memory for an observer diff --git a/example/oceanbase-3.x/local-example.yaml b/example/oceanbase-3.x/local-example.yaml index b180d93..720aa37 100644 --- a/example/oceanbase-3.x/local-example.yaml +++ b/example/oceanbase-3.x/local-example.yaml @@ -10,9 +10,6 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" devname: lo mysql_port: 2881 # External port for OceanBase Database. The default value is 2881. DO NOT change this value after the cluster is started. rpc_port: 2882 # Internal port for OceanBase Database. The default value is 2882. DO NOT change this value after the cluster is started. diff --git a/example/oceanbase-3.x/mini-distributed-example.yaml b/example/oceanbase-3.x/mini-distributed-example.yaml index 380c8d2..d7a7704 100644 --- a/example/oceanbase-3.x/mini-distributed-example.yaml +++ b/example/oceanbase-3.x/mini-distributed-example.yaml @@ -16,9 +16,6 @@ oceanbase-ce: - name: server3 ip: 172.19.33.4 global: - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" devname: eth0 cluster_id: 1 # please set memory limit to a suitable value which is matching resource. diff --git a/example/oceanbase-3.x/mini-distributed-with-obproxy-example.yaml b/example/oceanbase-3.x/mini-distributed-with-obproxy-example.yaml index dfa8876..d2056e3 100644 --- a/example/oceanbase-3.x/mini-distributed-with-obproxy-example.yaml +++ b/example/oceanbase-3.x/mini-distributed-with-obproxy-example.yaml @@ -16,9 +16,6 @@ oceanbase-ce: - name: server3 ip: 192.168.1.4 global: - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" devname: eth0 cluster_id: 1 # please set memory limit to a suitable value which is matching resource. diff --git a/example/oceanbase-3.x/mini-local-example.yaml b/example/oceanbase-3.x/mini-local-example.yaml index c23a54e..037fa37 100755 --- a/example/oceanbase-3.x/mini-local-example.yaml +++ b/example/oceanbase-3.x/mini-local-example.yaml @@ -10,9 +10,6 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" devname: lo mysql_port: 2881 # External port for OceanBase Database. The default value is 2881. DO NOT change this value after the cluster is started. rpc_port: 2882 # Internal port for OceanBase Database. The default value is 2882. DO NOT change this value after the cluster is started. diff --git a/example/oceanbase-3.x/mini-single-example.yaml b/example/oceanbase-3.x/mini-single-example.yaml index 2d6790c..09f2959 100755 --- a/example/oceanbase-3.x/mini-single-example.yaml +++ b/example/oceanbase-3.x/mini-single-example.yaml @@ -17,9 +17,6 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" devname: eth0 mysql_port: 2881 # External port for OceanBase Database. The default value is 2881. DO NOT change this value after the cluster is started. rpc_port: 2882 # Internal port for OceanBase Database. The default value is 2882. DO NOT change this value after the cluster is started. diff --git a/example/oceanbase-3.x/mini-single-with-obproxy-example.yaml b/example/oceanbase-3.x/mini-single-with-obproxy-example.yaml index 0e82ea8..f5b5dad 100644 --- a/example/oceanbase-3.x/mini-single-with-obproxy-example.yaml +++ b/example/oceanbase-3.x/mini-single-with-obproxy-example.yaml @@ -17,9 +17,6 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" devname: eth0 mysql_port: 2881 # External port for OceanBase Database. The default value is 2881. DO NOT change this value after the cluster is started. rpc_port: 2882 # Internal port for OceanBase Database. The default value is 2882. DO NOT change this value after the cluster is started. diff --git a/example/oceanbase-3.x/single-example.yaml b/example/oceanbase-3.x/single-example.yaml index e91cd58..eaf1ee5 100644 --- a/example/oceanbase-3.x/single-example.yaml +++ b/example/oceanbase-3.x/single-example.yaml @@ -17,9 +17,6 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" devname: eth0 mysql_port: 2881 # External port for OceanBase Database. The default value is 2881. DO NOT change this value after the cluster is started. rpc_port: 2882 # Internal port for OceanBase Database. The default value is 2882. DO NOT change this value after the cluster is started. diff --git a/example/oceanbase-3.x/single-with-obproxy-example.yaml b/example/oceanbase-3.x/single-with-obproxy-example.yaml index 579c738..a7f481a 100644 --- a/example/oceanbase-3.x/single-with-obproxy-example.yaml +++ b/example/oceanbase-3.x/single-with-obproxy-example.yaml @@ -17,9 +17,6 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" devname: eth0 mysql_port: 2881 # External port for OceanBase Database. The default value is 2881. DO NOT change this value after the cluster is started. rpc_port: 2882 # Internal port for OceanBase Database. The default value is 2882. DO NOT change this value after the cluster is started. diff --git a/example/prometheus/distributed-with-obagent-and-prometheus-example.yaml b/example/prometheus/distributed-with-obagent-and-prometheus-example.yaml index 1eff5af..58756f6 100644 --- a/example/prometheus/distributed-with-obagent-and-prometheus-example.yaml +++ b/example/prometheus/distributed-with-obagent-and-prometheus-example.yaml @@ -15,10 +15,11 @@ oceanbase-ce: - name: server3 ip: 172.19.33.4 global: - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: eth0 + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 # if current hardware's memory capacity is smaller than 50G, please use the setting of "mini-single-example.yaml" and do a small adjustment. memory_limit: 64G # The maximum running memory for an observer # The reserved system memory. system_memory is reserved for general tenants. The default value is 30G. diff --git a/example/single-example.yaml b/example/single-example.yaml index 4c5cecf..527f5ac 100644 --- a/example/single-example.yaml +++ b/example/single-example.yaml @@ -16,10 +16,11 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: eth0 + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 mysql_port: 2881 # External port for OceanBase Database. The default value is 2881. DO NOT change this value after the cluster is started. rpc_port: 2882 # Internal port for OceanBase Database. The default value is 2882. DO NOT change this value after the cluster is started. zone: zone1 diff --git a/example/single-with-obproxy-example.yaml b/example/single-with-obproxy-example.yaml index b39a4ac..76fadf8 100644 --- a/example/single-with-obproxy-example.yaml +++ b/example/single-with-obproxy-example.yaml @@ -16,10 +16,11 @@ oceanbase-ce: # data_dir: /data # The directory for clog, ilog, and slog. The default value is the same as the data_dir value. # redo_dir: /redo - # Please set devname as the network adaptor's name whose ip is in the setting of severs. - # if set severs as "127.0.0.1", please set devname as "lo" - # if current ip is 192.168.1.10, and the ip's network adaptor's name is "eth0", please use "eth0" - devname: eth0 + # Starting from observer version 4.2, the network selection for the observer is based on the 'local_ip' parameter, and the 'devname' parameter is no longer mandatory. + # If the 'local_ip' parameter is set, the observer will first use this parameter for the configuration, regardless of the 'devname' parameter. + # If only the 'devname' parameter is set, the observer will use the 'devname' parameter for the configuration. + # If neither the 'devname' nor the 'local_ip' parameters are set, the 'local_ip' parameter will be automatically assigned the IP address configured above. + # devname: eth0 mysql_port: 2881 # External port for OceanBase Database. The default value is 2881. DO NOT change this value after the cluster is started. rpc_port: 2882 # Internal port for OceanBase Database. The default value is 2882. DO NOT change this value after the cluster is started. zone: zone1 diff --git a/init.sh b/init.sh index 487ef20..27d303c 100644 --- a/init.sh +++ b/init.sh @@ -65,6 +65,8 @@ for DIR in plugins config_parser; do fi done +echo '' >> ${OBD_HOME}/version + echo "============update .bashrc============" ALIAS_OBD_EXIST=$(grep "alias obd=" ~/.bashrc | head -n 1) diff --git a/plugins/ob-configserver/1.0.0/display.py b/plugins/ob-configserver/1.0.0/display.py index bc0b7b7..191a209 100644 --- a/plugins/ob-configserver/1.0.0/display.py +++ b/plugins/ob-configserver/1.0.0/display.py @@ -54,7 +54,7 @@ def display(plugin_context, cursor, *args, **kwargs): lambda x: [x['server'], x['port'], x['vip_address'], x['vip_port'], x['status'], x['pid']], title='ob-configserver') if result: - cmd = "curl -s 'http://{0}:{1}/services?Action=GetObProxyConfig' |jq .".format(result[0]['server'], result[0]['port']) + cmd = "curl -s 'http://{0}:{1}/services?Action=GetObProxyConfig'".format(result[0]['server'], result[0]['port']) stdio.print(cmd) plugin_context.return_true() diff --git a/plugins/obproxy/3.1.0/ocp_check.py b/plugins/obproxy/3.1.0/ocp_check.py index 055be99..144ca67 100644 --- a/plugins/obproxy/3.1.0/ocp_check.py +++ b/plugins/obproxy/3.1.0/ocp_check.py @@ -33,19 +33,16 @@ def ocp_check(plugin_context, ocp_version, cursor, new_cluster_config=None, new_ only_one = True min_version = Version('3.1.1') - max_version = min_version + ocp_version_420 = Version("4.2.0") ocp_version = Version(ocp_version) if ocp_version < min_version: stdio.error('The current plugin version does not support OCP V%s' % ocp_version) return - if ocp_version > max_version: - stdio.warn('The plugin library does not support OCP V%s. The takeover requirements are not applicable to the current check.' % ocp_version) - for server in cluster_config.servers: client = clients[server] - if is_admin and client.config.username != 'admin': + if is_admin and client.config.username != 'admin' and ocp_version < ocp_version_420: is_admin = False stdio.error('The current user must be the admin user. Run the edit-config command to modify the user.username field') if can_sudo and not client.execute_command('sudo whoami'): @@ -55,6 +52,6 @@ def ocp_check(plugin_context, ocp_version, cursor, new_cluster_config=None, new_ only_one = False stdio.error('%s Multiple OBProxies exist.' % server) - if is_admin and can_sudo and only_one: + if (is_admin or ocp_version >= ocp_version_420) and can_sudo and only_one: stdio.print('Configurations of the OBProxy can be taken over by OCP after they take effect.' if new_cluster_config else 'Configurations of the OBProxy can be taken over by OCP.') - return plugin_context.return_true() \ No newline at end of file + return plugin_context.return_true() diff --git a/plugins/oceanbase-diagnostic-tool/1.0/analyze_log.py b/plugins/oceanbase-diagnostic-tool/1.0/analyze_log.py new file mode 100644 index 0000000..2e1abfe --- /dev/null +++ b/plugins/oceanbase-diagnostic-tool/1.0/analyze_log.py @@ -0,0 +1,105 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + + +from __future__ import absolute_import, division, print_function +from ssh import LocalClient +import datetime +import os +from tool import TimeUtils +from subprocess import call, Popen, PIPE +import _errno as err + + +def analyze_log(plugin_context, *args, **kwargs): + def get_option(key, default=''): + value = getattr(options, key) + if value is None: + value = default + stdio.verbose('get option: %s value %s' % (key, value)) + return value + + def local_execute_command(command, env=None, timeout=None): + command = r"cd {install_dir} && sh ".format(install_dir=obdiag_install_dir) + command + return LocalClient.execute_command(command, env, timeout, stdio) + + def get_obdiag_cmd(): + base_commond=r"cd {install_dir} && ./obdiag analyze log".format(install_dir=obdiag_install_dir) + if files_option_path: + cmd = r"{base} --files {files_option_path}".format( + base = base_commond, + files_option_path = files_option_path, + ) + else: + cmd = r"{base} --from {from_option} --to {to_option} --scope {scope_option}".format( + base = base_commond, + from_option = from_option, + to_option = to_option, + scope_option = scope_option, + ) + if ob_install_dir_option: + cmd = cmd + r" --ob_install_dir {ob_install_dir_option}".format(ob_install_dir_option=ob_install_dir_option) + if store_dir_option: + cmd = cmd + r" --store_dir {store_dir_option}".format(store_dir_option=store_dir_option) + if grep_option: + cmd = cmd + r" --grep '{grep_option}'".format(grep_option=grep_option) + if log_level_option: + cmd = cmd + r" --log_level '{log_level_option}'".format(log_level_option=log_level_option) + return cmd + + def run(): + obdiag_cmd = get_obdiag_cmd() + stdio.verbose('execute cmd: {}'.format(obdiag_cmd)) + return LocalClient.run_command(obdiag_cmd, env=None, stdio=stdio) + + options = plugin_context.options + obdiag_bin = "obdiag" + ob_install_dir_option = None + files_option_path = None + cluster_config = plugin_context.cluster_config + stdio = plugin_context.stdio + from_option = get_option('from') + to_option = get_option('to') + scope_option = get_option('scope') + since_option = get_option('since') + grep_option = get_option('grep') + log_level_option = get_option('log_level') + files_option = get_option('files') + if files_option: + files_option_path = os.path.abspath(get_option('files')) + store_dir_option = os.path.abspath(get_option('store_dir')) + obdiag_install_dir = get_option('obdiag_dir') + if not files_option: + global_conf = cluster_config.get_global_conf() + ob_install_dir_option = global_conf.get('home_path') + + from_option, to_option, ok = TimeUtils().parse_time_from_to(from_time=from_option, to_time=to_option, stdio=stdio) + if not ok: + from_option, to_option = TimeUtils().parse_time_since(since=since_option) + + ret = local_execute_command('%s --help' % obdiag_bin) + if not ret: + stdio.error(err.EC_OBDIAG_NOT_FOUND.format()) + return plugin_context.return_false() + try: + if run(): + plugin_context.return_true() + except KeyboardInterrupt: + stdio.exception("obdiag analyze log failded") + return plugin_context.return_false() \ No newline at end of file diff --git a/plugins/oceanbase-diagnostic-tool/1.0/checker.py b/plugins/oceanbase-diagnostic-tool/1.0/checker.py new file mode 100644 index 0000000..26dc068 --- /dev/null +++ b/plugins/oceanbase-diagnostic-tool/1.0/checker.py @@ -0,0 +1,96 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + + +from __future__ import absolute_import, division, print_function + +from ssh import LocalClient +import _errno as err +import sys +from tool import FileUtil, YamlLoader + +if sys.version_info.major == 2: + import MySQLdb as mysql +else: + import pymysql as mysql + +def checker(plugin_context, *args, **kwargs): + stdio = plugin_context.stdio + options = plugin_context.options + def get_option(key, default=''): + value = getattr(options, key) + if value is None: + value = default + stdio.verbose('get option: %s value %s' % (key, value)) + return value + + def local_execute_command(command, env=None, timeout=None): + command = r"cd {install_dir} && sh ".format(install_dir=obdiag_install_dir) + command + return LocalClient.execute_command(command, env, timeout, stdio) + + def get_obdiag_cmd(): + base_commond = r"{install_dir}/obdiag check".format(install_dir=obdiag_install_dir) + # check options + if cases: + cmd = r"{base} --cases {cases}".format( + base=base_commond, + cases=cases, + ) + else: + cmd = r"{base}".format(base=base_commond) + return cmd + + def run(): + obdiag_cmd = get_obdiag_cmd() + stdio.verbose('execute cmd: {}'.format(obdiag_cmd)) + return LocalClient.run_command(obdiag_cmd, env=None, stdio=stdio) + + obdiag_bin = "obdiag" + cases = get_option('cases') + obdiag_install_dir = get_option('obdiag_dir') + # get obdiag_conf + obdiag_conf_yaml_path = obdiag_install_dir + "/conf/config.yml" + with FileUtil.open(obdiag_conf_yaml_path) as f: + obdiag_info = YamlLoader(stdio=stdio).load(f) + obdiag_obcluster_info = obdiag_info['OBCLUSTER'] + db_host = obdiag_obcluster_info["host"] + db_port = obdiag_obcluster_info["port"] + db_user = obdiag_obcluster_info["user"] + db_password = obdiag_obcluster_info["password"] + + ret = local_execute_command('%s --help' % obdiag_bin) + if not ret: + stdio.error(err.EC_OBDIAG_NOT_FOUND.format()) + return plugin_context.return_false() + + stdio.start_loading('Check database connectivity') + try: + mysql.connect(host=db_host, user=db_user, port=int(db_port), password=str(db_password), cursorclass=mysql.cursors.DictCursor) + except Exception: + stdio.stop_loading('fail') + stdio.error('cluster :{0} . Invalid cluster information. Please check the conf in OBD'.format(obdiag_obcluster_info)) + return plugin_context.return_false() + stdio.stop_loading('succeed') + + try: + if run(): + plugin_context.return_true() + except KeyboardInterrupt: + stdio.exception("obdiag check failded") + return plugin_context.return_false() diff --git a/plugins/oceanbase-diagnostic-tool/1.0/gather_all.py b/plugins/oceanbase-diagnostic-tool/1.0/gather_all.py index 11ee81d..a0a8c44 100644 --- a/plugins/oceanbase-diagnostic-tool/1.0/gather_all.py +++ b/plugins/oceanbase-diagnostic-tool/1.0/gather_all.py @@ -44,7 +44,7 @@ def local_execute_command(command, env=None, timeout=None): return LocalClient.execute_command(command, env, timeout, stdio) def get_obdiag_cmd(): - base_commond=r"cd {install_dir} && sh obdiag gather all".format(install_dir=obdiag_install_dir) + base_commond=r"cd {install_dir} && ./obdiag gather all".format(install_dir=obdiag_install_dir) cmd = r"{base} --cluster_name {cluster_name} --from {from_option} --to {to_option} --scope {scope_option} --encrypt {encrypt_option}".format( base=base_commond, cluster_name=cluster_name, @@ -68,17 +68,7 @@ def get_obdiag_cmd(): def run(): obdiag_cmd = get_obdiag_cmd() stdio.verbose('execute cmd: {}'.format(obdiag_cmd)) - p = None - return_code = 255 - try: - p = Popen(obdiag_cmd, shell=True) - return_code = p.wait() - except: - stdio.exception("") - if p: - p.kill() - stdio.verbose('exit code: {}'.format(return_code)) - return return_code == 0 + return LocalClient.run_command(obdiag_cmd, env=None, stdio=stdio) options = plugin_context.options obdiag_bin = "obdiag" @@ -112,14 +102,9 @@ def run(): clog_dir = server_config['clog_dir'] slog_dir = server_config['slog_dir'] - try: - if (not from_option) and (not to_option) and since_option: - now_time = datetime.datetime.now() - to_option = (now_time + datetime.timedelta(minutes=10)).strftime('%Y-%m-%d %H:%M:%S') - from_option = (now_time - datetime.timedelta(seconds=TimeUtils.parse_time_sec(since_option))).strftime('%Y-%m-%d %H:%M:%S') - except: - stdio.error(err.EC_OBDIAG_OPTIONS_FORMAT_ERROR.format(option="since", value=since_option)) - return plugin_context.return_false() + from_option, to_option, ok = TimeUtils.parse_time_from_to(from_time=from_option, to_time=to_option, stdio=stdio) + if not ok: + from_option, to_option = TimeUtils.parse_time_since(since=since_option) ret = local_execute_command('%s --help' % obdiag_bin) if not ret: diff --git a/plugins/oceanbase-diagnostic-tool/1.0/gather_clog.py b/plugins/oceanbase-diagnostic-tool/1.0/gather_clog.py index 70ff35d..eaf4987 100644 --- a/plugins/oceanbase-diagnostic-tool/1.0/gather_clog.py +++ b/plugins/oceanbase-diagnostic-tool/1.0/gather_clog.py @@ -40,7 +40,7 @@ def local_execute_command(command, env=None, timeout=None): return LocalClient.execute_command(command, env, timeout, stdio) def get_obdiag_cmd(): - base_commond = r"cd {install_dir} && sh obdiag gather clog".format(install_dir=obdiag_install_dir) + base_commond = r"cd {install_dir} && ./obdiag gather clog".format(install_dir=obdiag_install_dir) cmd = r"{base} --clog_dir {data_dir} --from {from_option} --to {to_option} --encrypt {encrypt_option}".format( base = base_commond, data_dir = data_dir, @@ -57,17 +57,7 @@ def get_obdiag_cmd(): def run(): obdiag_cmd = get_obdiag_cmd() stdio.verbose('execute cmd: {}'.format(obdiag_cmd)) - p = None - return_code = 255 - try: - p = Popen(obdiag_cmd, shell=True) - return_code = p.wait() - except: - stdio.exception("") - if p: - p.kill() - stdio.verbose('exit code: {}'.format(return_code)) - return return_code == 0 + return LocalClient.run_command(obdiag_cmd, env=None, stdio=stdio) options = plugin_context.options obdiag_bin = "obdiag" @@ -93,14 +83,9 @@ def run(): server_config['clog_dir'] = '%s/clog' % server_config['redo_dir'] data_dir = server_config['clog_dir'] - try: - if (not from_option) and (not to_option) and since_option: - now_time = datetime.datetime.now() - to_option = (now_time + datetime.timedelta(minutes=10)).strftime('%Y-%m-%d %H:%M:%S') - from_option = (now_time - datetime.timedelta(seconds=TimeUtils.parse_time_sec(since_option))).strftime('%Y-%m-%d %H:%M:%S') - except: - stdio.error(err.EC_OBDIAG_OPTIONS_FORMAT_ERROR.format(option="since", value=since_option)) - return plugin_context.return_false() + from_option, to_option, ok = TimeUtils.parse_time_from_to(from_time=from_option, to_time=to_option, stdio=stdio) + if not ok: + from_option, to_option = TimeUtils.parse_time_since(since=since_option) ret = local_execute_command('%s --help' % obdiag_bin) diff --git a/plugins/oceanbase-diagnostic-tool/1.0/gather_log.py b/plugins/oceanbase-diagnostic-tool/1.0/gather_log.py index c4a8bce..2adb1c1 100644 --- a/plugins/oceanbase-diagnostic-tool/1.0/gather_log.py +++ b/plugins/oceanbase-diagnostic-tool/1.0/gather_log.py @@ -40,7 +40,7 @@ def local_execute_command(command, env=None, timeout=None): return LocalClient.execute_command(command, env, timeout, stdio) def get_obdiag_cmd(): - base_commond=r"cd {install_dir} && sh obdiag gather log".format(install_dir=obdiag_install_dir) + base_commond=r"cd {install_dir} && ./obdiag gather log".format(install_dir=obdiag_install_dir) cmd = r"{base} --from {from_option} --to {to_option} --scope {scope_option} --encrypt {encrypt_option}".format( base = base_commond, from_option = from_option, @@ -59,17 +59,7 @@ def get_obdiag_cmd(): def run(): obdiag_cmd = get_obdiag_cmd() stdio.verbose('execute cmd: {}'.format(obdiag_cmd)) - p = None - return_code = 255 - try: - p = Popen(obdiag_cmd, shell=True) - return_code = p.wait() - except: - stdio.exception("") - if p: - p.kill() - stdio.verbose('exit code: {}'.format(return_code)) - return return_code == 0 + return LocalClient.run_command(obdiag_cmd, env=None, stdio=stdio) options = plugin_context.options obdiag_bin = "obdiag" @@ -85,14 +75,9 @@ def run(): store_dir_option = os.path.abspath(get_option('store_dir')) ob_install_dir_option = global_conf.get('home_path') obdiag_install_dir = get_option('obdiag_dir') - try: - if (not from_option) and (not to_option) and since_option: - now_time = datetime.datetime.now() - to_option = (now_time + datetime.timedelta(minutes=1)).strftime('%Y-%m-%d %H:%M:%S') - from_option = (now_time - datetime.timedelta(seconds=TimeUtils.parse_time_sec(since_option))).strftime('%Y-%m-%d %H:%M:%S') - except: - stdio.error(err.EC_OBDIAG_OPTIONS_FORMAT_ERROR.format(option="since", value=since_option)) - return plugin_context.return_false() + from_option, to_option, ok = TimeUtils.parse_time_from_to(from_time=from_option, to_time=to_option, stdio=stdio) + if not ok: + from_option, to_option = TimeUtils.parse_time_since(since=since_option) ret = local_execute_command('%s --help' % obdiag_bin) if not ret: diff --git a/plugins/oceanbase-diagnostic-tool/1.0/gather_obproxy_log.py b/plugins/oceanbase-diagnostic-tool/1.0/gather_obproxy_log.py index 597dbb8..7bfcf20 100644 --- a/plugins/oceanbase-diagnostic-tool/1.0/gather_obproxy_log.py +++ b/plugins/oceanbase-diagnostic-tool/1.0/gather_obproxy_log.py @@ -40,7 +40,7 @@ def local_execute_command(command, env=None, timeout=None): return LocalClient.execute_command(command, env, timeout, stdio) def get_obdiag_cmd(): - base_commond=r"cd {install_dir} && sh obdiag gather obproxy_log".format(install_dir=obdiag_install_dir) + base_commond=r"cd {install_dir} && ./obdiag gather obproxy_log".format(install_dir=obdiag_install_dir) cmd = r"{base} --from {from_option} --to {to_option} --scope {scope_option} --encrypt {encrypt_option}".format( base = base_commond, from_option = from_option, @@ -59,17 +59,7 @@ def get_obdiag_cmd(): def run(): obdiag_cmd = get_obdiag_cmd() stdio.verbose('execute cmd: {}'.format(obdiag_cmd)) - p = None - return_code = 255 - try: - p = Popen(obdiag_cmd, shell=True) - return_code = p.wait() - except: - stdio.exception("") - if p: - p.kill() - stdio.verbose('exit code: {}'.format(return_code)) - return return_code == 0 + return LocalClient.run_command(obdiag_cmd, env=None, stdio=stdio) options = plugin_context.options obdiag_bin = "obdiag" @@ -86,14 +76,9 @@ def run(): obproxy_install_dir_option=global_conf.get('home_path') obdiag_install_dir = get_option('obdiag_dir') - try: - if (not from_option) and (not to_option) and since_option: - now_time = datetime.datetime.now() - to_option = (now_time + datetime.timedelta(minutes=1)).strftime('%Y-%m-%d %H:%M:%S') - from_option = (now_time - datetime.timedelta(seconds=TimeUtils.parse_time_sec(since_option))).strftime('%Y-%m-%d %H:%M:%S') - except: - stdio.error(err.EC_OBDIAG_OPTIONS_FORMAT_ERROR.format(option="since", value=since_option)) - return plugin_context.return_false() + from_option, to_option, ok = TimeUtils.parse_time_from_to(from_time=from_option, to_time=to_option, stdio=stdio) + if not ok: + from_option, to_option = TimeUtils.parse_time_since(since=since_option) ret = local_execute_command('%s --help' % obdiag_bin) if not ret: diff --git a/plugins/oceanbase-diagnostic-tool/1.0/gather_perf.py b/plugins/oceanbase-diagnostic-tool/1.0/gather_perf.py index 0ab01ee..a9132d9 100644 --- a/plugins/oceanbase-diagnostic-tool/1.0/gather_perf.py +++ b/plugins/oceanbase-diagnostic-tool/1.0/gather_perf.py @@ -38,7 +38,7 @@ def local_execute_command(command, env=None, timeout=None): return LocalClient.execute_command(command, env, timeout, stdio) def get_obdiag_cmd(): - base_commond=r"cd {install_dir} && sh obdiag gather perf".format(install_dir=obdiag_install_dir) + base_commond=r"cd {install_dir} && ./obdiag gather perf".format(install_dir=obdiag_install_dir) cmd = r"{base} --scope {scope_option} ".format( base = base_commond, scope_option = scope_option @@ -52,17 +52,7 @@ def get_obdiag_cmd(): def run(): obdiag_cmd = get_obdiag_cmd() stdio.verbose('execute cmd: {}'.format(obdiag_cmd)) - p = None - return_code = 255 - try: - p = Popen(obdiag_cmd, shell=True) - return_code = p.wait() - except: - stdio.exception("") - if p: - p.kill() - stdio.verbose('exit code: {}'.format(return_code)) - return return_code == 0 + return LocalClient.run_command(obdiag_cmd, env=None, stdio=stdio) options = plugin_context.options obdiag_bin = "obdiag" diff --git a/plugins/oceanbase-diagnostic-tool/1.0/gather_plan_monitor.py b/plugins/oceanbase-diagnostic-tool/1.0/gather_plan_monitor.py index 0f4b2b5..e09485f 100644 --- a/plugins/oceanbase-diagnostic-tool/1.0/gather_plan_monitor.py +++ b/plugins/oceanbase-diagnostic-tool/1.0/gather_plan_monitor.py @@ -38,7 +38,7 @@ def local_execute_command(command, env=None, timeout=None): return LocalClient.execute_command(command, env, timeout, stdio) def get_obdiag_cmd(): - base_commond=r"cd {install_dir} && sh obdiag gather plan_monitor".format(install_dir=obdiag_install_dir) + base_commond=r"cd {install_dir} && ./obdiag gather plan_monitor".format(install_dir=obdiag_install_dir) cmd = r"{base} --trace_id {trace_id}".format( base=base_commond, trace_id=trace_id, @@ -50,17 +50,7 @@ def get_obdiag_cmd(): def run(): obdiag_cmd = get_obdiag_cmd() stdio.verbose('execute cmd: {}'.format(obdiag_cmd)) - p = None - return_code = 255 - try: - p = Popen(obdiag_cmd, shell=True) - return_code = p.wait() - except: - stdio.exception("") - if p: - p.kill() - stdio.verbose('exit code: {}'.format(return_code)) - return return_code == 0 + return LocalClient.run_command(obdiag_cmd, env=None, stdio=stdio) options = plugin_context.options obdiag_bin = "obdiag" diff --git a/plugins/oceanbase-diagnostic-tool/1.0/gather_slog.py b/plugins/oceanbase-diagnostic-tool/1.0/gather_slog.py index 056d4cb..ac49b57 100644 --- a/plugins/oceanbase-diagnostic-tool/1.0/gather_slog.py +++ b/plugins/oceanbase-diagnostic-tool/1.0/gather_slog.py @@ -44,7 +44,7 @@ def local_execute_command(command, env=None, timeout=None): return LocalClient.execute_command(command, env, timeout, stdio) def get_obdiag_cmd(): - base_commond = r"cd {install_dir} && sh obdiag gather slog".format(install_dir=obdiag_install_dir) + base_commond = r"cd {install_dir} && ./obdiag gather slog".format(install_dir=obdiag_install_dir) cmd = r"{base} --slog_dir {data_dir} --from {from_option} --to {to_option} --encrypt {encrypt_option}".format( base = base_commond, data_dir = data_dir, @@ -61,17 +61,7 @@ def get_obdiag_cmd(): def run(): obdiag_cmd = get_obdiag_cmd() stdio.verbose('execute cmd: {}'.format(obdiag_cmd)) - p = None - return_code = 255 - try: - p = Popen(obdiag_cmd, shell=True) - return_code = p.wait() - except: - stdio.exception("") - if p: - p.kill() - stdio.verbose('exit code: {}'.format(return_code)) - return return_code == 0 + return LocalClient.run_command(obdiag_cmd, env=None, stdio=stdio) options = plugin_context.options obdiag_bin = "obdiag" @@ -98,14 +88,9 @@ def run(): server_config['slog_dir'] = '%s/slog' % server_config[mount_key] data_dir = server_config['slog_dir'] - try: - if (not from_option) and (not to_option) and since_option: - now_time = datetime.datetime.now() - to_option = (now_time + datetime.timedelta(minutes=10)).strftime('%Y-%m-%d %H:%M:%S') - from_option = (now_time - datetime.timedelta(seconds=TimeUtils.parse_time_sec(since_option))).strftime('%Y-%m-%d %H:%M:%S') - except: - stdio.error(err.EC_OBDIAG_OPTIONS_FORMAT_ERROR.format(option="since", value=since_option)) - return plugin_context.return_false() + from_option, to_option, ok = TimeUtils.parse_time_from_to(from_time=from_option, to_time=to_option, stdio=stdio) + if not ok: + from_option, to_option = TimeUtils.parse_time_since(since=since_option) ret = local_execute_command('%s --help' % obdiag_bin) if not ret: diff --git a/plugins/oceanbase-diagnostic-tool/1.0/gather_stack.py b/plugins/oceanbase-diagnostic-tool/1.0/gather_stack.py index c4c5571..320f1ef 100644 --- a/plugins/oceanbase-diagnostic-tool/1.0/gather_stack.py +++ b/plugins/oceanbase-diagnostic-tool/1.0/gather_stack.py @@ -38,7 +38,7 @@ def local_execute_command(command, env=None, timeout=None): return LocalClient.execute_command(command, env, timeout, stdio) def get_obdiag_cmd(): - base_commond = r"cd {install_dir} && sh obdiag gather stack".format(install_dir=obdiag_install_dir) + base_commond = r"cd {install_dir} && ./obdiag gather stack".format(install_dir=obdiag_install_dir) cmd = r"{base} ".format( base = base_commond ) @@ -51,17 +51,7 @@ def get_obdiag_cmd(): def run(): obdiag_cmd = get_obdiag_cmd() stdio.verbose('execute cmd: {}'.format(obdiag_cmd)) - p = None - return_code = 255 - try: - p = Popen(obdiag_cmd, shell=True) - return_code = p.wait() - except: - stdio.exception("") - if p: - p.kill() - stdio.verbose('exit code: {}'.format(return_code)) - return return_code == 0 + return LocalClient.run_command(obdiag_cmd, env=None, stdio=stdio) options = plugin_context.options obdiag_bin = "obdiag" diff --git a/plugins/oceanbase-diagnostic-tool/1.0/gather_sysstat.py b/plugins/oceanbase-diagnostic-tool/1.0/gather_sysstat.py index 79bd78c..98a28a6 100644 --- a/plugins/oceanbase-diagnostic-tool/1.0/gather_sysstat.py +++ b/plugins/oceanbase-diagnostic-tool/1.0/gather_sysstat.py @@ -38,7 +38,7 @@ def local_execute_command(command, env=None, timeout=None): return LocalClient.execute_command(command, env, timeout, stdio) def get_obdiag_cmd(): - base_commond=r"cd {install_dir} && sh obdiag gather sysstat".format(install_dir=obdiag_install_dir) + base_commond=r"cd {install_dir} && ./obdiag gather sysstat".format(install_dir=obdiag_install_dir) cmd = r"{base}".format( base=base_commond, ) @@ -49,17 +49,7 @@ def get_obdiag_cmd(): def run(): obdiag_cmd = get_obdiag_cmd() stdio.verbose('execute cmd: {}'.format(obdiag_cmd)) - p = None - return_code = 255 - try: - p = Popen(obdiag_cmd, shell=True) - return_code = p.wait() - except: - stdio.exception("") - if p: - p.kill() - stdio.verbose('exit code: {}'.format(return_code)) - return return_code == 0 + return LocalClient.run_command(obdiag_cmd, env=None, stdio=stdio) options = plugin_context.options obdiag_bin = "obdiag" diff --git a/plugins/oceanbase-diagnostic-tool/1.0/generate_config.py b/plugins/oceanbase-diagnostic-tool/1.0/generate_config.py index fc51c43..497535d 100644 --- a/plugins/oceanbase-diagnostic-tool/1.0/generate_config.py +++ b/plugins/oceanbase-diagnostic-tool/1.0/generate_config.py @@ -36,7 +36,7 @@ "log_filename": "obdiag.log", "log_level": "INFO", "mode": "obdiag", - "stdout_handler_log_level": "DEBUG" + "stdout_handler_log_level": "INFO" } } } @@ -81,6 +81,7 @@ def get_obdiag_config(): nodeItem["user"] = parse_empty(user_config.username) nodeItem["password"] = parse_empty(user_config.password) nodeItem["private_key"] = parse_empty(user_config.key_file) + nodeItem["home_path"] = cluster_config.get_server_conf(server).get("home_path") nodes.append(nodeItem) nodes_config = nodes @@ -114,11 +115,22 @@ def get_obdiag_config(): obcluster_config["password"] = global_conf.get('root_password') if global_conf.get('mysql_port') is not None: obcluster_config["port"] = global_conf.get('mysql_port') + checker_config = {} + checker_config["ignore_obversion"]=False + checker_config["report"] = {} + if "report_path" in checker_config["report"]: + checker_config["report"]["report_path"] = get_option('report_path') + else: + checker_config["report"]["report_path"]= "./check_report/" + checker_config["report"]["export_type"] = "table" + checker_config["package_file"] = obdiag_install_dir+"/check_package.yaml" + checker_config["tasks_base_path"] = obdiag_install_dir+"/handler/checker/tasks/" config={ "OBDIAG": base_config, "OCP": ocp_config, "OBCLUSTER": obcluster_config, - "NODES":nodes_config + "NODES":nodes_config, + "CHECK": checker_config } return config diff --git a/plugins/oceanbase-diagnostic-tool/1.0/pre_check.py b/plugins/oceanbase-diagnostic-tool/1.0/pre_check.py index cf8d1e7..2969d54 100644 --- a/plugins/oceanbase-diagnostic-tool/1.0/pre_check.py +++ b/plugins/oceanbase-diagnostic-tool/1.0/pre_check.py @@ -52,7 +52,7 @@ def utils_work_dir_checker(util_name): def version_checker(): client = LocalClient check_status = {} - ret = client.execute_command('cd {} && sh obdiag version'.format(obdiag_path)) + ret = client.execute_command('cd {} && ./obdiag version'.format(obdiag_path)) if not ret: check_status = {'version_checker_status': False, 'obdiag_version': obdiag_new_version, 'obdiag_found': False} return check_status @@ -63,7 +63,7 @@ def version_checker(): return check_status else: major_version = found.group(1) - if Version(major_version) < Version(obdiag_new_version): + if Version(major_version) > Version(obdiag_new_version): check_status = {'version_checker_status': True, 'obdiag_version': major_version, 'obdiag_found': True} return check_status else: diff --git a/plugins/oceanbase/3.1.0/connect.py b/plugins/oceanbase/3.1.0/connect.py index 2db330c..578ed93 100644 --- a/plugins/oceanbase/3.1.0/connect.py +++ b/plugins/oceanbase/3.1.0/connect.py @@ -22,6 +22,7 @@ import sys import time +import re from copy import copy if sys.version_info.major == 2: import MySQLdb as mysql @@ -96,6 +97,10 @@ def execute(self, sql, args=None, execute_func=None, raise_exception=None, exc_l return getattr(self.cursor, execute_func)() except Exception as e: getattr(stdio, exc_level)(EC_SQL_EXECUTE_FAILED.format(sql=sql)) + pattern = r'\n\[(.*?)\]\s+\[(.*?)\]\s+\[(.*?)\]$' + error_matches = re.findall(pattern, str(e.args[-1])) + if len(error_matches) > 0 and len(error_matches[-1]) == 3: + getattr(stdio, exc_level)("observer error trace [%s] from [%s]" % (error_matches[-1][2], error_matches[-1][0])) if raise_exception is None: raise_exception = self._raise_exception if raise_exception: diff --git a/plugins/oceanbase/3.1.0/ocp_check.py b/plugins/oceanbase/3.1.0/ocp_check.py index d0af70b..7aebcaf 100644 --- a/plugins/oceanbase/3.1.0/ocp_check.py +++ b/plugins/oceanbase/3.1.0/ocp_check.py @@ -35,19 +35,16 @@ def ocp_check(plugin_context, ocp_version, cursor, new_cluster_config=None, new_ pwd_not_empty = True min_version = Version('3.1.1') - max_version = min_version + ocp_version_420 = Version("4.2.0") ocp_version = Version(ocp_version) if ocp_version < min_version: stdio.error('The current plugin version does not support OCP V%s' % ocp_version) return - if ocp_version > max_version: - stdio.warn('The plugin library does not support OCP V%s. The takeover requirements are not applicable to the current check.' % ocp_version) - for server in cluster_config.servers: client = clients[server] - if is_admin and client.config.username != 'admin': + if is_admin and client.config.username != 'admin' and ocp_version < ocp_version_420: is_admin = False stdio.error('The current user must be the admin user. Run the edit-config command to modify the user.username field') if can_sudo and not client.execute_command('sudo whoami'): @@ -79,12 +76,15 @@ def ocp_check(plugin_context, ocp_version, cursor, new_cluster_config=None, new_ keys = list(config.keys()) if '$_zone_idc' in keys and isinstance(keys[keys.index('$_zone_idc')], InnerConfigItem): del zones[zone] - if zones: + if zones and ocp_version < ocp_version_420: if not cluster_config.parser or cluster_config.parser.STYLE == 'default': stdio.error('Zone: IDC information is missing for %s. Run the chst command to change the configuration style of %s to cluster, and then run the edit-config command to add IDC information.' % (','.join(zones.keys()), cluster_config.name)) else: stdio.error('Zone: IDC information is missing for %s. Run the edit-config command to add IDC information.' % ','.join(zones.keys())) + else: + zones = {} - if is_admin and can_sudo and only_one and pwd_not_empty and not zones: + # if ocp version is greater than 4.2.0, then admin and zone idc check is not needed + if can_sudo and only_one and pwd_not_empty and is_admin and not zones: stdio.print('Configurations of the %s can be taken over by OCP after they take effect.' % cluster_config.name if new_cluster_config else 'Configurations of the %s can be taken over by OCP.' % cluster_config.name) - return plugin_context.return_true() \ No newline at end of file + return plugin_context.return_true() diff --git a/plugins/oceanbase/3.1.0/reload.py b/plugins/oceanbase/3.1.0/reload.py index 385ed9f..3360a60 100644 --- a/plugins/oceanbase/3.1.0/reload.py +++ b/plugins/oceanbase/3.1.0/reload.py @@ -31,6 +31,7 @@ def reload(plugin_context, cursor, new_cluster_config, *args, **kwargs): inner_config = { InnerConfigItem('$_zone_idc'): 'idc' } + not_paramters = ['production_mode'] inner_keys = inner_config.keys() zones_config = {} cluster_server = {} @@ -47,6 +48,9 @@ def reload(plugin_context, cursor, new_cluster_config, *args, **kwargs): cluster_server[server] = '%s:%s' % (server.ip, config['rpc_port']) stdio.verbose('compare configuration of %s' % (server)) for key in new_config: + if key in not_paramters: + stdio.verbose('%s is not a oceanbase parameter. skip' % key) + continue n_value = new_config[key] if key not in config or config[key] != n_value: if isinstance(key, InnerConfigItem) and key in inner_keys: diff --git a/plugins/oceanbase/3.1.0/start_check.py b/plugins/oceanbase/3.1.0/start_check.py index 0b0824f..8211dc1 100644 --- a/plugins/oceanbase/3.1.0/start_check.py +++ b/plugins/oceanbase/3.1.0/start_check.py @@ -29,7 +29,7 @@ stdio = None success = True - +production_mode = False def get_port_socket_inode(client, port): port = hex(port)[2:].zfill(4).upper() @@ -105,7 +105,7 @@ def get_disk_info(all_paths, client, stdio): return disk_info -def start_check(plugin_context, init_check_status=False, strict_check=False, work_dir_check=False, work_dir_empty_check=True, generate_configs={}, precheck=False, *args, **kwargs): +def start_check(plugin_context, init_check_status=False, strict_check=False, work_dir_check=False, work_dir_empty_check=True, generate_configs={}, precheck=False, source_option='start', *args, **kwargs): def check_pass(item): status = check_status[server] if status[item].status == err.CheckStatus.WAIT: @@ -125,9 +125,19 @@ def alert(item, error, suggests=[]): if strict_check: success = False check_fail(item, error, suggests) - stdio.error(error) + print_with_suggests(error, suggests) + else: + stdio.warn(error) + + def alert_strict(item, error, suggests=[]): + global success + if strict_check or production_mode: + success = False + check_fail(item, error, suggests) + print_with_suggests(error, suggests) else: stdio.warn(error) + def error(item, _error, suggests=[]): global success if plugin_context.dev_mode: @@ -135,12 +145,16 @@ def error(item, _error, suggests=[]): else: success = False check_fail(item, _error, suggests) - stdio.error(_error) + print_with_suggests(_error, suggests) + def critical(item, error, suggests=[]): global success success = False check_fail(item, error, suggests) - stdio.error(error) + print_with_suggests(error, suggests) + + def print_with_suggests(error, suggests=[]): + stdio.error('{}, {}'.format(error, suggests[0].msg if suggests else '')) def system_memory_check(): server_memory_config = server_memory_stat['servers'] @@ -162,7 +176,21 @@ def system_memory_check(): success = True check_status = {} cluster_config = plugin_context.cluster_config + INF = float('inf') plugin_context.set_variable('start_check_status', check_status) + + kernel_check_items = [ + {'check_item': 'vm.max_map_count', 'need': [327600, 1310720], 'recommend': 655360}, + {'check_item': 'vm.min_free_kbytes', 'need': [32768, 2097152], 'recommend': 2097152}, + {'check_item': 'vm.overcommit_memory', 'need': 0, 'recommend': 0}, + {'check_item': 'fs.file-max', 'need': [6573688, INF], 'recommend': 6573688}, + ] + + kernel_check_status = {} + for kernel_param in kernel_check_items: + check_item = kernel_param['check_item'] + kernel_check_status[check_item] = err.CheckStatus() + for server in cluster_config.servers: check_status[server] = { 'port': err.CheckStatus(), @@ -173,6 +201,7 @@ def system_memory_check(): 'net': err.CheckStatus(), 'ntp': err.CheckStatus(), } + check_status[server].update(kernel_check_status) if work_dir_check: check_status[server]['dir'] = err.CheckStatus() @@ -181,18 +210,22 @@ def system_memory_check(): clients = plugin_context.clients stdio = plugin_context.stdio - stdio.start_loading('Check before start observer') servers_clients = {} servers_port = {} servers_memory = {} servers_disk = {} servers_clog_mount = {} - servers_net_inferface = {} + servers_net_interface = {} servers_dirs = {} servers_check_dirs = {} START_NEED_MEMORY = 3 << 30 global_generate_config = generate_configs.get('global', {}) - stdio.start_loading('Check before start observer') + stdio.start_loading('Check before {} observer'.format(source_option)) + + parameter_check = True + port_check = True + kernel_check = True + is_running_opt = source_option in ['restart', 'upgrade'] for server in cluster_config.servers: ip = server.ip client = clients[server] @@ -200,6 +233,7 @@ def system_memory_check(): servers_clients[ip] = client server_config = cluster_config.get_server_conf_with_default(server) home_path = server_config['home_path'] + production_mode = server_config.get('production_mode', False) if not precheck: remote_pid_path = '%s/run/observer.pid' % home_path remote_pid = client.execute_command('cat %s' % remote_pid_path).stdout.strip() @@ -207,7 +241,10 @@ def system_memory_check(): if client.execute_command('ls /proc/%s' % remote_pid): stdio.verbose('%s is runnning, skip' % server) wait_2_pass() - continue + work_dir_check = False + port_check = False + parameter_check = False + kernel_check = is_running_opt if work_dir_check: stdio.verbose('%s dir check' % server) @@ -276,77 +313,79 @@ def system_memory_check(): servers_disk[ip] = {} servers_port[ip] = {} servers_clog_mount[ip] = {} - servers_net_inferface[ip] = {} + servers_net_interface[ip] = {} servers_memory[ip] = {'num': 0, 'percentage': 0, 'servers': {}} memory = servers_memory[ip] ports = servers_port[ip] disk = servers_disk[ip] clog_mount = servers_clog_mount[ip] - inferfaces = servers_net_inferface[ip] - stdio.verbose('%s port check' % server) - for key in ['mysql_port', 'rpc_port']: - port = int(server_config[key]) - if port in ports: - critical( - 'port', - err.EC_CONFIG_CONFLICT_PORT.format(server1=server, port=port, server2=ports[port]['server'], key=ports[port]['key']), - [err.SUG_PORT_CONFLICTS.format()] - ) - continue - ports[port] = { - 'server': server, - 'key': key - } - if get_port_socket_inode(client, port): - critical( - 'port', - err.EC_CONFLICT_PORT.format(server=ip, port=port), - [err.SUG_USE_OTHER_PORT.format()] - ) - - memory_limit = 0 - percentage = 0 - if server_config.get('memory_limit'): - memory_limit = parse_size(server_config['memory_limit']) - memory['num'] += memory_limit - elif 'memory_limit_percentage' in server_config: - percentage = int(parse_size(server_config['memory_limit_percentage'])) - memory['percentage'] += percentage - else: - percentage = 80 - memory['percentage'] += percentage - memory['servers'][server] = { - 'num': memory_limit, - 'percentage': percentage, - 'system_memory': parse_size(server_config.get('system_memory', 0)) - } - - data_path = server_config['data_dir'] if server_config.get('data_dir') else os.path.join(server_config['home_path'], 'store') - redo_dir = server_config['redo_dir'] if server_config.get('redo_dir') else data_path - clog_dir = server_config['clog_dir'] if server_config.get('clog_dir') else os.path.join(redo_dir, 'clog') - if not client.execute_command('ls %s/sstable/block_file' % data_path): - disk[data_path] = { - 'need': 90, - 'server': server - } - clog_mount[clog_dir] = { - 'threshold': server_config.get('clog_disk_utilization_threshold', 80) / 100.0, - 'server': server + interfaces = servers_net_interface[ip] + if port_check: + stdio.verbose('%s port check' % server) + for key in ['mysql_port', 'rpc_port']: + port = int(server_config[key]) + if port in ports: + critical( + 'port', + err.EC_CONFIG_CONFLICT_PORT.format(server1=server, port=port, server2=ports[port]['server'], key=ports[port]['key']), + [err.SUG_PORT_CONFLICTS.format()] + ) + continue + ports[port] = { + 'server': server, + 'key': key + } + if get_port_socket_inode(client, port): + critical( + 'port', + err.EC_CONFLICT_PORT.format(server=ip, port=port), + [err.SUG_USE_OTHER_PORT.format()] + ) + + if parameter_check: + memory_limit = 0 + percentage = 0 + if server_config.get('memory_limit'): + memory_limit = parse_size(server_config['memory_limit']) + memory['num'] += memory_limit + elif 'memory_limit_percentage' in server_config: + percentage = int(parse_size(server_config['memory_limit_percentage'])) + memory['percentage'] += percentage + else: + percentage = 80 + memory['percentage'] += percentage + memory['servers'][server] = { + 'num': memory_limit, + 'percentage': percentage, + 'system_memory': parse_size(server_config.get('system_memory', 0)) } - if 'datafile_size' in server_config and server_config['datafile_size']: - disk[data_path]['need'] = server_config['datafile_size'] - elif 'datafile_disk_percentage' in server_config and server_config['datafile_disk_percentage']: - disk[data_path]['need'] = int(server_config['datafile_disk_percentage']) - - devname = server_config.get('devname') - if devname: - if not client.execute_command("grep -e '^ *%s:' /proc/net/dev" % devname): - suggest = err.SUG_NO_SUCH_NET_DEVIC.format(ip=ip) - suggest.auto_fix = 'devname' not in global_generate_config and 'devname' not in server_generate_config - critical('net', err.EC_NO_SUCH_NET_DEVICE.format(server=server, devname=devname), suggests=[suggest]) - if devname not in inferfaces: - inferfaces[devname] = [] - inferfaces[devname].append(ip) + + data_path = server_config['data_dir'] if server_config.get('data_dir') else os.path.join(server_config['home_path'], 'store') + redo_dir = server_config['redo_dir'] if server_config.get('redo_dir') else data_path + clog_dir = server_config['clog_dir'] if server_config.get('clog_dir') else os.path.join(redo_dir, 'clog') + if not client.execute_command('ls %s/sstable/block_file' % data_path): + disk[data_path] = { + 'need': 90, + 'server': server + } + clog_mount[clog_dir] = { + 'threshold': server_config.get('clog_disk_utilization_threshold', 80) / 100.0, + 'server': server + } + if 'datafile_size' in server_config and server_config['datafile_size']: + disk[data_path]['need'] = server_config['datafile_size'] + elif 'datafile_disk_percentage' in server_config and server_config['datafile_disk_percentage']: + disk[data_path]['need'] = int(server_config['datafile_disk_percentage']) + + devname = server_config.get('devname') + if devname: + if not client.execute_command("grep -e '^ *%s:' /proc/net/dev" % devname): + suggest = err.SUG_NO_SUCH_NET_DEVIC.format(ip=ip) + suggest.auto_fix = 'devname' not in global_generate_config and 'devname' not in server_generate_config + critical('net', err.EC_NO_SUCH_NET_DEVICE.format(server=server, devname=devname), suggests=[suggest]) + if devname not in interfaces: + interfaces[devname] = [] + interfaces[devname].append(ip) for ip in servers_disk: client = servers_clients[ip] @@ -386,6 +425,19 @@ def system_memory_check(): 'recd': lambda x: 4096 * x, 'name': 'nproc' }, + 'core file size': { + 'need': lambda x: 0, + 'recd': lambda x: INF, + 'below_need_error': False, + 'below_recd_error_strict': False, + 'name': 'core' + }, + 'stack size': { + 'need': lambda x: 1024, + 'recd': lambda x: INF, + 'below_recd_error_strict': False, + 'name': 'stack' + }, } ulimits = {} src_data = re.findall('\s?([a-zA-Z\s]+[a-zA-Z])\s+\([a-zA-Z\-,\s]+\)\s+([\d[a-zA-Z]+)', ret.stdout) if ret else [] @@ -397,18 +449,68 @@ def system_memory_check(): continue if not value or not (value.strip().isdigit()): for server in ip_servers: - alert('ulimit', '(%s) failed to get %s' % (ip, key), [err.SUG_UNSUPPORT_OS.format()]) + alert('ulimit', '(%s) failed to get %s' % (ip, key), suggests=[err.SUG_UNSUPPORT_OS.format()]) else: value = int(value) need = ulimits_min[key]['need'](server_num) if need > value: + if (strict_check or production_mode) and ulimits_min[key].get('below_recd_error_strict', True) and value < ulimits_min[key]['recd'](server_num): + need = ulimits_min[key]['recd'](server_num) + need = need if need != INF else 'unlimited' for server in ip_servers: - critical('ulimit', err.EC_ULIMIT_CHECK.format(server=ip, key=key, need=need, now=value), [err.SUG_ULIMIT.format(name=ulimits_min[key]['name'], value=need, ip=ip)]) + if ulimits_min[key].get('below_need_error', True): + critical('ulimit', err.EC_ULIMIT_CHECK.format(server=ip, key=key, need=need, now=value), [err.SUG_ULIMIT.format(name=ulimits_min[key]['name'], value=need, ip=ip)]) + else: + alert('ulimit', err.EC_ULIMIT_CHECK.format(server=ip, key=key, need=need, now=value), suggests=[err.SUG_ULIMIT.format(name=ulimits_min[key]['name'], value=need, ip=ip)]) else: need = ulimits_min[key]['recd'](server_num) if need > value: + need = need if need != INF else 'unlimited' for server in ip_servers: - alert('ulimit', err.WC_ULIMIT_CHECK.format(server=ip, key=key, need=need, now=value), [err.SUG_ULIMIT.format(name=ulimits_min[key]['name'], value=need, ip=ip)]) + if ulimits_min[key].get('below_recd_error_strict', True): + alert('ulimit', err.WC_ULIMIT_CHECK.format(server=ip, key=key, need=need, now=value), suggests=[err.SUG_ULIMIT.format(name=ulimits_min[key]['name'], value=need, ip=ip)]) + else: + stdio.warn(err.WC_ULIMIT_CHECK.format(server=ip, key=key, need=need, now=value)) + + if kernel_check: + # check kernel params + try: + cmd = 'sysctl -a' + ret = client.execute_command(cmd) + if not ret: + alert_strict('kernel', err.EC_FAILED_TO_GET_PARAM.format(key='kernel parameter ', cmd=cmd), [err.SUG_CONNECT_EXCEPT.format(ip=ip)]) + continue + kernel_params = {} + kernel_param_src = ret.stdout.split('\n') + for kernel in kernel_param_src: + if not kernel: + continue + kernel = kernel.split('=') + kernel_params[kernel[0].strip()] = re.findall(r"[-+]?\d+", kernel[1]) + + for kernel_param in kernel_check_items: + check_item = kernel_param['check_item'] + if check_item not in kernel_params: + continue + values = kernel_params[check_item] + needs = kernel_param['need'] + recommends = kernel_param['recommend'] + for i in range(len(values)): + # This case is not handling the value of 'default'. Additional handling is required for 'default' in the future. + item_value = int(values[i]) + need = needs[i] if isinstance(needs, tuple) else needs + recommend = recommends[i] if isinstance(recommends, tuple) else recommends + if isinstance(need, list): + if item_value < need[0] or item_value > need[1]: + suggest = [err.SUG_SYSCTL.format(var=check_item, value=' '.join(str(i) for i in recommend) if isinstance(recommend, list) else recommend, ip=ip)] + need = 'within {}'.format(needs) if needs[-1] != INF else 'greater than {}'.format(needs[0]) + now = '[{}]'.format(', '.join(values)) if len(values) > 1 else item_value + alert_strict(check_item, err.EC_PARAM_NOT_IN_NEED.format(ip=ip, check_item=check_item, need=need, now=now, recommend=recommends), suggest) + break + elif item_value != need: + alert_strict(check_item, err.EC_PARAM_NOT_IN_NEED.format(ip=ip, check_item=check_item, need=needs, recommend=recommend, now=item_value), [err.SUG_SYSCTL.format(var=check_item, value=recommend, ip=ip)]) + except: + stdio.exception('') # memory ret = client.execute_command('cat /proc/meminfo') @@ -427,7 +529,7 @@ def system_memory_check(): if k in memory_key_map: key = memory_key_map[k] server_memory_stats[key] = parse_size(str(v)) - + server_memory_stat = servers_memory[ip] min_start_need = server_num * START_NEED_MEMORY total_use = server_memory_stat['percentage'] * server_memory_stats['total'] / 100 + server_memory_stat['num'] @@ -474,7 +576,7 @@ def system_memory_check(): if len(p) > len(kp): kp = p disk[kp]['threshold'] = min(disk[kp]['threshold'], servers_clog_mount[ip][path]['threshold']) - + for p in disk: total = disk[p]['total'] avail = disk[p]['avail'] @@ -510,8 +612,8 @@ def system_memory_check(): critical('disk', err.EC_OBSERVER_NOT_ENOUGH_DISK_4_CLOG.format(ip=ip, path=p), [suggest] + suggests) if success: - for ip in servers_net_inferface: - if servers_net_inferface[ip].get(None): + for ip in servers_net_interface: + if servers_net_interface[ip].get(None): devinfo = client.execute_command('cat /proc/net/dev').stdout interfaces = [] for interface in re.findall('\n\s+(\w+):', devinfo): @@ -520,17 +622,17 @@ def system_memory_check(): if not interfaces: interfaces = ['lo'] if len(interfaces) > 1: - servers = ','.join(str(server) for server in servers_net_inferface[ip][None]) + servers = ','.join(str(server) for server in servers_net_interface[ip][None]) suggest = err.SUG_NO_SUCH_NET_DEVIC.format(ip=ip) for server in ip_servers: critical('net', err.EC_OBSERVER_MULTI_NET_DEVICE.format(ip=ip, server=servers), [suggest]) else: - servers_net_inferface[ip][interfaces[0]] = servers_net_inferface[ip][None] - del servers_net_inferface[ip][None] + servers_net_interface[ip][interfaces[0]] = servers_net_interface[ip][None] + del servers_net_interface[ip][None] if success: - for ip in servers_net_inferface: + for ip in servers_net_interface: client = servers_clients[ip] - for devname in servers_net_inferface[ip]: + for devname in servers_net_interface[ip]: if client.is_localhost() and devname != 'lo' or (not client.is_localhost() and devname == 'lo'): suggest = err.SUG_NO_SUCH_NET_DEVIC.format(ip=ip) suggest.auto_fix = client.is_localhost() and 'devname' not in global_generate_config and 'devname' not in server_generate_config diff --git a/plugins/oceanbase/4.0.0.0/start_check.py b/plugins/oceanbase/4.0.0.0/start_check.py index e9ece5f..a8a73b4 100644 --- a/plugins/oceanbase/4.0.0.0/start_check.py +++ b/plugins/oceanbase/4.0.0.0/start_check.py @@ -31,7 +31,7 @@ stdio = None success = True - +production_mode = False def get_port_socket_inode(client, port): port = hex(port)[2:].zfill(4).upper() @@ -76,7 +76,7 @@ def time_delta(client): def get_mount_path(disk, _path): _mount_path = '/' for p in disk: - if p in _path: + if p in _path and _path.startswith(p): if len(p) > len(_mount_path): _mount_path = p return _mount_path @@ -133,7 +133,7 @@ def get_disk_info(all_paths, client, stdio): return disk_info -def start_check(plugin_context, init_check_status=False, strict_check=False, work_dir_check=False, work_dir_empty_check=True, generate_configs={}, precheck=False, *args, **kwargs): +def start_check(plugin_context, init_check_status=False, strict_check=False, work_dir_check=False, work_dir_empty_check=True, generate_configs={}, precheck=False, source_option='start', *args, **kwargs): def check_pass(item): status = check_status[server] if status[item].status == err.CheckStatus.WAIT: @@ -153,9 +153,19 @@ def alert(item, error, suggests=[]): if strict_check: success = False check_fail(item, error, suggests) - stdio.error(error) + print_with_suggests(error, suggests) else: stdio.warn(error) + + def alert_strict(item, error, suggests=[]): + global success + if strict_check or production_mode: + success = False + check_fail(item, error, suggests) + print_with_suggests(error, suggests) + else: + stdio.warn(error) + def error(item, _error, suggests=[]): global success if plugin_context.dev_mode: @@ -163,12 +173,16 @@ def error(item, _error, suggests=[]): else: success = False check_fail(item, _error, suggests) - stdio.error(_error) + print_with_suggests(_error, suggests) + def critical(item, error, suggests=[]): global success success = False check_fail(item, error, suggests) - stdio.error(error) + print_with_suggests(error, suggests) + + def print_with_suggests(error, suggests=[]): + stdio.error('{}, {}'.format(error, suggests[0].msg if suggests else '')) def system_memory_check(): server_memory_config = server_memory_stat['servers'] @@ -189,8 +203,21 @@ def system_memory_check(): success = True check_status = {} cluster_config = plugin_context.cluster_config + INF = float('inf') plugin_context.set_variable('start_check_status', check_status) + kernel_check_items = [ + {'check_item': 'vm.max_map_count', 'need': [327600, 1310720], 'recommend': 655360}, + {'check_item': 'vm.min_free_kbytes', 'need': [32768, 2097152], 'recommend': 2097152}, + {'check_item': 'vm.overcommit_memory', 'need': 0, 'recommend': 0}, + {'check_item': 'fs.file-max', 'need': [6573688, INF], 'recommend': 6573688}, + ] + + kernel_check_status = {} + for kernel_param in kernel_check_items: + check_item = kernel_param['check_item'] + kernel_check_status[check_item] = err.CheckStatus() + for server in cluster_config.servers: check_status[server] = { 'port': err.CheckStatus(), @@ -202,6 +229,7 @@ def system_memory_check(): 'ntp': err.CheckStatus(), 'ocp meta db': err.CheckStatus() } + check_status[server].update(kernel_check_status) if work_dir_check: check_status[server]['dir'] = err.CheckStatus() @@ -215,7 +243,7 @@ def system_memory_check(): servers_memory = {} servers_disk = {} servers_clog_mount = {} - servers_net_inferface = {} + servers_net_interface = {} servers_dirs = {} servers_check_dirs = {} servers_log_disk_size = {} @@ -223,10 +251,15 @@ def system_memory_check(): PRO_MEMORY_MIN = 16 << 30 PRO_POOL_MEM_MIN = 2147483648 START_NEED_MEMORY = 3 << 30 - global_generate_config = generate_configs.get('global', {}) - stdio.start_loading('Check before start observer') + global_generate_config = plugin_context.get_variable('global_generate_config', default=generate_configs.get('global', {})) + plugin_context.set_variable('global_generate_config', global_generate_config) + stdio.start_loading('Check before {} observer'.format(source_option)) need_bootstrap = True + parameter_check = True + port_check = True + kernel_check = True + is_running_opt = source_option in ['restart', 'upgrade'] for server in cluster_config.servers: ip = server.ip client = clients[server] @@ -234,6 +267,7 @@ def system_memory_check(): servers_clients[ip] = client server_config = cluster_config.get_server_conf_with_default(server) home_path = server_config['home_path'] + production_mode = server_config.get('production_mode', False) if not precheck: if need_bootstrap: data_dir = server_config['data_dir'] if server_config.get('data_dir') else '%s/store' % home_path @@ -244,7 +278,10 @@ def system_memory_check(): if remote_pid: if client.execute_command('ls /proc/%s' % remote_pid): stdio.verbose('%s is runnning, skip' % server) - continue + work_dir_check = False + port_check = False + parameter_check = False + kernel_check = is_running_opt if work_dir_check: stdio.verbose('%s dir check' % server) @@ -313,82 +350,84 @@ def system_memory_check(): servers_disk[ip] = {} servers_port[ip] = {} servers_clog_mount[ip] = {} - servers_net_inferface[ip] = {} + servers_net_interface[ip] = {} servers_memory[ip] = {'num': 0, 'percentage': 0, 'servers': {}} memory = servers_memory[ip] ports = servers_port[ip] disk = servers_disk[ip] clog_mount = servers_clog_mount[ip] - inferfaces = servers_net_inferface[ip] - stdio.verbose('%s port check' % server) - for key in ['mysql_port', 'rpc_port']: - port = int(server_config[key]) - if port in ports: - critical( - 'port', - err.EC_CONFIG_CONFLICT_PORT.format(server1=server, port=port, server2=ports[port]['server'], key=ports[port]['key']), - [err.SUG_PORT_CONFLICTS.format()] - ) - continue - ports[port] = { - 'server': server, - 'key': key + interfaces = servers_net_interface[ip] + if port_check: + stdio.verbose('%s port check' % server) + for key in ['mysql_port', 'rpc_port']: + port = int(server_config[key]) + if port in ports: + critical( + 'port', + err.EC_CONFIG_CONFLICT_PORT.format(server1=server, port=port, server2=ports[port]['server'], key=ports[port]['key']), + [err.SUG_PORT_CONFLICTS.format()] + ) + continue + ports[port] = { + 'server': server, + 'key': key + } + if get_port_socket_inode(client, port): + critical('port', err.EC_CONFLICT_PORT.format(server=ip, port=port), [err.SUG_USE_OTHER_PORT.format()]) + + if parameter_check: + servers_min_pool_memory[server] = __min_full_resource_pool_memory = server_config.get('__min_full_resource_pool_memory') + if production_mode and __min_full_resource_pool_memory < PRO_POOL_MEM_MIN: + error('mem', err.EC_OBSERVER_PRODUCTION_MODE_LIMIT.format(server=server, key="__min_full_resource_pool_memory", limit=PRO_POOL_MEM_MIN), [err.SUB_SET_NO_PRODUCTION_MODE.format()]) + + memory_limit = 0 + percentage = 0 + if server_config.get('memory_limit'): + memory_limit = parse_size(server_config['memory_limit']) + if production_mode and memory_limit < PRO_MEMORY_MIN: + error('mem', err.EC_OBSERVER_PRODUCTION_MODE_LIMIT.format(server=server, key='memory_limit', limit=format_size(PRO_MEMORY_MIN)), [err.SUB_SET_NO_PRODUCTION_MODE.format()]) + memory['num'] += memory_limit + elif 'memory_limit_percentage' in server_config: + percentage = int(parse_size(server_config['memory_limit_percentage'])) + memory['percentage'] += percentage + else: + percentage = 80 + memory['percentage'] += percentage + memory['servers'][server] = { + 'num': memory_limit, + 'percentage': percentage, + 'system_memory': parse_size(server_config.get('system_memory', 0)) } - if get_port_socket_inode(client, port): - critical('port', err.EC_CONFLICT_PORT.format(server=ip, port=port), [err.SUG_USE_OTHER_PORT.format()]) - - servers_min_pool_memory[server] = __min_full_resource_pool_memory = server_config.get('__min_full_resource_pool_memory') - if server_config.get('production_mode') and __min_full_resource_pool_memory < PRO_POOL_MEM_MIN: - error('mem', err.EC_OBSERVER_PRODUCTION_MODE_LIMIT.format(server=server, key="__min_full_resource_pool_memory", limit=PRO_POOL_MEM_MIN), [err.SUB_SET_NO_PRODUCTION_MODE.format()]) - - memory_limit = 0 - percentage = 0 - if server_config.get('memory_limit'): - memory_limit = parse_size(server_config['memory_limit']) - if server_config.get('production_mode') and memory_limit < PRO_MEMORY_MIN: - error('mem', err.EC_OBSERVER_PRODUCTION_MODE_LIMIT.format(server=server, key='memory_limit', limit=format_size(PRO_MEMORY_MIN)), [err.SUB_SET_NO_PRODUCTION_MODE.format()]) - memory['num'] += memory_limit - elif 'memory_limit_percentage' in server_config: - percentage = int(parse_size(server_config['memory_limit_percentage'])) - memory['percentage'] += percentage - else: - percentage = 80 - memory['percentage'] += percentage - memory['servers'][server] = { - 'num': memory_limit, - 'percentage': percentage, - 'system_memory': parse_size(server_config.get('system_memory', 0)) - } - data_path = server_config['data_dir'] if server_config.get('data_dir') else os.path.join(server_config['home_path'], 'store') - redo_dir = server_config['redo_dir'] if server_config.get('redo_dir') else data_path - clog_dir = server_config['clog_dir'] if server_config.get('clog_dir') else os.path.join(redo_dir, 'clog') - if not client.execute_command('ls %s/sstable/block_file' % data_path): - disk[data_path] = {'server': server} - clog_mount[clog_dir] = {'server': server} - if 'datafile_size' in server_config and server_config['datafile_size'] and parse_size(server_config['datafile_size']): - # if need is string, it means use datafile_size - disk[data_path]['need'] = server_config['datafile_size'] - elif 'datafile_disk_percentage' in server_config and server_config['datafile_disk_percentage']: - # if need is integer, it means use datafile_disk_percentage - disk[data_path]['need'] = int(server_config['datafile_disk_percentage']) - - if 'log_disk_size' in server_config and server_config['log_disk_size'] and parse_size(server_config['log_disk_size']): - # if need is string, it means use log_disk_size - clog_mount[clog_dir]['need'] = server_config['log_disk_size'] - elif 'log_disk_percentage' in server_config and server_config['log_disk_percentage']: - # if need is integer, it means use log_disk_percentage - clog_mount[clog_dir]['need'] = int(server_config['log_disk_percentage']) - - devname = server_config.get('devname') - if devname: - if not client.execute_command("grep -e '^ *%s:' /proc/net/dev" % devname): - suggest = err.SUG_NO_SUCH_NET_DEVIC.format(ip=ip) - suggest.auto_fix = 'devname' not in global_generate_config and 'devname' not in server_generate_config - critical('net', err.EC_NO_SUCH_NET_DEVICE.format(server=server, devname=devname), suggests=[suggest]) - if devname not in inferfaces: - inferfaces[devname] = [] - inferfaces[devname].append(ip) + data_path = server_config['data_dir'] if server_config.get('data_dir') else os.path.join(server_config['home_path'], 'store') + redo_dir = server_config['redo_dir'] if server_config.get('redo_dir') else data_path + clog_dir = server_config['clog_dir'] if server_config.get('clog_dir') else os.path.join(redo_dir, 'clog') + if not client.execute_command('ls %s/sstable/block_file' % data_path): + disk[data_path] = {'server': server} + clog_mount[clog_dir] = {'server': server} + if 'datafile_size' in server_config and server_config['datafile_size'] and parse_size(server_config['datafile_size']): + # if need is string, it means use datafile_size + disk[data_path]['need'] = server_config['datafile_size'] + elif 'datafile_disk_percentage' in server_config and server_config['datafile_disk_percentage']: + # if need is integer, it means use datafile_disk_percentage + disk[data_path]['need'] = int(server_config['datafile_disk_percentage']) + + if 'log_disk_size' in server_config and server_config['log_disk_size'] and parse_size(server_config['log_disk_size']): + # if need is string, it means use log_disk_size + clog_mount[clog_dir]['need'] = server_config['log_disk_size'] + elif 'log_disk_percentage' in server_config and server_config['log_disk_percentage']: + # if need is integer, it means use log_disk_percentage + clog_mount[clog_dir]['need'] = int(server_config['log_disk_percentage']) + + devname = server_config.get('devname') + if devname: + if not client.execute_command("grep -e '^ *%s:' /proc/net/dev" % devname): + suggest = err.SUG_NO_SUCH_NET_DEVIC.format(ip=ip) + suggest.auto_fix = 'devname' not in global_generate_config and 'devname' not in server_generate_config + critical('net', err.EC_NO_SUCH_NET_DEVICE.format(server=server, devname=devname), suggests=[suggest]) + if devname not in interfaces: + interfaces[devname] = [] + interfaces[devname].append(ip) ip_server_memory_info = {} @@ -425,10 +464,23 @@ def system_memory_check(): 'name': 'nofile' }, 'max user processes': { - 'need': lambda x: 4096, - 'recd': lambda x: 4096 * x, + 'need': lambda x: 120000, + 'recd': lambda x: 655350, 'name': 'nproc' }, + 'core file size': { + 'need': lambda x: 0, + 'recd': lambda x: INF, + 'below_need_error': False, + 'below_recd_error_strict': False, + 'name': 'core' + }, + 'stack size': { + 'need': lambda x: 1024, + 'recd': lambda x: INF, + 'below_recd_error_strict': False, + 'name': 'stack' + }, } ulimits = {} src_data = re.findall('\s?([a-zA-Z\s]+[a-zA-Z])\s+\([a-zA-Z\-,\s]+\)\s+([\d[a-zA-Z]+)', ret.stdout) if ret else [] @@ -440,19 +492,68 @@ def system_memory_check(): continue if not value or not (value.strip().isdigit()): for server in ip_servers: - alert('ulimit', '(%s) failed to get %s' % (ip, key), [err.SUG_UNSUPPORT_OS.format()]) + alert('ulimit', '(%s) failed to get %s' % (ip, key), suggests=[err.SUG_UNSUPPORT_OS.format()]) else: value = int(value) need = ulimits_min[key]['need'](server_num) if need > value: + if (strict_check or production_mode) and ulimits_min[key].get('below_recd_error_strict', True) and value < ulimits_min[key]['recd'](server_num): + need = ulimits_min[key]['recd'](server_num) + need = need if need != INF else 'unlimited' for server in ip_servers: - critical('ulimit', err.EC_ULIMIT_CHECK.format(server=ip, key=key, need=need, now=value), [err.SUG_ULIMIT.format(name=ulimits_min[key]['name'], value=need, ip=ip)]) + if ulimits_min[key].get('below_need_error', True): + critical('ulimit', err.EC_ULIMIT_CHECK.format(server=ip, key=key, need=need, now=value), [err.SUG_ULIMIT.format(name=ulimits_min[key]['name'], value=need, ip=ip)]) + else: + alert('ulimit', err.EC_ULIMIT_CHECK.format(server=ip, key=key, need=need, now=value), suggests=[err.SUG_ULIMIT.format(name=ulimits_min[key]['name'], value=need, ip=ip)]) else: need = ulimits_min[key]['recd'](server_num) if need > value: + need = need if need != INF else 'unlimited' for server in ip_servers: - alert('ulimit', err.WC_ULIMIT_CHECK.format(server=ip, key=key, need=need, now=value), [err.SUG_ULIMIT.format(name=ulimits_min[key]['name'], value=need, ip=ip)]) + if ulimits_min[key].get('below_recd_error_strict', True): + alert('ulimit', err.WC_ULIMIT_CHECK.format(server=ip, key=key, need=need, now=value), suggests=[err.SUG_ULIMIT.format(name=ulimits_min[key]['name'], value=need, ip=ip)]) + else: + stdio.warn(err.WC_ULIMIT_CHECK.format(server=ip, key=key, need=need, now=value)) + + if kernel_check: + # check kernel params + try: + cmd = 'sysctl -a' + ret = client.execute_command(cmd) + if not ret: + alert_strict('kernel', err.EC_FAILED_TO_GET_PARAM.format(key='kernel parameter ', cmd=cmd), [err.SUG_CONNECT_EXCEPT.format(ip=ip)]) + continue + kernel_params = {} + kernel_param_src = ret.stdout.split('\n') + for kernel in kernel_param_src: + if not kernel: + continue + kernel = kernel.split('=') + kernel_params[kernel[0].strip()] = re.findall(r"[-+]?\d+", kernel[1]) + for kernel_param in kernel_check_items: + check_item = kernel_param['check_item'] + if check_item not in kernel_params: + continue + values = kernel_params[check_item] + needs = kernel_param['need'] + recommends = kernel_param['recommend'] + for i in range(len(values)): + # This case is not handling the value of 'default'. Additional handling is required for 'default' in the future. + item_value = int(values[i]) + need = needs[i] if isinstance(needs, tuple) else needs + recommend = recommends[i] if isinstance(recommends, tuple) else recommends + if isinstance(need, list): + if item_value < need[0] or item_value > need[1]: + suggest = [err.SUG_SYSCTL.format(var=check_item, value=' '.join(str(i) for i in recommend) if isinstance(recommend, list) else recommend, ip=ip)] + need = 'within {}'.format(needs) if needs[-1] != INF else 'greater than {}'.format(needs[0]) + now = '[{}]'.format(', '.join(values)) if len(values) > 1 else item_value + alert_strict(check_item, err.EC_PARAM_NOT_IN_NEED.format(ip=ip, check_item=check_item, need=need, now=now, recommend=recommends), suggest) + break + elif item_value != need: + alert_strict(check_item, err.EC_PARAM_NOT_IN_NEED.format(ip=ip, check_item=check_item, need=needs, recommend=recommend, now=item_value), [err.SUG_SYSCTL.format(var=check_item, value=recommend, ip=ip)]) + except: + stdio.exception('') # memory ret = client.execute_command('cat /proc/meminfo') @@ -636,8 +737,8 @@ def system_memory_check(): if success: - for ip in servers_net_inferface: - if servers_net_inferface[ip].get(None): + for ip in servers_net_interface: + if servers_net_interface[ip].get(None): devinfo = client.execute_command('cat /proc/net/dev').stdout interfaces = [] for interface in re.findall('\n\s+(\w+):', devinfo): @@ -646,18 +747,18 @@ def system_memory_check(): if not interfaces: interfaces = ['lo'] if len(interfaces) > 1: - servers = ','.join(str(server) for server in servers_net_inferface[ip][None]) + servers = ','.join(str(server) for server in servers_net_interface[ip][None]) suggest = err.SUG_NO_SUCH_NET_DEVIC.format(ip=ip) for server in ip_servers: critical('net', err.EC_OBSERVER_MULTI_NET_DEVICE.format(ip=ip, server=servers), [suggest]) else: - servers_net_inferface[ip][interfaces[0]] = servers_net_inferface[ip][None] - del servers_net_inferface[ip][None] + servers_net_interface[ip][interfaces[0]] = servers_net_interface[ip][None] + del servers_net_interface[ip][None] if success: - for ip in servers_net_inferface: + for ip in servers_net_interface: client = servers_clients[ip] - for devname in servers_net_inferface[ip]: + for devname in servers_net_interface[ip]: if client.is_localhost() and devname != 'lo' or (not client.is_localhost() and devname == 'lo'): suggest = err.SUG_NO_SUCH_NET_DEVIC.format(ip=ip) suggest.auto_fix = client.is_localhost() and 'devname' not in global_generate_config and 'devname' not in server_generate_config diff --git a/plugins/oceanbase/4.2.0.0/generate_config.py b/plugins/oceanbase/4.2.0.0/generate_config.py index 87f3f94..11531b7 100644 --- a/plugins/oceanbase/4.2.0.0/generate_config.py +++ b/plugins/oceanbase/4.2.0.0/generate_config.py @@ -83,7 +83,7 @@ def generate_config(plugin_context, generate_config_mini=False, generate_check=T generate_keys = [] if not only_generate_password: generate_keys += [ - 'memory_limit', 'datafile_size', 'log_disk_size', 'devname', 'system_memory', 'cpu_count', 'production_mode', + 'memory_limit', 'datafile_size', 'log_disk_size', 'system_memory', 'cpu_count', 'production_mode', 'syslog_level', 'enable_syslog_recycle', 'enable_syslog_wf', 'max_syslog_file_count', 'cluster_id', 'ocp_meta_tenant_log_disk_size', 'datafile_next', 'datafile_maxsize' ] @@ -156,19 +156,6 @@ def summit_config(): server_config = cluster_config.get_server_conf_with_default(server) user_server_config = cluster_config.get_original_server_conf_with_global(server, format_conf=True) - if user_server_config.get('devname') is None: - if client.is_localhost(): - update_server_conf(server, 'devname', 'lo') - else: - devinfo = client.execute_command('cat /proc/net/dev').stdout - interfaces = re.findall('\n\s+(\w+):', devinfo) - for interface in interfaces: - if interface == 'lo': - continue - if client.execute_command('ping -W 1 -c 1 -I %s %s' % (interface, ip)): - update_server_conf(server, 'devname', interface) - break - dirs = {"home_path": server_config['home_path']} dirs["data_dir"] = server_config['data_dir'] if server_config.get('data_dir') else os.path.join(server_config['home_path'], 'store') dirs["redo_dir"] = server_config['redo_dir'] if server_config.get('redo_dir') else dirs["data_dir"] diff --git a/plugins/oceanbase/4.2.0.0/parameter.yaml b/plugins/oceanbase/4.2.0.0/parameter.yaml index b490fbd..f8f3b86 100644 --- a/plugins/oceanbase/4.2.0.0/parameter.yaml +++ b/plugins/oceanbase/4.2.0.0/parameter.yaml @@ -68,6 +68,14 @@ need_restart: true description_en: name of network adapter description_local: 服务进程绑定的网卡设备名 +- name: local_ip + name_local: 本机ip + type: STRING + min_value: NULL + max_value: NULL + need_restart: true + description_en: local ip address + description_local: 本机ip地址 - name: rpc_port name_local: 内部通信端口 require: true diff --git a/plugins/oceanbase/4.2.0.0/start.py b/plugins/oceanbase/4.2.0.0/start.py index 77b5600..be17f6c 100644 --- a/plugins/oceanbase/4.2.0.0/start.py +++ b/plugins/oceanbase/4.2.0.0/start.py @@ -29,14 +29,22 @@ from collections import OrderedDict +from tool import NetUtil + def config_url(ocp_config_server, appname, cid): - cfg_url = '%s&Action=ObRootServiceInfo&ObCluster=%s' % (ocp_config_server, appname) - proxy_cfg_url = '%s&Action=GetObProxyConfig&ObRegionGroup=%s' % (ocp_config_server, appname) + if ocp_config_server[-1] == '?': + link_char = '' + elif ocp_config_server.find('?') == -1: + link_char = '?' + else: + link_char = '&' + cfg_url = '%s%sAction=ObRootServiceInfo&ObCluster=%s' % (ocp_config_server, link_char, appname) + proxy_cfg_url = '%s%sAction=GetObProxyConfig&ObRegionGroup=%s' % (ocp_config_server, link_char, appname) # Command that clears the URL content for the cluster - cleanup_config_url_content = '%s&Action=DeleteObRootServiceInfoByClusterName&ClusterName=%s' % (ocp_config_server, appname) + cleanup_config_url_content = '%s%sAction=DeleteObRootServiceInfoByClusterName&ClusterName=%s' % (ocp_config_server, link_char, appname) # Command that register the cluster information to the Config URL - register_to_config_url = '%s&Action=ObRootServiceRegister&ObCluster=%s&ObClusterId=%s' % (ocp_config_server, appname, cid) + register_to_config_url = '%s%sAction=ObRootServiceRegister&ObCluster=%s&ObClusterId=%s' % (ocp_config_server, link_char, appname, cid) return cfg_url, cleanup_config_url_content, register_to_config_url @@ -100,11 +108,21 @@ def start(plugin_context, *args, **kwargs): try: cfg_url = init_config_server(obconfig_url, appname, cluster_id, getattr(options, 'force_delete', False), stdio) if not cfg_url: - stdio.error(EC_OBSERVER_FAILED_TO_REGISTER_WITH_DETAILS.format(appname, obconfig_url)) - return + stdio.warn(EC_OBSERVER_FAILED_TO_REGISTER_WITH_DETAILS.format(appname, obconfig_url)) except: - stdio.exception(EC_OBSERVER_FAILED_TO_REGISTER.format()) - return + stdio.warn(EC_OBSERVER_FAILED_TO_REGISTER.format()) + elif 'ob-configserver' in cluster_config.depends and appname: + obc_cluster_config = cluster_config.get_depend_config('ob-configserver') + vip_address = obc_cluster_config.get('vip_address') + if vip_address: + obc_ip = vip_address + obc_port = obc_cluster_config.get('vip_port') + else: + server = cluster_config.get_depend_servers('ob-configserver')[0] + client = clients[server] + obc_ip = NetUtil.get_host_ip() if client.is_localhost() else server.ip + obc_port = obc_cluster_config.get('listen_port') + cfg_url = "http://{0}:{1}/services?Action=ObRootServiceInfo&ObCluster={2}".format(obc_ip, obc_port, appname) stdio.start_loading('Start observer') for server in cluster_config.original_servers: @@ -121,6 +139,9 @@ def start(plugin_context, *args, **kwargs): if not server_config.get('data_dir'): server_config['data_dir'] = '%s/store' % home_path + + if not server_config.get('local_ip') and not server_config.get('devname'): + server_config['local_ip'] = server.ip if client.execute_command('ls %s/clog/tenant_1/' % server_config['data_dir']).stdout.strip(): need_bootstrap = False @@ -147,10 +168,12 @@ def start(plugin_context, *args, **kwargs): 'appname': '-n', 'cluster_id': '-c', 'data_dir': '-d', + 'devname': '-i', 'syslog_level': '-l', 'ipv6': '-6', 'mode': '-m', - 'scn': '-f' + 'scn': '-f', + 'local_ip': '-I' }) not_cmd_opt = [ 'home_path', 'obconfig_url', 'root_password', 'proxyro_password', @@ -171,7 +194,6 @@ def start(plugin_context, *args, **kwargs): if key in server_config: value = get_value(key) cmd.append('%s %s' % (not_opt_str[key], value)) - cmd.append('-I %s' % server.ip) cmd.append('-o %s' % ','.join(opt_str)) else: cmd.append('-p %s' % server_config['mysql_port']) diff --git a/plugins/oceanbase/4.2.0.0/start_check.py b/plugins/oceanbase/4.2.0.0/start_check.py index 324d641..a674d04 100644 --- a/plugins/oceanbase/4.2.0.0/start_check.py +++ b/plugins/oceanbase/4.2.0.0/start_check.py @@ -31,7 +31,7 @@ stdio = None success = True - +production_mode = False def get_port_socket_inode(client, port): port = hex(port)[2:].zfill(4).upper() @@ -76,7 +76,7 @@ def time_delta(client): def get_mount_path(disk, _path): _mount_path = '/' for p in disk: - if p in _path: + if p in _path and _path.startswith(p): if len(p) > len(_mount_path): _mount_path = p return _mount_path @@ -133,7 +133,7 @@ def get_disk_info(all_paths, client, stdio): return disk_info -def start_check(plugin_context, init_check_status=False, strict_check=False, work_dir_check=False, work_dir_empty_check=True, generate_configs={}, precheck=False, *args, **kwargs): +def start_check(plugin_context, init_check_status=False, strict_check=False, work_dir_check=False, work_dir_empty_check=True, generate_configs={}, precheck=False, source_option='start', *args, **kwargs): def check_pass(item): status = check_status[server] if status[item].status == err.CheckStatus.WAIT: @@ -153,9 +153,19 @@ def alert(item, error, suggests=[]): if strict_check: success = False check_fail(item, error, suggests) - stdio.error(error) + print_with_suggests(error, suggests) + else: + stdio.warn(error) + + def alert_strict(item, error, suggests=[]): + global success + if strict_check or production_mode: + success = False + check_fail(item, error, suggests) + print_with_suggests(error, suggests) else: stdio.warn(error) + def error(item, _error, suggests=[]): global success if plugin_context.dev_mode: @@ -163,12 +173,16 @@ def error(item, _error, suggests=[]): else: success = False check_fail(item, _error, suggests) - stdio.error(_error) + print_with_suggests(_error, suggests) + def critical(item, error, suggests=[]): global success success = False check_fail(item, error, suggests) - stdio.error(error) + print_with_suggests(error, suggests) + + def print_with_suggests(error, suggests=[]): + stdio.error('{}, {}'.format(error, suggests[0].msg if suggests else '')) def system_memory_check(): server_memory_config = server_memory_stat['servers'] @@ -189,8 +203,21 @@ def system_memory_check(): success = True check_status = {} cluster_config = plugin_context.cluster_config + INF = float('inf') plugin_context.set_variable('start_check_status', check_status) + kernel_check_items = [ + {'check_item': 'vm.max_map_count', 'need': [327600, 1310720], 'recommend': 655360}, + {'check_item': 'vm.min_free_kbytes', 'need': [32768, 2097152], 'recommend': 2097152}, + {'check_item': 'vm.overcommit_memory', 'need': 0, 'recommend': 0}, + {'check_item': 'fs.file-max', 'need': [6573688, INF], 'recommend': 6573688}, + ] + + kernel_check_status = {} + for kernel_param in kernel_check_items: + check_item = kernel_param['check_item'] + kernel_check_status[check_item] = err.CheckStatus() + for server in cluster_config.servers: check_status[server] = { 'port': err.CheckStatus(), @@ -202,9 +229,10 @@ def system_memory_check(): 'ntp': err.CheckStatus(), 'ocp meta db': err.CheckStatus() } + check_status[server].update(kernel_check_status) if work_dir_check: check_status[server]['dir'] = err.CheckStatus() - + if init_check_status: return plugin_context.return_true(start_check_status=check_status) @@ -215,7 +243,7 @@ def system_memory_check(): servers_memory = {} servers_disk = {} servers_clog_mount = {} - servers_net_inferface = {} + servers_net_interface = {} servers_dirs = {} servers_check_dirs = {} servers_log_disk_size = {} @@ -223,10 +251,15 @@ def system_memory_check(): PRO_MEMORY_MIN = 16 << 30 PRO_POOL_MEM_MIN = 2147483648 START_NEED_MEMORY = 3 << 30 - global_generate_config = generate_configs.get('global', {}) - stdio.start_loading('Check before start observer') + global_generate_config = plugin_context.get_variable('global_generate_config', default=generate_configs.get('global', {})) + plugin_context.set_variable('global_generate_config', global_generate_config) + stdio.start_loading('Check before {} observer'.format(source_option)) need_bootstrap = True + parameter_check = True + port_check = True + kernel_check = True + is_running_opt = source_option in ['restart', 'upgrade'] for server in cluster_config.servers: ip = server.ip client = clients[server] @@ -234,6 +267,7 @@ def system_memory_check(): servers_clients[ip] = client server_config = cluster_config.get_server_conf_with_default(server) home_path = server_config['home_path'] + production_mode = server_config.get('production_mode', False) if not precheck: if need_bootstrap: data_dir = server_config['data_dir'] if server_config.get('data_dir') else '%s/store' % home_path @@ -244,7 +278,10 @@ def system_memory_check(): if remote_pid: if client.execute_command('ls /proc/%s' % remote_pid): stdio.verbose('%s is runnning, skip' % server) - continue + work_dir_check = False + port_check = False + parameter_check = False + kernel_check = is_running_opt if work_dir_check: stdio.verbose('%s dir check' % server) @@ -313,83 +350,84 @@ def system_memory_check(): servers_disk[ip] = {} servers_port[ip] = {} servers_clog_mount[ip] = {} - servers_net_inferface[ip] = {} + servers_net_interface[ip] = {} servers_memory[ip] = {'num': 0, 'percentage': 0, 'servers': {}} memory = servers_memory[ip] ports = servers_port[ip] disk = servers_disk[ip] clog_mount = servers_clog_mount[ip] - inferfaces = servers_net_inferface[ip] - stdio.verbose('%s port check' % server) - for key in ['mysql_port', 'rpc_port']: - port = int(server_config[key]) - if port in ports: - critical( - 'port', - err.EC_CONFIG_CONFLICT_PORT.format(server1=server, port=port, server2=ports[port]['server'], key=ports[port]['key']), - [err.SUG_PORT_CONFLICTS.format()] - ) - continue - ports[port] = { - 'server': server, - 'key': key + interfaces = servers_net_interface[ip] + if port_check: + stdio.verbose('%s port check' % server) + for key in ['mysql_port', 'rpc_port']: + port = int(server_config[key]) + if port in ports: + critical( + 'port', + err.EC_CONFIG_CONFLICT_PORT.format(server1=server, port=port, server2=ports[port]['server'], key=ports[port]['key']), + [err.SUG_PORT_CONFLICTS.format()] + ) + continue + ports[port] = { + 'server': server, + 'key': key + } + if get_port_socket_inode(client, port): + critical('port', err.EC_CONFLICT_PORT.format(server=ip, port=port), [err.SUG_USE_OTHER_PORT.format()]) + + if parameter_check: + servers_min_pool_memory[server] = __min_full_resource_pool_memory = server_config.get('__min_full_resource_pool_memory') + if production_mode and __min_full_resource_pool_memory < PRO_POOL_MEM_MIN: + error('mem', err.EC_OBSERVER_PRODUCTION_MODE_LIMIT.format(server=server, key="__min_full_resource_pool_memory", limit=PRO_POOL_MEM_MIN), [err.SUB_SET_NO_PRODUCTION_MODE.format()]) + + memory_limit = 0 + percentage = 0 + if server_config.get('memory_limit'): + memory_limit = parse_size(server_config['memory_limit']) + if production_mode and memory_limit < PRO_MEMORY_MIN: + error('mem', err.EC_OBSERVER_PRODUCTION_MODE_LIMIT.format(server=server, key='memory_limit', limit=format_size(PRO_MEMORY_MIN)), [err.SUB_SET_NO_PRODUCTION_MODE.format()]) + memory['num'] += memory_limit + elif 'memory_limit_percentage' in server_config: + percentage = int(parse_size(server_config['memory_limit_percentage'])) + memory['percentage'] += percentage + else: + percentage = 80 + memory['percentage'] += percentage + memory['servers'][server] = { + 'num': memory_limit, + 'percentage': percentage, + 'system_memory': parse_size(server_config.get('system_memory', 0)) } - if get_port_socket_inode(client, port): - critical('port', err.EC_CONFLICT_PORT.format(server=ip, port=port), [err.SUG_USE_OTHER_PORT.format()]) - - servers_min_pool_memory[server] = __min_full_resource_pool_memory = server_config.get('__min_full_resource_pool_memory') - if server_config.get('production_mode') and __min_full_resource_pool_memory < PRO_POOL_MEM_MIN: - error('mem', err.EC_OBSERVER_PRODUCTION_MODE_LIMIT.format(server=server, key="__min_full_resource_pool_memory", limit=PRO_POOL_MEM_MIN), [err.SUB_SET_NO_PRODUCTION_MODE.format()]) - - memory_limit = 0 - percentage = 0 - if server_config.get('memory_limit'): - memory_limit = parse_size(server_config['memory_limit']) - if server_config.get('production_mode') and memory_limit < PRO_MEMORY_MIN: - error('mem', err.EC_OBSERVER_PRODUCTION_MODE_LIMIT.format(server=server, key='memory_limit', limit=format_size(PRO_MEMORY_MIN)), [err.SUB_SET_NO_PRODUCTION_MODE.format()]) - memory['num'] += memory_limit - elif 'memory_limit_percentage' in server_config: - percentage = int(parse_size(server_config['memory_limit_percentage'])) - memory['percentage'] += percentage - else: - percentage = 80 - memory['percentage'] += percentage - memory['servers'][server] = { - 'num': memory_limit, - 'percentage': percentage, - 'system_memory': parse_size(server_config.get('system_memory', 0)) - } - - data_path = server_config['data_dir'] if server_config.get('data_dir') else os.path.join(server_config['home_path'], 'store') - redo_dir = server_config['redo_dir'] if server_config.get('redo_dir') else data_path - clog_dir = server_config['clog_dir'] if server_config.get('clog_dir') else os.path.join(redo_dir, 'clog') - if not client.execute_command('ls %s/sstable/block_file' % data_path): - disk[data_path] = {'server': server} - clog_mount[clog_dir] = {'server': server} - if 'datafile_size' in server_config and server_config['datafile_size'] and parse_size(server_config['datafile_size']): - # if need is string, it means use datafile_size - disk[data_path]['need'] = server_config['datafile_size'] - elif 'datafile_disk_percentage' in server_config and server_config['datafile_disk_percentage']: - # if need is integer, it means use datafile_disk_percentage - disk[data_path]['need'] = int(server_config['datafile_disk_percentage']) - - if 'log_disk_size' in server_config and server_config['log_disk_size'] and parse_size(server_config['log_disk_size']): - # if need is string, it means use log_disk_size - clog_mount[clog_dir]['need'] = server_config['log_disk_size'] - elif 'log_disk_percentage' in server_config and server_config['log_disk_percentage']: - # if need is integer, it means use log_disk_percentage - clog_mount[clog_dir]['need'] = int(server_config['log_disk_percentage']) - - devname = server_config.get('devname') - if devname: - if not client.execute_command("grep -e '^ *%s:' /proc/net/dev" % devname): - suggest = err.SUG_NO_SUCH_NET_DEVIC.format(ip=ip) - suggest.auto_fix = 'devname' not in global_generate_config and 'devname' not in server_generate_config - critical('net', err.EC_NO_SUCH_NET_DEVICE.format(server=server, devname=devname), suggests=[suggest]) - if devname not in inferfaces: - inferfaces[devname] = [] - inferfaces[devname].append(ip) + data_path = server_config['data_dir'] if server_config.get('data_dir') else os.path.join(server_config['home_path'], 'store') + redo_dir = server_config['redo_dir'] if server_config.get('redo_dir') else data_path + clog_dir = server_config['clog_dir'] if server_config.get('clog_dir') else os.path.join(redo_dir, 'clog') + if not client.execute_command('ls %s/sstable/block_file' % data_path): + disk[data_path] = {'server': server} + clog_mount[clog_dir] = {'server': server} + if 'datafile_size' in server_config and server_config['datafile_size'] and parse_size(server_config['datafile_size']): + # if need is string, it means use datafile_size + disk[data_path]['need'] = server_config['datafile_size'] + elif 'datafile_disk_percentage' in server_config and server_config['datafile_disk_percentage']: + # if need is integer, it means use datafile_disk_percentage + disk[data_path]['need'] = int(server_config['datafile_disk_percentage']) + + if 'log_disk_size' in server_config and server_config['log_disk_size'] and parse_size(server_config['log_disk_size']): + # if need is string, it means use log_disk_size + clog_mount[clog_dir]['need'] = server_config['log_disk_size'] + elif 'log_disk_percentage' in server_config and server_config['log_disk_percentage']: + # if need is integer, it means use log_disk_percentage + clog_mount[clog_dir]['need'] = int(server_config['log_disk_percentage']) + + devname = server_config.get('devname') + if devname: + if not client.execute_command("grep -e '^ *%s:' /proc/net/dev" % devname): + suggest = err.SUG_NO_SUCH_NET_DEVIC.format(ip=ip) + suggest.auto_fix = 'devname' not in global_generate_config and 'devname' not in server_generate_config + critical('net', err.EC_NO_SUCH_NET_DEVICE.format(server=server, devname=devname), suggests=[suggest]) + if devname not in interfaces: + interfaces[devname] = [] + interfaces[devname].append(ip) ip_server_memory_info = {} for ip in servers_disk: @@ -425,10 +463,23 @@ def system_memory_check(): 'name': 'nofile' }, 'max user processes': { - 'need': lambda x: 4096, - 'recd': lambda x: 4096 * x, + 'need': lambda x: 120000, + 'recd': lambda x: 655350, 'name': 'nproc' }, + 'core file size': { + 'need': lambda x: 0, + 'recd': lambda x: INF, + 'below_need_error': False, + 'below_recd_error_strict': False, + 'name': 'core' + }, + 'stack size': { + 'need': lambda x: 1024, + 'recd': lambda x: INF, + 'below_recd_error_strict': False, + 'name': 'stack' + }, } ulimits = {} src_data = re.findall('\s?([a-zA-Z\s]+[a-zA-Z])\s+\([a-zA-Z\-,\s]+\)\s+([\d[a-zA-Z]+)', ret.stdout) if ret else [] @@ -440,19 +491,68 @@ def system_memory_check(): continue if not value or not (value.strip().isdigit()): for server in ip_servers: - alert('ulimit', '(%s) failed to get %s' % (ip, key), [err.SUG_UNSUPPORT_OS.format()]) + alert('ulimit', '(%s) failed to get %s' % (ip, key), suggests=[err.SUG_UNSUPPORT_OS.format()]) else: value = int(value) need = ulimits_min[key]['need'](server_num) if need > value: + if (strict_check or production_mode) and ulimits_min[key].get('below_recd_error_strict', True) and value < ulimits_min[key]['recd'](server_num): + need = ulimits_min[key]['recd'](server_num) + need = need if need != INF else 'unlimited' for server in ip_servers: - critical('ulimit', err.EC_ULIMIT_CHECK.format(server=ip, key=key, need=need, now=value), [err.SUG_ULIMIT.format(name=ulimits_min[key]['name'], value=need, ip=ip)]) + if ulimits_min[key].get('below_need_error', True): + critical('ulimit', err.EC_ULIMIT_CHECK.format(server=ip, key=key, need=need, now=value), [err.SUG_ULIMIT.format(name=ulimits_min[key]['name'], value=need, ip=ip)]) + else: + alert('ulimit', err.EC_ULIMIT_CHECK.format(server=ip, key=key, need=need, now=value), suggests=[err.SUG_ULIMIT.format(name=ulimits_min[key]['name'], value=need, ip=ip)]) else: need = ulimits_min[key]['recd'](server_num) if need > value: + need = need if need != INF else 'unlimited' for server in ip_servers: - alert('ulimit', err.WC_ULIMIT_CHECK.format(server=ip, key=key, need=need, now=value), [err.SUG_ULIMIT.format(name=ulimits_min[key]['name'], value=need, ip=ip)]) + if ulimits_min[key].get('below_recd_error_strict', True): + alert('ulimit', err.WC_ULIMIT_CHECK.format(server=ip, key=key, need=need, now=value), suggests=[err.SUG_ULIMIT.format(name=ulimits_min[key]['name'], value=need, ip=ip)]) + else: + stdio.warn(err.WC_ULIMIT_CHECK.format(server=ip, key=key, need=need, now=value)) + + if kernel_check: + # check kernel params + try: + cmd = 'sysctl -a' + ret = client.execute_command(cmd) + if not ret: + alert_strict('kernel', err.EC_FAILED_TO_GET_PARAM.format(key='kernel parameter ', cmd=cmd), [err.SUG_CONNECT_EXCEPT.format(ip=ip)]) + continue + kernel_params = {} + kernel_param_src = ret.stdout.split('\n') + for kernel in kernel_param_src: + if not kernel: + continue + kernel = kernel.split('=') + kernel_params[kernel[0].strip()] = re.findall(r"[-+]?\d+", kernel[1]) + for kernel_param in kernel_check_items: + check_item = kernel_param['check_item'] + if check_item not in kernel_params: + continue + values = kernel_params[check_item] + needs = kernel_param['need'] + recommends = kernel_param['recommend'] + for i in range(len(values)): + # This case is not handling the value of 'default'. Additional handling is required for 'default' in the future. + item_value = int(values[i]) + need = needs[i] if isinstance(needs, tuple) else needs + recommend = recommends[i] if isinstance(recommends, tuple) else recommends + if isinstance(need, list): + if item_value < need[0] or item_value > need[1]: + suggest = [err.SUG_SYSCTL.format(var=check_item, value=' '.join(str(i) for i in recommend) if isinstance(recommend, list) else recommend, ip=ip)] + need = 'within {}'.format(needs) if needs[-1] != INF else 'greater than {}'.format(needs[0]) + now = '[{}]'.format(', '.join(values)) if len(values) > 1 else item_value + alert_strict(check_item, err.EC_PARAM_NOT_IN_NEED.format(ip=ip, check_item=check_item, need=need, now=now, recommend=recommends), suggest) + break + elif item_value != need: + alert_strict(check_item, err.EC_PARAM_NOT_IN_NEED.format(ip=ip, check_item=check_item, need=needs, recommend=recommend, now=item_value), [err.SUG_SYSCTL.format(var=check_item, value=recommend, ip=ip)]) + except: + stdio.exception('') # memory ret = client.execute_command('cat /proc/meminfo') @@ -634,31 +734,11 @@ def system_memory_check(): suggest.auto_fix = False error('ocp meta db', err.EC_OCP_EXPRESS_META_DB_NOT_ENOUGH_LOG_DISK.format(), [suggest]) - if success: - for ip in servers_net_inferface: - if servers_net_inferface[ip].get(None): - devinfo = client.execute_command('cat /proc/net/dev').stdout - interfaces = [] - for interface in re.findall('\n\s+(\w+):', devinfo): - if interface != 'lo': - interfaces.append(interface) - if not interfaces: - interfaces = ['lo'] - if len(interfaces) > 1: - servers = ','.join(str(server) for server in servers_net_inferface[ip][None]) - suggest = err.SUG_NO_SUCH_NET_DEVIC.format(ip=ip) - for server in ip_servers: - critical('net', err.EC_OBSERVER_MULTI_NET_DEVICE.format(ip=ip, server=servers), [suggest]) - else: - servers_net_inferface[ip][interfaces[0]] = servers_net_inferface[ip][None] - del servers_net_inferface[ip][None] - - if success: - for ip in servers_net_inferface: + for ip in servers_net_interface: client = servers_clients[ip] - for devname in servers_net_inferface[ip]: - if client.is_localhost() and devname != 'lo' or (not client.is_localhost() and devname == 'lo'): + for devname in servers_net_interface[ip]: + if client.is_localhost() and (devname != 'lo' and devname is not None) or (not client.is_localhost() and devname == 'lo'): suggest = err.SUG_NO_SUCH_NET_DEVIC.format(ip=ip) suggest.auto_fix = client.is_localhost() and 'devname' not in global_generate_config and 'devname' not in server_generate_config for server in ip_servers: @@ -667,11 +747,15 @@ def system_memory_check(): for _ip in servers_clients: if ip == _ip: continue - if not client.execute_command('ping -W 1 -c 1 -I %s %s' % (devname, _ip)): + ping_cmd = 'ping -W 1 -c 1 -I %s %s' % (devname, _ip) if devname is not None else 'ping -W 1 -c 1 %s' % _ip + if not client.execute_command(ping_cmd): suggest = err.SUG_NO_SUCH_NET_DEVIC.format(ip=ip) suggest.auto_fix = 'devname' not in global_generate_config and 'devname' not in server_generate_config for server in ip_servers: - critical('net', err.EC_OBSERVER_PING_FAILED.format(ip1=ip, devname=devname, ip2=_ip), [suggest]) + if devname is not None: + critical('net', err.EC_OBSERVER_PING_FAILED.format(ip1=ip, devname=devname, ip2=_ip), [suggest]) + else: + critical('net', err.EC_OBSERVER_PING_FAILED_WITH_NO_DEVNAME.format(ip1=ip, ip2=_ip), [suggest]) break diff --git a/plugins/ocp-server/4.2.1/bootstrap.py b/plugins/ocp-server/4.2.1/bootstrap.py new file mode 100644 index 0000000..3b88250 --- /dev/null +++ b/plugins/ocp-server/4.2.1/bootstrap.py @@ -0,0 +1,25 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + + +from __future__ import absolute_import, division, print_function + + +def bootstrap(plugin_context, *args, **kwargs): + return True diff --git a/plugins/ocp-server/4.2.1/connect.py b/plugins/ocp-server/4.2.1/connect.py new file mode 100644 index 0000000..acfbc7a --- /dev/null +++ b/plugins/ocp-server/4.2.1/connect.py @@ -0,0 +1,152 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + + +from __future__ import absolute_import, division, print_function + +import json +import requests +from requests.auth import HTTPBasicAuth +import time + +import _errno as err + + +class OcpServerCursor(object): + + class Response(object): + + def __init__(self, code, content): + self.code = code + self.content = content + + def __bool__(self): + return self.code == 200 + + def __init__(self, ip, port, username=None, password=None): + self.ip = ip + self.port = port + self.username = username + self.password = password + self.url_prefix = "http://{ip}:{port}/".format(ip=self.ip, port=self.port) + if self.username: + self.auth = HTTPBasicAuth(username=username, password=password) + else: + self.auth = None + + def status(self, stdio=None): + ocp_status_ok = False + now = time.time() + check_wait_time = 300 + count = 0 + while time.time() - now < check_wait_time: + stdio.verbose("query ocp to check...") + count += 1 + resp = self._request('GET', 'api/v2/time', stdio=stdio) + try: + if resp.code == 200 or count >= 10: + ocp_status_ok = True + break + except Exception: + stdio.verbose("ocp still not active") + time.sleep(3) + if ocp_status_ok: + stdio.verbose("check ocp server status ok") + return True + else: + stdio.verbose("OCP is still not working properly, check failed.") + return True + + def info(self, stdio=None): + resp = self._request('GET', 'api/v2/info', stdio=stdio) + if resp.code == 200: + return resp.content + + def task_over_precheck(self, data, stdio=None): + resp = self._request('POST', 'api/v2/ob/clusters/takeOverPreCheck', data=data, stdio=stdio) + if resp.code == 200: + return resp.content + + def compute_host_types(self, data, stdio=None): + resp = self._request('POST', 'api/v2/compute/hostTypes', data=data, stdio=stdio) + if resp.code == 200: + return resp.content + + def profiles_credentials(self, data, stdio=None): + resp = self._request('POST', 'api/v2/profiles/me/credentials', data=data, stdio=stdio) + if resp.code == 200: + return resp.content + + def task_over(self, data, stdio=None): + resp = self._request('POST', 'api/v2/ob/clusters/takeOver', data=data, stdio=stdio) + if resp.code == 200: + return resp.content + + def _request(self, method, api, data=None, retry=5, stdio=None): + url = self.url_prefix + api + headers = {"Content-Type": "application/json"} + try: + if data is not None: + data = json.dumps(data) + stdio.verbose('send http request method: {}, url: {}, data: {}'.format(method, url, data)) + resp = requests.request(method, url, data=data, verify=False, headers=headers, auth=self.auth) + return_code = resp.status_code + content = resp.content + except Exception as e: + if retry: + retry -= 1 + return self._request(method=method, api=api, data=data, retry=retry, stdio=stdio) + stdio.exception("") + return_code = 500 + content = str(e) + if return_code != 200: + stdio.verbose("request ocp-server failed: %s" % content) + try: + content = json.loads(content.decode()) + except: + pass + return self.Response(code=return_code, content=content) + + +def connect(plugin_context, target_server=None, *args, **kwargs): + cluster_config = plugin_context.cluster_config + stdio = plugin_context.stdio + if target_server: + servers = [target_server] + stdio.start_loading('Connect to ocp-server ({})'.format(target_server)) + else: + servers = cluster_config.servers + stdio.start_loading('Connect to ocp-server') + cursors = {} + for server in servers: + config = cluster_config.get_server_conf(server) + username = 'admin' + password = config['admin_password'] + stdio.verbose('connect ocp-server ({}:{} by user {})'.format(server.ip, config['port'], username)) + cursor = OcpServerCursor(ip=server.ip, port=config['port'], username=username, password=password) + if cursor.status(stdio=stdio): + cursors[server] = cursor + if not cursors: + stdio.error(err.EC_FAIL_TO_CONNECT.format(component=cluster_config.name)) + stdio.stop_loading('fail') + return plugin_context.return_false() + + stdio.stop_loading('succeed') + return plugin_context.return_true(connect=cursors, cursor=cursors) + diff --git a/plugins/ocp-server/4.2.1/destroy.py b/plugins/ocp-server/4.2.1/destroy.py new file mode 100644 index 0000000..9e4932d --- /dev/null +++ b/plugins/ocp-server/4.2.1/destroy.py @@ -0,0 +1,59 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + + +from __future__ import absolute_import, division, print_function + +import _errno as err + +global_ret = True + + +def destroy(plugin_context, *args, **kwargs): + def clean(path): + client = clients[server] + ret = client.execute_command('rm -fr %s/*' % path, timeout=-1) + if not ret: + global global_ret + global_ret = False + stdio.warn(err.EC_CLEAN_PATH_FAILED.format(server=server, path=path)) + else: + stdio.verbose('%s:%s cleaned' % (server, path)) + + cluster_config = plugin_context.cluster_config + clients = plugin_context.clients + stdio = plugin_context.stdio + global global_ret + stdio.start_loading('ocp-server work dir cleaning') + for server in cluster_config.servers: + server_config = cluster_config.get_server_conf(server) + stdio.verbose('%s work path cleaning', server) + home_path = server_config['home_path'] + clean(home_path) + + for key in ['log_dir', 'soft_dir']: + path = server_config.get(key) + if path: + clean(path) + if global_ret: + stdio.stop_loading('succeed') + return plugin_context.return_true() + else: + stdio.stop_loading('fail') + return plugin_context.return_false() diff --git a/plugins/ocp-server/4.2.1/display.py b/plugins/ocp-server/4.2.1/display.py new file mode 100644 index 0000000..5733c4e --- /dev/null +++ b/plugins/ocp-server/4.2.1/display.py @@ -0,0 +1,128 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + + +from __future__ import absolute_import, division, print_function + +from tool import NetUtil +from copy import deepcopy + + +def get_missing_required_parameters(parameters): + results = [] + for key in ["jdbc_url", "jdbc_password", "jdbc_username", "cluster_name", "ob_cluster_id", "root_sys_password", + "server_addresses", "agent_username", "agent_password"]: + if parameters.get(key) is None: + results.append(key) + return results + + +def prepare_parameters(cluster_config, stdio): + # depends config + env = {} + depend_observer = False + depend_info = {} + ob_servers_conf = {} + root_servers = [] + for comp in ["oceanbase", "oceanbase-ce"]: + ob_zones = {} + if comp in cluster_config.depends: + depend_observer = True + observer_globals = cluster_config.get_depend_config(comp) + ocp_meta_keys = [ + "ocp_meta_tenant", "ocp_meta_db", "ocp_meta_username", "ocp_meta_password", "appname", "cluster_id", "root_password" + ] + for key in ocp_meta_keys: + value = observer_globals.get(key) + if value is not None: + depend_info[key] = value + ob_servers = cluster_config.get_depend_servers(comp) + for ob_server in ob_servers: + ob_servers_conf[ob_server] = ob_server_conf = cluster_config.get_depend_config(comp, ob_server) + if 'server_ip' not in depend_info: + depend_info['server_ip'] = ob_server.ip + depend_info['mysql_port'] = ob_server_conf['mysql_port'] + zone = ob_server_conf['zone'] + if zone not in ob_zones: + ob_zones[zone] = ob_server + root_servers = ob_zones.values() + break + for comp in ['obproxy', 'obproxy-ce']: + if comp in cluster_config.depends: + obproxy_servers = cluster_config.get_depend_servers(comp) + obproxy_server = obproxy_servers[0] + obproxy_server_config = cluster_config.get_depend_config(comp, obproxy_server) + depend_info['server_ip'] = obproxy_server.ip + depend_info['mysql_port'] = obproxy_server_config['listen_port'] + break + + for server in cluster_config.servers: + server_config = deepcopy(cluster_config.get_server_conf_with_default(server)) + original_server_config = cluster_config.get_original_server_conf(server) + missed_keys = get_missing_required_parameters(original_server_config) + if missed_keys: + if 'jdbc_url' in missed_keys and depend_observer: + server_config['jdbc_url'] = 'jdbc:oceanbase://{}:{}/{}'.format(depend_info['server_ip'], depend_info['mysql_port'], depend_info['ocp_meta_db']) + if 'jdbc_username' in missed_keys and depend_observer: + server_config['jdbc_username'] = "{}@{}".format(depend_info['ocp_meta_username'], + depend_info.get('ocp_meta_tenant', {}).get("tenant_name")) + depends_key_maps = { + "jdbc_password": "ocp_meta_password", + "cluster_name": "appname", + "ob_cluster_id": "cluster_id", + "root_sys_password": "root_password", + "agent_username": "obagent_username", + "agent_password": "obagent_password", + "server_addresses": "server_addresses" + } + for key in depends_key_maps: + if key in missed_keys: + if depend_info.get(depends_key_maps[key]) is not None: + server_config[key] = depend_info[depends_key_maps[key]] + env[server] = server_config + return env + + +def display(plugin_context, cursor, *args, **kwargs): + cluster_config = plugin_context.cluster_config + stdio = plugin_context.stdio + servers = cluster_config.servers + results = [] + start_env = prepare_parameters(cluster_config, stdio) + for server in servers: + api_cursor = cursor.get(server) + server_config = start_env[server] + ip = server.ip + if ip == '127.0.0.1': + ip = NetUtil.get_host_ip() + url = 'http://{}:{}'.format(ip, api_cursor.port) + results.append({ + 'ip': ip, + 'port': api_cursor.port, + 'user': "admin", + 'password': server_config['admin_password'], + 'url': url, + 'status': 'active' if api_cursor and api_cursor.status(stdio) else 'inactive' + }) + stdio.print_list(results, ['url', 'username', 'password', 'status'], lambda x: [x['url'], 'admin', server_config['admin_password'], x['status']], title='ocp-server') + active_result = [r for r in results if r['status'] == 'active'] + info_dict = active_result[0] if len(active_result) > 0 else None + if info_dict is not None: + info_dict['type'] = 'web' + return plugin_context.return_true(info=info_dict) diff --git a/plugins/ocp-server/4.2.1/file_map.yaml b/plugins/ocp-server/4.2.1/file_map.yaml new file mode 100644 index 0000000..c2e8fc3 --- /dev/null +++ b/plugins/ocp-server/4.2.1/file_map.yaml @@ -0,0 +1,4 @@ +- src_path: ./home/admin/ocp-server/lib/ocp-server-ce-$version-$release_simple.jar + target_path: lib/ocp-server.jar + type: file + install_method: cp diff --git a/plugins/ocp-server/4.2.1/generate_config.py b/plugins/ocp-server/4.2.1/generate_config.py new file mode 100644 index 0000000..6cd6327 --- /dev/null +++ b/plugins/ocp-server/4.2.1/generate_config.py @@ -0,0 +1,64 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + + +from __future__ import absolute_import, division, print_function + + +def generate_config(plugin_context, auto_depend=False, generate_config_mini=False, return_generate_keys=False, *args, **kwargs): + if return_generate_keys: + return plugin_context.return_true(generate_keys=['memory_size', 'log_dir', 'logging_file_max_history']) + + cluster_config = plugin_context.cluster_config + stdio = plugin_context.stdio + depend_comps = [['obagent'], ['oceanbase', 'oceanbase-ce'], ['obproxy', 'obproxy-ce']] + generate_configs = {'global': {}} + plugin_context.set_variable('generate_configs', generate_configs) + stdio.start_loading('Generate ocp server configuration') + min_memory_size = '752M' + + if auto_depend: + for comps in depend_comps: + for comp in comps: + if cluster_config.add_depend_component(comp): + break + global_config = cluster_config.get_global_conf() + if generate_config_mini: + if 'memory_size' not in global_config: + cluster_config.update_global_conf('memory_size', min_memory_size) + + auto_set_memory = False + if 'memory_size' not in global_config: + for server in cluster_config.servers: + server_config = cluster_config.get_server_conf(server) + if 'memory_size' not in server_config: + auto_set_memory = True + if auto_set_memory: + observer_num = 0 + for comp in ['oceanbase', 'oceanbase-ce']: + if comp in cluster_config.depends: + observer_num = len(cluster_config.get_depend_servers(comp)) + if not observer_num: + stdio.warn('The component oceanbase/oceanbase-ce is not in the depends, the memory size cannot be calculated, and a fixed value of {} is used'.format(min_memory_size)) + cluster_config.update_global_conf('memory_size', min_memory_size) + else: + cluster_config.update_global_conf('memory_size', '%dM' % (512 + (observer_num + 3) * 60)) + + stdio.stop_loading('succeed') + return plugin_context.return_true() \ No newline at end of file diff --git a/plugins/ocp-server/4.2.1/init.py b/plugins/ocp-server/4.2.1/init.py new file mode 100644 index 0000000..1bcd5d3 --- /dev/null +++ b/plugins/ocp-server/4.2.1/init.py @@ -0,0 +1,162 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + + +from __future__ import absolute_import, division, print_function + +import os.path +from glob import glob + +import _errno as err +from const import CONST_OBD_HOME + + +OBD_INSTALL_PRE = os.environ.get('OBD_INSTALL_PRE', '/') + + +def _clean(server, client, path, stdio=None): + ret = client.execute_command('rm -fr %s' % path, timeout=-1) + if not ret: + stdio.warn(err.EC_CLEAN_PATH_FAILED.format(server=server, path=path)) + return False + else: + stdio.verbose('%s:%s cleaned' % (server, path)) + return True + + +def _ocp_lib(client, home_path, soft_dir='', stdio=None): + stdio.verbose('cp rpm & pos') + if soft_dir: + client.execute_command('mkdir -p -m 755 %s' % soft_dir, timeout=-1) + else: + client.execute_command('mkdir -p -m 755 %s/data/files/' % home_path, timeout=-1) + client.execute_command('mkdir -p -m 755 %s/ocp-server/lib/' % home_path, timeout=-1) + client.execute_command('mkdir -p -m 755 %s/logs/ocp/' % home_path, timeout=-1) + + OBD_HOME = os.path.join(os.environ.get(CONST_OBD_HOME, os.getenv('HOME')), '.obd') + for rpm in glob(os.path.join(OBD_HOME, 'mirror/local/*ocp-agent-*.rpm')): + name = os.path.basename(rpm) + client.put_file(rpm, os.path.join(home_path, 'ocp-server/lib/', name)) + if soft_dir: + client.put_file(rpm, os.path.join(soft_dir, name)) + + +def init(plugin_context, upgrade=False, *args, **kwargs): + cluster_config = plugin_context.cluster_config + clients = plugin_context.clients + stdio = plugin_context.stdio + + global_ret = True + force = getattr(plugin_context.options, 'force', False) + clean = getattr(plugin_context.options, 'clean', False) + if upgrade: + for server in cluster_config.servers: + _ocp_lib(client, home_path, soft_dir, stdio) + plugin_context.return_true() + return + + stdio.start_loading('Initializes ocp-server work home') + servers_dirs = {} + for server in cluster_config.servers: + server_config = cluster_config.get_server_conf(server) + client = clients[server] + ip = server.ip + if ip not in servers_dirs: + servers_dirs[ip] = {} + dirs = servers_dirs[ip] + home_path = server_config['home_path'] + launch_user = server_config.get('launch_user', None) + soft_dir = server_config.get('soft_dir', '') + keys = ['home_path', 'log_dir', 'soft_dir'] + for key in keys: + if key not in server_config: + continue + path = server_config[key] + if path in dirs: + global_ret = False + stdio.error(err.EC_CONFIG_CONFLICT_DIR.format(server1=server, path=path, server2=dirs[path]['server'], key=dirs[path]['key'])) + continue + dirs[path] = { + 'server': server, + 'key': key, + } + need_clean = force + if clean and not force: + if client.execute_command( + 'bash -c \'if [[ "$(ls -d {0} 2>/dev/null)" != "" && ! -O {0} ]]; then exit 0; else exit 1; fi\''.format( + home_path)): + owner = client.execute_command("ls -ld %s | awk '{print $3}'" % home_path).stdout.strip() + global_ret = False + err_msg = ' {} is not empty, and the owner is {}'.format(home_path, owner) + stdio.error(err.EC_FAIL_TO_INIT_PATH.format(server=server, key='home path', msg=err_msg)) + continue + need_clean = True + if need_clean: + port = server_config['port'] + client.execute_command("pkill -9 -u `whoami` -f 'java -jar {home_path}/lib/ocp-server.jar --port {port}'".format(home_path=home_path, port=port)) + if not _clean(server, client, home_path, stdio=stdio): + global_ret = False + continue + if client.execute_command('mkdir -p -m 755 %s' % home_path): + ret = client.execute_command('ls %s' % (home_path)) + if not ret or ret.stdout.strip(): + global_ret = False + stdio.error(err.EC_FAIL_TO_INIT_PATH.format(server=server, key='home path', msg=err.InitDirFailedErrorMessage.NOT_EMPTY.format(path=home_path))) + continue + else: + global_ret = False + stdio.error(err.EC_FAIL_TO_INIT_PATH.format(server=server, key='home path', msg=err.InitDirFailedErrorMessage.CREATE_FAILED.format(path=home_path))) + continue + if not client.execute_command("bash -c 'mkdir -p -m 755 %s/{run,bin,lib}'" % home_path): + global_ret = False + stdio.error(err.EC_FAIL_TO_INIT_PATH.format(server=server, key='home path', msg=err.InitDirFailedErrorMessage.PERMISSION_DENIED.format(path=home_path))) + if 'log_dir' in server_config: + log_dir = server_config['log_dir'] + if client.execute_command('mkdir -p -m 755 %s' % log_dir): + ret = client.execute_command('ls %s' % log_dir) + if not ret or ret.stdout.strip(): + global_ret = False + stdio.error(err.EC_FAIL_TO_INIT_PATH.format(server=server, key='log dir', msg=err.InitDirFailedErrorMessage.NOT_EMPTY.format(path=log_dir))) + continue + else: + global_ret = False + stdio.error(err.EC_FAIL_TO_INIT_PATH.format(server=server, key='log dir', msg=err.InitDirFailedErrorMessage.CREATE_FAILED.format(path=log_dir))) + continue + else: + log_dir = os.path.join(home_path, 'log') + if not client.execute_command('mkdir -p -m 755 %s' % log_dir): + global_ret = False + stdio.error(err.EC_FAIL_TO_INIT_PATH.format(server=server, key='log dir', msg=err.InitDirFailedErrorMessage.NOT_EMPTY.format(path=log_dir))) + continue + link_path = os.path.join(home_path, 'log') + client.execute_command("if [ ! '%s' -ef '%s' ]; then ln -sf %s %s; fi" % (log_dir, link_path, log_dir, link_path)) + _ocp_lib(client, home_path, soft_dir, stdio) + if launch_user: + res_home = client.execute_command("sudo chown -R %s %s" % (launch_user, home_path)) + res_log = client.execute_command("sudo chown -R %s %s" % (launch_user, log_dir)) + res_soft = client.execute_command("sudo chown -R %s %s" % (launch_user, soft_dir)) + if not (res_home and res_log and res_soft): + global_ret = False + if global_ret: + stdio.stop_loading('succeed') + plugin_context.return_true() + else: + stdio.stop_loading('fail') + plugin_context.return_false() + diff --git a/plugins/ocp-server/4.2.1/parameter.yaml b/plugins/ocp-server/4.2.1/parameter.yaml new file mode 100644 index 0000000..bf7816e --- /dev/null +++ b/plugins/ocp-server/4.2.1/parameter.yaml @@ -0,0 +1,363 @@ +- name: home_path + name_local: 工作目录 + require: true + essential: true + type: STRING + need_redeploy: true + description_en: the directory for the work data + description_local: OCP server server工作目录 +- name: port + name_local: 端口 + require: true + essential: true + type: INT + default: 8180 + need_restart: true + description_en: the port of ocp server. + description_local: OCP server使用的端口 +- name: log_dir + name_local: 日志目录 + type: STRING + require: false + essential: true + need_redeploy: true + description_en: The directory for logging file. The default value is $home_path/log. + description_local: OCP server server日志目录, 默认为工作目录下的log +- name: soft_dir + name_local: 软件包目录 + type: STRING + require: false + need_redeploy: true + description_en: The directory for software. The default value is ~/ocp-server/lib. + description_local: OCP server 软件包安装目录, ~/ocp-server/lib +- name: java_bin + name_local: java路径 + type: STRING + require: true + essential: true + default: java + need_restart: true + description_en: The path of java binary + description_local: OCP server 使用的java可执行文件的路径 +- name: memory_size + name_local: 进程内存 + require: false + essential: true + type: CAPACITY + min_value: 512M + need_restart: true + description_en: the memroy size of ocp server server. Please enter an capacity, such as 2G + description_local: OCP server server进程内存大小。请输入带容量带单位的整数,如2G +- name: admin_password + name_local: ocp login password + type: STRING + require: true + essential: true + default: aaAA11__ + need_restart: true + description_local: ocp 登录密码 + description_en: When logining ocp, use it +- name: logging_file_max_size + name_local: 单个日志文件大小 + type: STRING + require: false + essential: true + default: 100MB + need_restart: true + description_local: 单个日志文件大小 + description_en: When logging_file_name is configured, specify the log file size through this configuration +- name: logging_file_total_size_cap + name_local: 日志总大小 + type: STRING + require: true + essential: true + default: 1GB + need_restart: true + description_local: 日志文件总大小 + description_en: When logging_file_name is configured, specify the total log file size through this configuration +- name: jdbc_url + require: false + type: STRING + need_redeploy: true + description_en: The jdbc connection url for ocp meta db + description_local: OCP使用的元数据库的jdbc连接串 +- name: jdbc_username + require: false + type: STRING + need_redeploy: true + description_en: The username name for ocp meta dbx + description_local: OCP使用的元数据库的用户名 +- name: jdbc_password + require: false + type: STRING + default: + need_redeploy: true + description_en: The password name for ocp meta db + description_local: OCP使用的元数据库的密码 +- name: system_password + require: true + type: STRING + default: oceanbase + need_restart: true + description_en: The password name for ocp server + description_local: OCP server中system用户的密码 +- name: launch_user + require: false + type: STRING + default: '' + need_redeploy: true + description_en: Start user of OCP process + description_local: OCP进程的启动用户 +- name: 'session_timeout' + type: 'STRING' + require: false + need_restart: true + description_local: '登陆会话/Session超时的时间,默认是30m,最少60s。如果不加后缀单位,则默认是秒。重启生效。' + description_en: 'Session timeout interval, default is 30m, at least 60s. If the suffix unit is not added, the default is seconds. Restart OCP to take effect.' +- name: 'login_encrypt_enabled' + type: 'STRING' + require: false + need_restart: true + description_local: '登录信息是否开启加密传输,默认开启,重启生效' + description_en: 'Switch to enable encrypted transmission of login information, enabled by default. Restart OCP to take effect.' +- name: 'login_encrypt_public_key' + type: 'STRING' + require: false + need_restart: true + description_local: '加密登录信息的公钥,建议部署后修改此配置,修改后重启生效' + description_en: 'The public key for login encryption, It is recommended to modify this configuration after deployment. Restart OCP to take effect.' +- name: 'login_encrypt_private_key' + type: 'STRING' + require: false + need_restart: true + description_local: '加密登录信息的私钥,建议部署后修改此配置,修改后重启生效' + description_en: 'The private key for encryption. It is recommended to modify this configuration after deployment. Restart OCP to take effect.' +- name: 'enable_basic_auth' + type: 'STRING' + require: false + need_restart: true + description_local: '是否启用Basic Auth登陆模式,通常供程序和SDK等客户端场景使用,默认true。本配置与ocp.iam.auth可同时开启。重启生效。' + description_en: 'Whether to enable Basic Authentication, usually for client programs and SDKs to call server APIs. The default is true. This configuration and ocp.iam.auth can be enabled together. Restart OCP to take effect.' +- name: 'enable_csrf' + type: 'STRING' + require: false + need_restart: true + description_local: '是否启用CSRF跨站点请求伪造安全保护,通常基于网页登陆的方式都推荐要启用,默认true。重启生效。' + description_en: 'Whether to enable CSRF cross-site request forgery security protection. It is recommended to enable it, the default is true. Restart OCP to take effect.' +- name: 'vault_key' + type: 'STRING' + require: false + need_restart: true + description_local: '密码箱加密密钥' + description_en: 'vault secret key' +- name: 'druid_name' + type: 'STRING' + require: false + need_restart: true + description_local: 'metadb的druid连接池名称。重启生效' + description_en: 'metadb druid connection pool name. Restart to take effect' +- name: 'druid_init_size' + type: 'STRING' + require: false + need_restart: true + description_local: '初始化时建立物理连接的个数。重启生效' + description_en: 'The number of physical connections established during initialization. Restart to take effect' +- name: 'druid_min_idle' + type: 'STRING' + require: false + need_restart: true + description_local: '最小连接池数量。重启生效' + description_en: 'Minimum number of connections. Restart to take effect' +- name: 'druid_max_active' + type: 'STRING' + require: false + need_restart: true + description_local: '最大连接池数量。重启生效' + description_en: 'The maximum number of connections. Restart to take effect' +- name: 'druid_test_while_idle' + type: 'STRING' + require: false + need_restart: true + description_local: '建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测。重启生效' + description_en: 'It is recommended to set it to true, which will not affect performance and ensure safety. Detect when applying for connection. Restart to take effect' +- name: 'druid_validation_query' + type: 'STRING' + require: false + need_restart: true + description_local: '用来检测连接是否有效的sql。重启生效' + description_en: 'SQL used to detect whether the connection is valid. Restart to take effect' +- name: 'druid_max_wait' + type: 'STRING' + require: false + need_restart: true + description_local: '获取连接时最大等待时间,单位毫秒。重启生效' + description_en: 'Maximum waiting time when getting a connection, in milliseconds. Restart to take effect' +- name: 'druid_keep_alive' + type: 'STRING' + require: false + need_restart: true + description_local: '连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis(缺省值1800秒),则会执行keepAlive操作。重启生效' + description_en: 'For connections within the number of minIdle in the connection pool, if the idle time exceeds minEvictableIdleTimeMillis (the default value is 1800 seconds), the keepAlive operation will be performed. Restart to take effect' +- name: 'logging_pattern_console' + type: 'STRING' + require: false + need_restart: true + description_local: '用于控制台输出的日志格式' + description_en: 'Log format for console output' +- name: 'logging_pattern_file' + type: 'STRING' + require: false + need_restart: true + description_local: '用于文件输出的日志格式' + description_en: 'Log format used for file output' +- name: 'logging_file_clean_when_start' + type: 'STRING' + require: false + need_restart: true + description_local: '启动时删除压缩的日志文件' + description_en: 'Clean the archive log files on startup' +- name: 'logging_file_max_history' + name_local: 日志保留天数 + type: INT + require: false + essential: true + need_restart: true + min_value: 1 + max_value: 2147483647 + description_local: '最多保留的归档日志文件的天数,默认不限制' + description_en: 'When logging.file is configured, set the maximum of retention days the log archive log files to keep. The default value is unlimited' +- name: 'default_timezone' + type: 'STRING' + require: false + need_restart: true + description_local: '系统默认时区,若不设置则使用 system default time zone,重启生效' + description_en: 'System default time zone, if not set, use system default time zone, restart to take effect' +- name: 'default_lang' + type: 'STRING' + require: false + need_restart: true + description_local: '系统默认语言(非前端语言设置),若不设置则使用 zh-CN,重启生效' + description_en: 'System default language (non-front-end language setting), if not set, use zh-CN, restart to take effect' +- name: 'ocp.idempotent.client-token.expire.time' + type: 'STRING' + require: false + need_restart: true + description_local: '幂等请求token的缓存过期时间,默认14d' + description_en: 'Expire time of idempotent client token, the default is 14d' +- name: 'exporter_inactive_threshold' + type: 'INT' + require: false + need_restart: true + description_local: 'exporter地址判定为失效的连续不可用时间(秒)' + description_en: 'consecutive failure time of exporter address that is regarded as inactive (seconds)' +- name: 'ocp.monitor.host.exporters' + type: 'STRING' + require: false + need_restart: true + description_local: '主机监控exporter' + description_en: 'exporters of ocp host' +- name: 'ocp.monitor.ob.exporters' + type: 'STRING' + require: false + need_restart: true + description_local: 'OB监控exporter' + description_en: 'exporters of ob' +- name: 'monitor_collect_interval' + type: 'STRING' + require: false + need_restart: true + description_local: '秒级别监控采集间隔,默认 1s,支持配置选项是 1s, 5s, 10s, 15s' + description_en: 'The parameter determines the second-level monitoring and collection interval. The supported configuration options are 1s, 5s, 10s, 15s. Default value is 1s' +- name: 'montior_retention_days' + type: 'STRING' + require: false + need_restart: true + description_local: '监控数据保存天数,key 是监控数据的表名,value 是保存的天数,修改后重启生效.' + description_en: 'Retention days for monitor data, key is table name for monitor data, value is the retention days. Restart to take effect.' +- name: ocp_meta_tenant + require: true + type: DICT + default: + tenant_name: meta_tenant + max_cpu: 1 + memory_size: 2147483648 + need_redeploy: true + description_en: The tenant specifications for ocp meta db + description_local: ocp server的元数据库使用的租户规格 +- name: ocp_monitor_tenant + require: false + type: DICT + default: + tenant_name: monitor_tenant + max_cpu: 1 + memory_size: 2147483648 + need_redeploy: true + description_en: The tenant specifications for ocp monitor + description_local: ocp server的监控租户使用的租户规格 +- name: ocp_meta_tenant_log_disk_size + name_local: OCP server元数据库租户日志磁盘大小 + essential: true + require: false + type: CAPACITY_MB + default: 2048M + need_redeploy: true + description_en: The tenant log disk size for ocp meta db + description_local: ocp server的元数据库使用的租户日志磁盘大小 +- name: ocp_monitor_tenant_log_disk_size + name_local: OCP server监控租户日志磁盘大小 + essential: true + require: false + type: CAPACITY_MB + default: 2048M + need_redeploy: true + description_en: The tenant log disk size for ocp monitor db + description_local: ocp server的监控租户使用的租户日志磁盘大小 +- name: ocp_meta_username + require: false + type: STRING + default: meta + need_redeploy: true + description_en: The user name for ocp meta db + description_local: ocp server的元数据库使用的用户名 +- name: ocp_meta_password + require: true + type: STRING + default: oceanbase + need_redeploy: true + description_en: The password for ocp meta db + description_local: ocp server的元数据库使用的密码 +- name: ocp_meta_db + require: false + type: STRING + default: meta_database + need_redeploy: true + description_en: The database name for ocp meta db + description_local: ocp server的元数据库使用的数据库名 +- name: ocp_monitor_username + require: false + type: STRING + default: monitor_user + description_en: The username for obagent monitor user + description_local: obagent 监控用户的用户名 +- name: ocp_monitor_password + require: false + type: STRING + default: oceanbase + need_redeploy: true + description_en: The password for obagent monitor password + description_local: obagent 监控用户的密码 +- name: ocp_monitor_db + require: false + type: STRING + default: monitor_database + need_redeploy: true + description_en: The database name for ocp meta db + description_local: ocp server的监控数据库使用的数据库名 +- name: ocp_site_url + require: false + type: STRING + default: '' + need_restart: true + need_redeploy: true + description_en: The url for ocp server + description_local: ocp server的连接串 diff --git a/plugins/ocp-server/4.2.1/reload.py b/plugins/ocp-server/4.2.1/reload.py new file mode 100644 index 0000000..83a8411 --- /dev/null +++ b/plugins/ocp-server/4.2.1/reload.py @@ -0,0 +1,25 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + + +from __future__ import absolute_import, division, print_function + + +def reload(plugin_context, *args, **kwargs): + return plugin_context.return_true() diff --git a/plugins/ocp-server/4.2.1/restart.py b/plugins/ocp-server/4.2.1/restart.py new file mode 100644 index 0000000..9de2d40 --- /dev/null +++ b/plugins/ocp-server/4.2.1/restart.py @@ -0,0 +1,157 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + + +from __future__ import absolute_import, division, print_function + +import os + + +class Restart(object): + + def __init__(self, plugin_context, local_home_path, start_check_plugin, start_plugin, reload_plugin, stop_plugin, connect_plugin, + display_plugin, repository, new_cluster_config=None, new_clients=None, bootstrap_plugin=None, + repository_dir_map=None): + self.local_home_path = local_home_path + + self.namespace = plugin_context.namespace + self.namespaces = plugin_context.namespaces + self.deploy_name = plugin_context.deploy_name + self.repositories = plugin_context.repositories + self.plugin_name = plugin_context.plugin_name + + self.components = plugin_context.components + self.clients = plugin_context.clients + self.cluster_config = plugin_context.cluster_config + self.cmds = plugin_context.cmds + self.options = plugin_context.options + self.dev_mode = plugin_context.dev_mode + self.stdio = plugin_context.stdio + + self.plugin_context = plugin_context + self.repository = repository + self.start_check_plugin = start_check_plugin + self.start_plugin = start_plugin + self.reload_plugin = reload_plugin + self.connect_plugin = connect_plugin + self.display_plugin = display_plugin + self.bootstrap_plugin = bootstrap_plugin + self.stop_plugin = stop_plugin + self.new_clients = new_clients + self.new_cluster_config = new_cluster_config + self.sub_io = self.stdio.sub_io() + self.dbs = None + self.cursors = None + self.repository_dir_map = repository_dir_map + + def call_plugin(self, plugin, **kwargs): + args = { + 'namespace': self.namespace, + 'namespaces': self.namespaces, + 'deploy_name': self.deploy_name, + 'cluster_config': self.cluster_config, + 'repositories': self.repositories, + 'repository': self.repository, + 'components': self.components, + 'clients': self.clients, + 'cmd': self.cmds, + 'options': self.options, + 'stdio': self.sub_io + } + args.update(kwargs) + + self.stdio.verbose('Call %s for %s' % (plugin, self.repository)) + return plugin(**args) + + def connect(self, cluster_config): + if self.cursors is None: + self.sub_io.start_loading('Connect to ocp express') + ret = self.call_plugin(self.connect_plugin, cluster_config=cluster_config) + if not ret: + self.sub_io.stop_loading('fail') + return False + self.sub_io.stop_loading('succeed') + self.cursors = ret.get_return('cursor') + self.dbs = ret.get_return('connect') + return True + + def dir_read_check(self, client, path): + if not client.execute_command('cd %s' % path): + dirpath, name = os.path.split(path) + return self.dir_read_check(client, dirpath) and client.execute_command('sudo chmod +1 %s' % path) + return True + + def restart(self): + clients = self.clients + if not self.call_plugin(self.stop_plugin, clients=clients): + self.stdio.stop_loading('stop_loading', 'fail') + return False + + if self.new_clients: + self.stdio.verbose('use new clients') + for server in self.cluster_config.servers: + new_client = self.new_clients[server] + server_config = self.cluster_config.get_server_conf(server) + for key in ['home_path', 'data_dir']: + if key in server_config: + path = server_config[key] + if not new_client.execute_command('sudo chown -R %s: %s' % (new_client.config.username, path)): + self.stdio.stop_loading('stop_loading', 'fail') + return False + self.dir_read_check(new_client, path) + clients = self.new_clients + + cluster_config = self.new_cluster_config if self.new_cluster_config else self.cluster_config + + need_bootstrap = self.bootstrap_plugin is not None + if not self.call_plugin(self.start_check_plugin, clients=clients, cluster_config=cluster_config): + self.stdio.stop_loading('stop_loading', 'fail') + return False + if not self.call_plugin(self.start_plugin, clients=clients, cluster_config=cluster_config, local_home_path=self.local_home_path, need_bootstrap=need_bootstrap, repository_dir_map=self.repository_dir_map): + self.rollback() + self.stdio.stop_loading('stop_loading', 'fail') + return False + + if self.connect(cluster_config): + if self.bootstrap_plugin: + self.call_plugin(self.bootstrap_plugin, cursor=self.cursors) + return self.call_plugin(self.display_plugin, cursor=self.cursors) + return False + + def rollback(self): + if self.new_clients: + cluster_config = self.new_cluster_config if self.new_cluster_config else self.cluster_config + self.call_plugin(self.stop_plugin, clients=self.new_clients, cluster_config=cluster_config) + for server in self.cluster_config.servers: + client = self.clients[server] + new_client = self.new_clients[server] + server_config = self.cluster_config.get_server_conf(server) + home_path = server_config['home_path'] + new_client.execute_command('sudo chown -R %s: %s' % (client.config.username, home_path)) + + +def restart(plugin_context, local_home_path, start_check_plugin, start_plugin, reload_plugin, stop_plugin, connect_plugin, display_plugin, + new_cluster_config=None, new_clients=None, rollback=False, bootstrap_plugin=None, repository_dir_map=None, *args, + **kwargs): + repository = kwargs.get('repository') + task = Restart(plugin_context=plugin_context, local_home_path=local_home_path, start_check_plugin=start_check_plugin, start_plugin=start_plugin, bootstrap_plugin=bootstrap_plugin, reload_plugin=reload_plugin, stop_plugin=stop_plugin, connect_plugin=connect_plugin, + display_plugin=display_plugin, repository=repository, new_cluster_config=new_cluster_config, new_clients=new_clients, repository_dir_map=repository_dir_map) + call = task.rollback if rollback else task.restart + if call(): + plugin_context.return_true() diff --git a/plugins/ocp-server/4.2.1/start.py b/plugins/ocp-server/4.2.1/start.py new file mode 100644 index 0000000..cdd6284 --- /dev/null +++ b/plugins/ocp-server/4.2.1/start.py @@ -0,0 +1,715 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + + +from __future__ import absolute_import, division, print_function + +import copy +import os +import re +import time +from glob import glob +from copy import deepcopy +from const import CONST_OBD_HOME + +from tool import Cursor, FileUtil, YamlLoader +from _errno import EC_OBSERVER_CAN_NOT_MIGRATE_IN + + +OBD_INSTALL_PRE = os.environ.get('OBD_INSTALL_PRE', '/') + +PRI_KEY_FILE = '.ocp-server' +PUB_KEY_FILE = '.ocp-server.pub' + + +EXCLUDE_KEYS = [ + "home_path", "cluster_name", "ob_cluster_id", "admin_password", "memory_xms", "memory_xmx", "ocpCPU", + "root_sys_password", "server_addresses", "system_password", "memory_size", 'jdbc_url', 'jdbc_username', + 'jdbc_password', "ocp_meta_tenant", "ocp_meta_tenant_log_disk_size", "ocp_meta_username", "ocp_meta_password", + + ] + +CONFIG_MAPPER = { + "port": "server.port", + "session_timeout": "server.servlet.session.timeout", + "login_encrypt_enabled": "ocp.login.encryption.enabled", + "login_encrypt_public_key": "ocp.login.encryption.public-key", + "login_encrypt_private_key": "ocp.login.encryption.private-key", + "enable_basic_auth": "ocp.iam.auth.basic.enabled", + "enable_csrf": "ocp.iam.csrf.enabled", + "vault_key": "ocp.express.vault.secret-key", + "druid_name": "spring.datasource.druid.name", + "druid_init_size": "spring.datasource.druid.initial-size", + "druid_min_idle": "spring.datasource.druid.min-idle", + "druid_max_active": "spring.datasource.druid.max-active", + "druid_test_while_idle": "spring.datasource.druid.test-while-idle", + "druid_validation_query": "spring.datasource.druid.validation-query", + "druid_max_wait": "spring.datasource.druid.max-wait", + "druid_keep_alive": "spring.datasource.druid.keep-alive", + "logging_pattern_console": "logging.pattern.console", + "logging_pattern_file": "logging.pattern.file", + "logging_file_name": "logging.file.name", + "logging_file_max_size": "logging.file.max-size", + "logging_file_total_size_cap": "logging.file.total-size-cap", + "logging_file_clean_when_start": "logging.file.clean-history-on-start", + "logging_file_max_history": "logging.file.max-history", + "logging_level_web": "logging.level.web", + "default_timezone": "ocp.system.default.timezone", + "default_lang": "ocp.system.default.language", + "obsdk_sql_query_limit": "ocp.monitor.collect.obsdk.sql-query-row-limit", + "exporter_inactive_threshold": "ocp.monitor.exporter.inactive.threshold.seconds", + "monitor_collect_interval": "ocp.metric.collect.interval.second", + "montior_retention_days": "ocp.monitor.data.retention-days", + "obsdk_cache_size": "obsdk.connector.holder.capacity", + "obsdk_max_idle": "obsdk.connector.max-idle.seconds", + "obsdk_cleanup_period": "obsdk.connector.cleanup.period.seconds", + "obsdk_print_sql": "obsdk.print.sql", + "obsdk_slow_query_threshold": "obsdk.slow.query.threshold.millis", + "obsdk_init_timeout": "obsdk.connector.init.timeout.millis", + "obsdk_init_core_size": "obsdk.connector.init.executor.thread-count", + "obsdk_global_timeout": "obsdk.operation.global.timeout.millis", + "obsdk_connect_timeout": "obsdk.socket.connect.timeout.millis", + "obsdk_read_timeout": "obsdk.socket.read.timeout.millis" + } + + +def parse_size(size): + _bytes = 0 + if isinstance(size, str): + size = size.strip() + if not isinstance(size, str) or size.isdigit(): + _bytes = int(size) + else: + units = {"B": 1, "K": 1 << 10, "M": 1 << 20, "G": 1 << 30, "T": 1 << 40} + match = re.match(r'^(0|[1-9][0-9]*)\s*([B,K,M,G,T])$', size.upper()) + _bytes = int(match.group(1)) * units[match.group(2)] + return _bytes + + +def format_size(size, precision=1): + units = ['B', 'K', 'M', 'G', 'T', 'P'] + idx = 0 + if precision: + div = 1024.0 + format = '%.' + str(precision) + 'f%s' + else: + div = 1024 + format = '%d%s' + while idx < 5 and size >= 1024: + size /= 1024.0 + idx += 1 + return format % (size, units[idx]) + + +def exec_sql_in_tenant(sql, cursor, tenant, password, mode, retries=10, args=None): + user = 'SYS' if mode == 'oracle' else 'root' + tenant_cursor = cursor.new_cursor(tenant=tenant, user=user, password=password) + while not tenant_cursor and retries: + retries -= 1 + time.sleep(2) + tenant_cursor = cursor.new_cursor(tenant=tenant, user=user, password=password) + return tenant_cursor.execute(sql, args) + + +def get_port_socket_inode(client, port, stdio): + port = hex(port)[2:].zfill(4).upper() + cmd = "bash -c 'cat /proc/net/{tcp*,udp*}' | awk -F' ' '{print $2,$10}' | grep '00000000:%s' | awk -F' ' '{print $2}' | uniq" % port + res = client.execute_command(cmd) + if not res or not res.stdout.strip(): + return False + stdio.verbose(res.stdout) + return res.stdout.strip().split('\n') + + +def confirm_port(client, pid, port, stdio, launch_user=None): + socket_inodes = get_port_socket_inode(client, port, stdio) + if not socket_inodes: + return False + if launch_user: + ret = client.execute_command("""su - %s -c 'ls -l /proc/%s/fd/ |grep -E "socket:\[(%s)\]"'""" % (launch_user, pid, '|'.join(socket_inodes))) + else: + ret = client.execute_command("ls -l /proc/%s/fd/ |grep -E 'socket:\[(%s)\]'" % (pid, '|'.join(socket_inodes))) + if ret and ret.stdout.strip(): + return True + return False + + +def get_missing_required_parameters(parameters): + results = [] + for key in ["jdbc_url", "jdbc_password", "jdbc_username", "cluster_name", "ob_cluster_id", "root_sys_password", + "server_addresses", "agent_username", "agent_password"]: + if parameters.get(key) is None: + results.append(key) + return results + + +def get_ocp_depend_config(cluster_config, stdio): + # depends config + env = {} + depend_observer = False + depend_info = {} + ob_servers_conf = {} + root_servers = [] + for comp in ["oceanbase", "oceanbase-ce"]: + ob_zones = {} + if comp in cluster_config.depends: + depend_observer = True + ob_servers = cluster_config.get_depend_servers(comp) + for ob_server in ob_servers: + ob_servers_conf[ob_server] = ob_server_conf = cluster_config.get_depend_config(comp, ob_server) + if 'server_ip' not in depend_info: + depend_info['server_ip'] = ob_server.ip + depend_info['mysql_port'] = ob_server_conf['mysql_port'] + zone = ob_server_conf['zone'] + if zone not in ob_zones: + ob_zones[zone] = ob_server + break + for comp in ['obproxy', 'obproxy-ce']: + if comp in cluster_config.depends: + obproxy_servers = cluster_config.get_depend_servers(comp) + obproxy_server = obproxy_servers[0] + obproxy_server_config = cluster_config.get_depend_config(comp, obproxy_server) + depend_info['server_ip'] = obproxy_server.ip + depend_info['mysql_port'] = obproxy_server_config['listen_port'] + break + + for server in cluster_config.servers: + server_config = deepcopy(cluster_config.get_server_conf_with_default(server)) + original_server_config = cluster_config.get_original_server_conf(server) + missed_keys = get_missing_required_parameters(original_server_config) + if missed_keys: + if 'jdbc_url' in missed_keys and depend_observer: + server_config['jdbc_url'] = 'jdbc:oceanbase://{}:{}/{}'.format(depend_info['server_ip'], + depend_info['mysql_port'], + server_config['ocp_meta_db']) + server_config['jdbc_username'] = '%s@%s' % ( + server_config['ocp_meta_username'], server_config['ocp_meta_tenant']['tenant_name']) + server_config['jdbc_password'] = server_config['ocp_meta_password'] + server_config['root_password'] = depend_info.get('root_password', '') + env[server] = server_config + return env + + +def start(plugin_context, start_env=None, cursor='', sys_cursor1='', without_ocp_parameter=False, *args, **kwargs): + def get_option(key, default=''): + value = getattr(options, key, default) + if not value: + value = default + return value + + def get_parsed_option(key, default=''): + value = get_option(key=key, default=default) + if value is None: + return value + try: + parsed_value = parse_size(value) + except: + stdio.exception("") + raise Exception("Invalid option {}: {}".format(key, value)) + return parsed_value + + def error(*arg, **kwargs): + stdio.error(*arg, **kwargs) + stdio.stop_loading('fail') + + def create_tenant(cursor, name, max_cpu, memory_size, db_username, tenant_password, database, stdio): + mode = get_option('mode', 'mysql').lower() + if not mode in ['mysql', 'oracle']: + error('No such tenant mode: %s.\n--mode must be `mysql` or `oracle`' % mode) + return plugin_context.return_false() + + unit_name = '%s_unit' % name + sql = 'select * from oceanbase.DBA_OB_UNIT_CONFIGS order by name' + res = cursor.fetchall(sql) + if res is False: + return plugin_context.return_false() + for row in res: + if str(row['NAME']) == unit_name: + unit_name += '1' + + pool_name = '%s_pool' % name + + sql = "select * from oceanbase.DBA_OB_TENANTS where TENANT_NAME = %s" + tenant_exists = False + res = cursor.fetchone(sql, [name]) + if res: + if create_if_not_exists: + tenant_exists = True + else: + error('Tenant %s already exists' % name) + return plugin_context.return_false() + elif res is False: + return plugin_context.return_false() + if not tenant_exists: + stdio.start_loading('Create tenant %s' % name) + zone_list = get_option('zone_list', set()) + MIN_CPU = 1 + MIN_MEMORY = 1073741824 + MIN_LOG_DISK_SIZE = 2147483648 + MIN_IOPS = 1024 + zone_obs_num = {} + sql = "select zone, count(*) num from oceanbase.__all_server where status = 'active' group by zone" + res = cursor.fetchall(sql, raise_exception=True) + + for row in res: + zone_obs_num[str(row['zone'])] = row['num'] + + if not zone_list: + zone_list = zone_obs_num.keys() + if isinstance(zone_list, str): + zones = zone_list.replace(';', ',').split(',') + else: + zones = zone_list + zone_list = "('%s')" % "','".join(zones) + + min_unit_num = min(zone_obs_num.items(), key=lambda x: x[1])[1] + unit_num = get_option('unit_num', min_unit_num) + if unit_num > min_unit_num: + error('resource pool unit num is bigger than zone server count') + return plugin_context.return_false() + + sql = "select count(*) num from oceanbase.__all_server where status = 'active' and start_service_time > 0" + count = 30 + while count: + num = cursor.fetchone(sql) + if num is False: + error('%s : execute failed' % sql) + return plugin_context.return_false() + num = num['num'] + if num >= unit_num: + break + count -= 1 + time.sleep(1) + if count == 0: + stdio.error(EC_OBSERVER_CAN_NOT_MIGRATE_IN) + return plugin_context.return_false() + + sql = "SELECT * FROM oceanbase.GV$OB_SERVERS where zone in %s" % zone_list + servers_stats = cursor.fetchall(sql, raise_exception=True) + cpu_available = servers_stats[0]['CPU_CAPACITY_MAX'] - servers_stats[0]['CPU_ASSIGNED_MAX'] + mem_available = servers_stats[0]['MEM_CAPACITY'] - servers_stats[0]['MEM_ASSIGNED'] + disk_available = servers_stats[0]['DATA_DISK_CAPACITY'] - servers_stats[0]['DATA_DISK_IN_USE'] + log_disk_available = servers_stats[0]['LOG_DISK_CAPACITY'] - servers_stats[0]['LOG_DISK_ASSIGNED'] + for servers_stat in servers_stats[1:]: + cpu_available = min(servers_stat['CPU_CAPACITY_MAX'] - servers_stat['CPU_ASSIGNED_MAX'], cpu_available) + mem_available = min(servers_stat['MEM_CAPACITY'] - servers_stat['MEM_ASSIGNED'], mem_available) + disk_available = min(servers_stat['DATA_DISK_CAPACITY'] - servers_stat['DATA_DISK_IN_USE'], + disk_available) + log_disk_available = min(servers_stat['LOG_DISK_CAPACITY'] - servers_stat['LOG_DISK_ASSIGNED'], + log_disk_available) + + if cpu_available < MIN_CPU: + error('%s: resource not enough: cpu count less than %s' % (zone_list, MIN_CPU)) + return plugin_context.return_false() + if mem_available < MIN_MEMORY: + error('%s: resource not enough: memory less than %s' % (zone_list, format_size(MIN_MEMORY))) + return plugin_context.return_false() + if log_disk_available < MIN_LOG_DISK_SIZE: + error( + '%s: resource not enough: log disk size less than %s' % (zone_list, format_size(MIN_MEMORY))) + return plugin_context.return_false() + + # cpu options + min_cpu = get_option('min_cpu', max_cpu) + if cpu_available < max_cpu: + error('resource not enough: cpu (Avail: %s, Need: %s)' % (cpu_available, max_cpu)) + return plugin_context.return_false() + if max_cpu < min_cpu: + error('min_cpu must less then max_cpu') + return plugin_context.return_false() + + # memory options + log_disk_size = get_parsed_option('log_disk_size', None) + + if memory_size is None: + memory_size = mem_available + if log_disk_size is None: + log_disk_size = log_disk_available + + if mem_available < memory_size: + error('resource not enough: memory (Avail: %s, Need: %s)' % ( + format_size(mem_available), format_size(memory_size))) + return plugin_context.return_false() + + # log disk size options + if log_disk_size is not None and log_disk_available < log_disk_size: + error('resource not enough: log disk space (Avail: %s, Need: %s)' % ( + format_size(disk_available), format_size(log_disk_size))) + return plugin_context.return_false() + + # iops options + max_iops = get_option('max_iops', None) + min_iops = get_option('min_iops', None) + iops_weight = get_option('iops_weight', None) + if max_iops is not None and max_iops < MIN_IOPS: + error('max_iops must greater than %d' % MIN_IOPS) + return plugin_context.return_false() + if max_iops is not None and min_iops is not None and max_iops < min_iops: + error('min_iops must less then max_iops') + return plugin_context.return_false() + + zone_num = len(zones) + charset = get_option('charset', '') + collate = get_option('collate', '') + replica_num = get_option('replica_num', zone_num) + logonly_replica_num = get_option('logonly_replica_num', 0) + tablegroup = get_option('tablegroup', '') + primary_zone = get_option('primary_zone', 'RANDOM') + locality = get_option('locality', '') + variables = get_option('variables', "ob_tcp_invited_nodes='%'") + + if replica_num == 0: + replica_num = zone_num + elif replica_num > zone_num: + error('replica_num cannot be greater than zone num (%s)' % zone_num) + return plugin_context.return_false() + if not primary_zone: + primary_zone = 'RANDOM' + if logonly_replica_num > replica_num: + error('logonly_replica_num cannot be greater than replica_num (%s)' % replica_num) + return plugin_context.return_false() + + # create resource unit + sql = "create resource unit %s max_cpu %.1f, memory_size %d" % (unit_name, max_cpu, memory_size) + if min_cpu is not None: + sql += ', min_cpu %.1f' % min_cpu + if max_iops is not None: + sql += ', max_iops %d' % max_iops + if min_iops is not None: + sql += ', min_iops %d' % min_iops + if iops_weight is not None: + sql += ', iops_weight %d' % iops_weight + if log_disk_size is not None: + sql += ', log_disk_size %d' % log_disk_size + + res = cursor.execute(sql, raise_exception=True) + + # create resource pool + sql = "create resource pool %s unit='%s', unit_num=%d, zone_list=%s" % ( + pool_name, unit_name, unit_num, zone_list) + res = cursor.execute(sql, raise_exception=True) + + # create tenant + sql = "create tenant %s replica_num=%d,zone_list=%s,primary_zone='%s',resource_pool_list=('%s')" + sql = sql % (name, replica_num, zone_list, primary_zone, pool_name) + if charset: + sql += ", charset = '%s'" % charset + if collate: + sql += ", collate = '%s'" % collate + if logonly_replica_num: + sql += ", logonly_replica_num = %d" % logonly_replica_num + if tablegroup: + sql += ", default tablegroup ='%s'" % tablegroup + if locality: + sql += ", locality = '%s'" % locality + + set_mode = "ob_compatibility_mode = '%s'" % mode + if variables: + sql += "set %s, %s" % (variables, set_mode) + else: + sql += "set %s" % set_mode + res = cursor.execute(sql, raise_exception=True) + stdio.stop_loading('succeed') + if database: + sql = 'create database if not exists {}'.format(database) + if not exec_sql_in_tenant(sql=sql, cursor=cursor, tenant=name, password=tenant_password if tenant_exists else '', mode=mode) and not create_if_not_exists: + stdio.error('failed to create database {}'.format(database)) + return plugin_context.return_false() + + db_password = tenant_password + if db_username: + sql = "create user if not exists '{username}' IDENTIFIED BY %s".format(username=db_username) + sargs = [db_password] + if exec_sql_in_tenant(sql=sql, cursor=cursor, tenant=name, password=tenant_password if tenant_exists else '', mode=mode, args=sargs): + sql = "grant all on *.* to '{username}' WITH GRANT OPTION".format(username=db_username) + if exec_sql_in_tenant(sql=sql, cursor=cursor, tenant=name, password=tenant_password if tenant_exists else '', mode=mode): + sql = 'alter user root IDENTIFIED BY %s' + if exec_sql_in_tenant(sql=sql, cursor=cursor, tenant=name, password=tenant_password if tenant_exists else '', mode=mode, args=sargs): + return True + stdio.error('failed to create user {}'.format(db_username)) + return plugin_context.return_false() + return True + + def _ocp_lib(client, home_path, soft_dir='', stdio=None): + stdio.verbose('cp rpm & pos') + OBD_HOME = os.path.join(os.environ.get(CONST_OBD_HOME, os.getenv('HOME')), '.obd') + for rpm in glob(os.path.join(OBD_HOME, 'mirror/local/*ocp-agent-*.rpm')): + name = os.path.basename(rpm) + client.put_file(rpm, os.path.join(home_path, 'ocp-server/lib/', name)) + if soft_dir: + client.put_file(rpm, os.path.join(soft_dir, name)) + + def start_cluster(times=0): + jdbc_host = jdbc_port = jdbc_url = jdbc_username = jdbc_password = jdbc_public_key = cursor = monitor_user = monitor_tenant = monitor_memory_size = monitor_max_cpu = monitor_password = monitor_db = meta_password = '' + for server in cluster_config.servers: + server_config = start_env[server] + # check meta db connect before start + jdbc_url = server_config['jdbc_url'] + jdbc_username = server_config['jdbc_username'] + jdbc_password = server_config['jdbc_password'] + root_password = server_config.get('root_password', '') + cursor = get_option('metadb_cursor', '') + cursor = kwargs.get('metadb_cursor', '') if cursor == '' else cursor + matched = re.match(r"^jdbc:\S+://(\S+?)(|:\d+)/(\S+)", jdbc_url) + stdio.verbose('metadb connect check') + if matched: + jdbc_host = matched.group(1) + jdbc_port = matched.group(2)[1:] + jdbc_database = matched.group(3) + password = root_password if root_password else jdbc_password + retries = 10 + while not cursor and retries and get_option("skip_create_tenant", 'False') == 'False': + try: + retries -= 1 + time.sleep(2) + cursor = Cursor(ip=jdbc_host, port=jdbc_port, user='root@sys', password=password, stdio=stdio) + except: + pass + + global_config = cluster_config.get_global_conf() + site_url = global_config.get('ocp_site_url', '') + soft_dir = global_config.get('soft_dir', '') + meta_user = global_config.get('ocp_meta_username', 'meta_user') + meta_tenant = global_config.get('ocp_meta_tenant')['tenant_name'] + meta_max_cpu = global_config['ocp_meta_tenant'].get('max_cpu', 2) + meta_memory_size = global_config['ocp_meta_tenant'].get('memory_size', '2G') + meta_password = global_config.get('ocp_meta_password', '') + meta_db = global_config.get('ocp_meta_db', 'meta_database') + if global_config.get('ocp_monitor_tenant'): + monitor_user = global_config.get('ocp_monitor_username', 'monitor_user') + monitor_tenant = global_config['ocp_monitor_tenant']['tenant_name'] + monitor_max_cpu = global_config['ocp_monitor_tenant'].get('max_cpu', 2) + monitor_memory_size = global_config['ocp_monitor_tenant'].get('memory_size', '4G') + monitor_password = global_config.get('ocp_monitor_password', '') + monitor_db = global_config.get('ocp_monitor_db', 'monitor_database') + if get_option("skip_create_tenant", 'False') == 'False': + if not times: + if not create_tenant(cursor, meta_tenant, meta_max_cpu, parse_size(meta_memory_size), meta_user, + meta_password, + meta_db, stdio): + return plugin_context.return_false() + meta_cursor = Cursor(jdbc_host, jdbc_port, meta_user, meta_tenant, meta_password, stdio) + plugin_context.set_variable('meta_cursor', meta_cursor) + + if not times: + if not create_tenant(cursor, monitor_tenant, monitor_max_cpu, parse_size(monitor_memory_size), + monitor_user, + monitor_password, monitor_db, stdio): + return plugin_context.return_false() + if meta_tenant not in jdbc_username: + jdbc_username = meta_user + '@' + meta_tenant + jdbc_url = jdbc_url.rsplit('/', 1)[0] + '/' + meta_db + jdbc_password = meta_password + + server_pid = {} + success = True + stdio.start_loading("Start ocp-server") + for server in cluster_config.servers: + client = clients[server] + server_config = start_env[server] + home_path = server_config['home_path'] + launch_user = server_config.get('launch_user', None) + _ocp_lib(client, home_path, soft_dir, stdio) + system_password = server_config["system_password"] + port = server_config['port'] + if not site_url: + site_url = 'http://{}:{}'.format(server.ip, port) + pid_path = os.path.join(home_path, 'run/ocp-server.pid') + pids = client.execute_command("cat %s" % pid_path).stdout.strip() + if not times and pids and all([client.execute_command('ls /proc/%s' % pid) for pid in pids.split('\n')]): + server_pid[server] = pids + continue + + memory_xms = server_config.get('memory_xms', None) + memory_xmx = server_config.get('memory_xmx', None) + if memory_xms or memory_xmx: + jvm_memory_option = "-Xms{0} -Xmx{1}".format(memory_xms, memory_xmx) + else: + memory_size = server_config.get('memory_size', '1G') + jvm_memory_option = "-Xms{0} -Xmx{0}".format(format_size(parse_size(memory_size), 0).lower()) + extra_options = { + "ocp.iam.encrypted-system-password": system_password + } + extra_options_str = ' '.join(["-D{}={}".format(k, v) for k, v in extra_options.items()]) + java_bin = server_config['java_bin'] + cmd = f'{java_bin} -jar {jvm_memory_option} {extra_options_str} {home_path}/lib/ocp-server.jar --bootstrap' + jar_cmd = copy.deepcopy(cmd) + if "log_dir" not in server_config: + log_dir = os.path.join(home_path, 'log') + else: + log_dir = server_config["log_dir"] + server_config["logging_file_name"] = os.path.join(log_dir, 'ocp-server.log') + jdbc_password_to_str = jdbc_password.replace("'", """'"'"'""") + environ_variable = 'export JDBC_URL=%s; export JDBC_USERNAME=%s;' \ + 'export JDBC_PASSWORD=\'%s\'; ' \ + 'export JDBC_PUBLIC_KEY=%s;' % ( + jdbc_url, jdbc_username, jdbc_password_to_str, jdbc_public_key + ) + if not times: + cmd += ' --progress-log={}'.format(os.path.join(log_dir, 'bootstrap.log')) + for key in server_config: + if key == 'jdbc_url' and monitor_user: + monitor_password = monitor_password.replace("'", """'"'"'""") + cmd += f' --with-property=ocp.monitordb.host:{jdbc_host}' \ + f' --with-property=ocp.monitordb.username:{monitor_user + "@" + monitor_tenant}' \ + f' --with-property=ocp.monitordb.port:{jdbc_port}' \ + f' --with-property=ocp.monitordb.password:\'{monitor_password}\'' \ + f' --with-property=ocp.monitordb.database:{monitor_db}' + if key not in EXCLUDE_KEYS and key in CONFIG_MAPPER: + cmd += ' --with-property={}:{}'.format(CONFIG_MAPPER[key], server_config[key]) + cmd += ' --with-property=ocp.site.url:{}'.format(site_url) + # set connection mode to direct to avoid obclient issue + cmd += ' --with-property=obsdk.ob.connection.mode:direct' + if server_config['admin_password'] != '********': + admin_password = server_config['admin_password'].replace("'", """'"'"'""") + environ_variable += "export OCP_INITIAL_ADMIN_PASSWORD=\'%s\';" % admin_password + cmd += f' --with-property=ocp.file.local.built-in.dir:{home_path}/ocp-server/lib' + cmd += f' --with-property=ocp.log.download.tmp.dir:{home_path}/logs/ocp' + cmd += ' --with-property=ocp.file.local.dir:{}'.format(soft_dir) if soft_dir else f' --with-property=ocp.file.local.dir:{home_path}/data/files' + real_cmd = environ_variable + cmd + execute_cmd = "cd {}; {} > /dev/null 2>&1 &".format(home_path, real_cmd) + if server_config.get('launch_user'): + cmd_file = os.path.join(home_path, 'cmd.sh') + client.write_file(execute_cmd, cmd_file) + execute_cmd = "chmod +x {0};sudo chown -R {1} {0};sudo su - {1} -c '{0}' &".format(cmd_file, server_config['launch_user']) + client.execute_command(execute_cmd, timeout=3600) + time.sleep(10) + ret = client.execute_command( + "ps -aux | grep -F '%s' | grep -v grep | awk '{print $2}' " % jar_cmd) + if ret: + server_pid[server] = ret.stdout.strip() + if not server_pid[server]: + stdio.error("failed to start {} ocp server".format(server)) + success = False + continue + client.write_file(server_pid[server], os.path.join(home_path, 'run/ocp-server.pid')) + if times == 0 and len(cluster_config.servers) > 1: + break + + if success: + stdio.stop_loading('succeed') + else: + stdio.stop_loading('fail') + return plugin_context.return_false() + + stdio.start_loading("ocp-server program health check") + failed = [] + servers = server_pid.keys() + count = 40 + while servers and count: + count -= 1 + tmp_servers = [] + for server in servers: + server_config = cluster_config.get_server_conf(server) + client = clients[server] + stdio.verbose('%s program health check' % server) + pids_stat = {} + launch_user = server_config.get('launch_user', None) + if server in server_pid: + for pid in server_pid[server].split("\n"): + pids_stat[pid] = None + cmd = 'ls /proc/{}'.format(pid) if not launch_user else 'sudo ls /proc/{}'.format(pid) + if not client.execute_command(cmd): + pids_stat[pid] = False + continue + confirm = confirm_port(client, pid, int(server_config["port"]), stdio, launch_user) + if confirm: + pids_stat[pid] = True + break + if any(pids_stat.values()): + for pid in pids_stat: + if pids_stat[pid]: + stdio.verbose('%s ocp-server[pid: %s] started', server, pid) + continue + if all([stat is False for stat in pids_stat.values()]): + failed.append('failed to start {} ocp-server'.format(server)) + elif count: + tmp_servers.append(server) + stdio.verbose('failed to start %s ocp-server, remaining retries: %d' % (server, count)) + else: + failed.append('failed to start {} ocp-server'.format(server)) + servers = tmp_servers + if servers and count: + time.sleep(15) + + if failed: + stdio.stop_loading('failed') + for msg in failed: + stdio.error(msg) + return plugin_context.return_false() + else: + stdio.stop_loading('succeed') + plugin_context.return_true(need_bootstrap=False) + return True + + def stop_cluster(): + success = True + for server in cluster_config.servers: + server_config = cluster_config.get_server_conf(server) + client = clients[server] + home_path = server_config['home_path'] + pid_path = os.path.join(home_path, 'run/ocp-server.pid') + launch_user = server_config.get('launch_user', None) + cmd = 'cat {}'.format(pid_path) + pids = client.execute_command('sudo ' + cmd if launch_user else cmd).stdout.strip().split('\n') + success = False + for pid in pids: + cmd = 'ls /proc/{}'.format(pid) + if pid and client.execute_command('sudo ' + cmd if launch_user else cmd): + cmd = 'ls /proc/{}/fd'.format(pid) + if client.execute_command('sudo ' + cmd if launch_user else cmd): + stdio.verbose('{} ocp-server[pid: {}] stopping...'.format(server, pid)) + cmd = 'kill -9 {}'.format(pid) + client.execute_command('sudo ' + cmd if launch_user else cmd) + return True + else: + stdio.verbose('failed to stop ocp-server[pid:{}] in {}, permission deny'.format(pid, server)) + success = False + else: + stdio.verbose('{} ocp-server is not running'.format(server)) + if not success: + stdio.stop_loading('fail') + return plugin_context.return_true() + + cluster_config = plugin_context.cluster_config + options = plugin_context.options + clients = plugin_context.clients + stdio = plugin_context.stdio + create_if_not_exists = get_option('create_if_not_exists', True) + sys_cursor = kwargs.get('sys_cursor') + global tenant_cursor + tenant_cursor = None + + if not start_env: + start_env = get_ocp_depend_config(cluster_config, stdio) + if not start_env: + return plugin_context.return_false() + + if not without_ocp_parameter and not get_option('without_ocp_parameter', ''): + if not start_cluster(): + stdio.error('start ocp-server failed') + return plugin_context.return_false() + if not stop_cluster(): + stdio.error('stop ocp-server failed') + return plugin_context.return_false() + if not start_cluster(1): + stdio.error('start ocp-server failed') + return plugin_context.return_false() + time.sleep(10) + return plugin_context.return_true() diff --git a/plugins/ocp-server/4.2.1/start_check.py b/plugins/ocp-server/4.2.1/start_check.py new file mode 100644 index 0000000..184c242 --- /dev/null +++ b/plugins/ocp-server/4.2.1/start_check.py @@ -0,0 +1,590 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + + +from __future__ import absolute_import, division, print_function + +import re +import os +import time +import datetime + +from copy import deepcopy +from _rpm import Version +import _errno as err +from ssh import SshConfig, SshClient +from tool import Cursor +from const import CONST_OBD_HOME + +success = True + + +def get_missing_required_parameters(parameters): + results = [] + for key in ["jdbc_url", "jdbc_password", "jdbc_username"]: + if parameters.get(key) is None: + results.append(key) + return results + + +def get_port_socket_inode(client, port): + port = hex(port)[2:].zfill(4).upper() + cmd = "bash -c 'cat /proc/net/{udp*,tcp*}' | awk -F' ' '{print $2,$10}' | grep '00000000:%s' | awk -F' ' '{print $2}' | uniq" % port + res = client.execute_command(cmd) + if not res or not res.stdout.strip(): + return False + return res.stdout.strip().split('\n') + + +def password_check(passwd): + pattern = r"((?=(.*\d){2,})(?=(.*[a-z]){2,})(?=(.*[A-Z]){2,})(?=(.*[~!@#%^&*_\-+=|(){}\[\]:;,.?/]){2,})[0-9a-zA-Z~!@#%^&*_\-+=|(){}\[\]:;,.?/]{8,32})" + if re.match(pattern, passwd): + return True + + +def parse_size(size): + _bytes = 0 + if not isinstance(size, str) or size.isdigit(): + _bytes = int(size) + else: + units = {"B": 1, "K": 1<<10, "M": 1<<20, "G": 1<<30, "T": 1<<40} + match = re.match(r'(0|[1-9][0-9]*)\s*([B,K,M,G,T])', size.upper()) + _bytes = int(match.group(1)) * units[match.group(2)] + return _bytes + + +def format_size(size, precision=1): + units = ['B', 'K', 'M', 'G'] + units_num = len(units) - 1 + idx = 0 + if precision: + div = 1024.0 + format = '%.' + str(precision) + 'f%s' + limit = 1024 + else: + div = 1024 + limit = 1024 + format = '%d%s' + while idx < units_num and size >= limit: + size /= div + idx += 1 + return format % (size, units[idx]) + + +def get_mount_path(disk, _path): + _mount_path = '/' + for p in disk: + if p in _path: + if len(p) > len(_mount_path): + _mount_path = p + return _mount_path + + +def get_disk_info_by_path(path, client, stdio): + disk_info = {} + ret = client.execute_command('df --block-size=1024 {}'.format(path)) + if ret: + for total, used, avail, puse, path in re.findall(r'(\d+)\s+(\d+)\s+(\d+)\s+(\d+%)\s+(.+)', ret.stdout): + disk_info[path] = {'total': int(total) << 10, 'avail': int(avail) << 10, 'need': 0} + stdio.verbose('get disk info for path {}, total: {} avail: {}'.format(path, disk_info[path]['total'], disk_info[path]['avail'])) + return disk_info + + +def get_disk_info(all_paths, client, stdio): + overview_ret = True + disk_info = get_disk_info_by_path('', client, stdio) + if not disk_info: + overview_ret = False + disk_info = get_disk_info_by_path('/', client, stdio) + if not disk_info: + disk_info['/'] = {'total': 0, 'avail': 0, 'need': 0} + all_path_success = {} + for path in all_paths: + all_path_success[path] = False + cur_path = path + while cur_path not in disk_info: + disk_info_for_current_path = get_disk_info_by_path(cur_path, client, stdio) + if disk_info_for_current_path: + disk_info.update(disk_info_for_current_path) + all_path_success[path] = True + break + else: + cur_path = os.path.dirname(cur_path) + if overview_ret or all(all_path_success.values()): + return disk_info + + +def get_ocp_depend_config(cluster_config, stdio): + # depends config + env = {} + depend_observer = False + depend_info = {} + ob_servers_conf = {} + for comp in ["oceanbase", "oceanbase-ce"]: + ob_zones = {} + if comp in cluster_config.depends: + depend_observer = True + ob_servers = cluster_config.get_depend_servers(comp) + for ob_server in ob_servers: + ob_servers_conf[ob_server] = ob_server_conf = cluster_config.get_depend_config(comp, ob_server) + if 'server_ip' not in depend_info: + depend_info['server_ip'] = ob_server.ip + depend_info['mysql_port'] = ob_server_conf['mysql_port'] + depend_info['root_password'] = ob_server_conf['root_password'] + zone = ob_server_conf['zone'] + if zone not in ob_zones: + ob_zones[zone] = ob_server + break + for comp in ['obproxy', 'obproxy-ce']: + if comp in cluster_config.depends: + obproxy_servers = cluster_config.get_depend_servers(comp) + obproxy_server = obproxy_servers[0] + obproxy_server_config = cluster_config.get_depend_config(comp, obproxy_server) + depend_info['server_ip'] = obproxy_server.ip + depend_info['mysql_port'] = obproxy_server_config['listen_port'] + break + + for server in cluster_config.servers: + server_config = deepcopy(cluster_config.get_server_conf_with_default(server)) + original_server_config = cluster_config.get_original_server_conf(server) + missed_keys = get_missing_required_parameters(original_server_config) + if missed_keys: + if 'jdbc_url' in missed_keys and depend_observer: + server_config['jdbc_url'] = 'jdbc:oceanbase://{}:{}/{}'.format(depend_info['server_ip'], + depend_info['mysql_port'], + server_config['ocp_meta_db']) + server_config['jdbc_username'] = '%s@%s' % ( + server_config['ocp_meta_username'], server_config['ocp_meta_tenant']['tenant_name']) + server_config['jdbc_password'] = server_config['ocp_meta_password'] + server_config['root_password'] = depend_info['root_password'] + env[server] = server_config + return env + + +def execute_cmd(server_config, cmd): + return cmd if not server_config.get('launch_user', None) else 'sudo ' + cmd + + +def start_check(plugin_context, init_check_status=False, work_dir_check=False, work_dir_empty_check=True, strict_check=False, precheck=False, *args, **kwargs): + + def check_pass(item): + status = check_status[server] + if status[item].status == err.CheckStatus.WAIT: + status[item].status = err.CheckStatus.PASS + def check_fail(item, error, suggests=[]): + status = check_status[server][item] + if status.status == err.CheckStatus.WAIT: + status.error = error + status.suggests = suggests + status.status = err.CheckStatus.FAIL + def wait_2_pass(): + status = check_status[server] + for item in status: + check_pass(item) + def alert(item, error, suggests=[]): + global success + if strict_check: + success = False + check_fail(item, error, suggests) + stdio.error(error) + else: + stdio.warn(error) + def error(item, _error, suggests=[]): + global success + if plugin_context.dev_mode: + stdio.warn(_error) + else: + success = False + check_fail(item, _error, suggests) + stdio.error(_error) + def critical(item, error, suggests=[]): + global success + success = False + check_fail(item, error, suggests) + stdio.error(error) + + cluster_config = plugin_context.cluster_config + options = plugin_context.options + clients = plugin_context.clients + stdio = plugin_context.stdio + global success + success = True + + check_status = {} + plugin_context.set_variable('start_check_status', check_status) + for server in cluster_config.servers: + check_status[server] = { + 'metadb connect': err.CheckStatus(), + 'port': err.CheckStatus(), + 'java': err.CheckStatus(), + 'disk': err.CheckStatus(), + 'mem': err.CheckStatus(), + 'oceanbase version': err.CheckStatus(), + 'time check': err.CheckStatus(), + 'launch user': err.CheckStatus(), + 'sudo nopasswd': err.CheckStatus(), + 'tenant': err.CheckStatus(), + 'clockdiff': err.CheckStatus() + } + if work_dir_check: + check_status[server]['dir'] = err.CheckStatus() + if init_check_status: + return plugin_context.return_true(start_check_status=check_status) + + stdio.start_loading('Check before start ocp-server') + env = get_ocp_depend_config(cluster_config, stdio) + if not env: + return plugin_context.return_false() + + if not cluster_config.depends: + for server in cluster_config.servers: + server_config = env[server] + # check meta db connect before start + jdbc_url = server_config['jdbc_url'] + jdbc_username = server_config['jdbc_username'] + jdbc_password = server_config['jdbc_password'] + root_password = server_config.get('root_password', '') + matched = re.match(r"^jdbc:\S+://(\S+?)(|:\d+)/(\S+)", jdbc_url) + cursor = getattr(options, 'metadb_cursor', '') + cursor = kwargs.get('metadb_cursor', '') if cursor == '' else cursor + stdio.verbose('metadb connect check') + if matched: + jdbc_host = matched.group(1) + jdbc_port = matched.group(2)[1:] + jdbc_database = matched.group(3) + password = root_password if root_password else jdbc_password + connected = False + retries = 10 + while not connected and retries: + retries -= 1 + try: + cursor = Cursor(ip=jdbc_host, port=jdbc_port, user=jdbc_username, password=jdbc_password, + stdio=stdio) + connected = True + except: + jdbc_username = 'root' + time.sleep(1) + if not connected: + success = False + error('metadb connect', err.EC_CONNECT_METADB, err.SUG_OCP_SERVER_JDBC_URL_CONFIG_ERROR) + if cursor and not cursor.fetchone('show DATABASES like "%s"' % jdbc_database): + critical('metadb connect', err.EC_DB_NOT_IN_JDBC_URL, err.SUG_OCP_SERVER_JDBC_URL_CONFIG_ERROR) + else: + critical('metadb connect', err.EC_ERROR_JDBC_URL, err.SUG_OCP_SERVER_JDBC_URL_CONFIG_ERROR) + client = clients[server] + # time check + stdio.verbose('time check ') + now = client.execute_command('date +"%Y-%m-%d %H:%M:%S"').stdout.strip() + now = datetime.datetime.strptime(now, '%Y-%m-%d %H:%M:%S') + stdio.verbose('now: %s' % now) + stdio.verbose('cursor: %s' % cursor) + if cursor: + ob_time = cursor.fetchone("SELECT NOW() now")['now'] + stdio.verbose('ob_time: %s' % ob_time) + if not abs((now - ob_time).total_seconds()) < 180: + critical('time check', err.EC_OCP_SERVER_TIME_SHIFT.format(server=server)) + + # tenant check + skip_create_tenant = 'False' + skip_create_tenant = getattr(options, "skip_create_tenant", "False") + if skip_create_tenant == 'False': + sql = "select * from oceanbase.DBA_OB_TENANTS where TENANT_NAME = %s" + meta_tenant = server_config.get('ocp_meta_tenant')['tenant_name'] + meta_max_cpu = server_config['ocp_meta_tenant'].get('max_cpu', 2) + meta_memory_size = server_config['ocp_meta_tenant'].get('memory_size', '2G') + if server_config.get('ocp_monitor_tenant'): + monitor_user = server_config.get('ocp_monitor_username', 'monitor_user') + monitor_tenant = server_config['ocp_monitor_tenant']['tenant_name'] + monitor_max_cpu = server_config['ocp_monitor_tenant'].get('max_cpu', 2) + monitor_memory_size = server_config['ocp_monitor_tenant'].get('memory_size', '4G') + res = cursor.fetchone(sql, [monitor_tenant]) + if res: + error('tenant', err.EC_OCP_SERVER_TENANT_ALREADY_EXISTS.format({"tenant_name":monitor_tenant})) + res = cursor.fetchone(sql, [meta_tenant]) + if res: + error('tenant', err.EC_OCP_SERVER_TENANT_ALREADY_EXISTS.format({"tenant_name":meta_tenant})) + break + + stdio.verbose('oceanbase version check') + versions_check = { + "oceanbase version": { + 'comps': ['oceanbase', 'oceanbase-ce'], + 'min_version': Version('4.0') + }, + } + repo_versions = {} + for repository in plugin_context.repositories: + repo_versions[repository.name] = repository.version + + for check_item in versions_check: + for comp in versions_check[check_item]['comps']: + if comp not in cluster_config.depends: + continue + depend_comp_version = repo_versions.get(comp) + if depend_comp_version is None: + stdio.verbose('failed to get {} version, skip version check'.format(comp)) + continue + min_version = versions_check[check_item]['min_version'] + if depend_comp_version < min_version: + critical(check_item, err.EC_OCP_EXPRESS_DEPENDS_COMP_VERSION.format(ocp_express_version=cluster_config.version, comp=comp, comp_version=min_version)) + + server_port = {} + servers_dirs = {} + servers_check_dirs = {} + for server in cluster_config.servers: + client = clients[server] + + if not (client.execute_command('sudo -n true') or client.execute_command('[ `id -u` == "0" ]')): + critical('sudo nopasswd', err.EC_SUDO_NOPASSWD.format(ip=str(server), user=client.config.username), + [err.SUG_SUDO_NOPASSWD.format(ip=str(server), user=client.config.username)]) + server_config = env[server] + missed_keys = get_missing_required_parameters(server_config) + if missed_keys: + stdio.error(err.EC_NEED_CONFIG.format(server=server, component=cluster_config.name, miss_keys=missed_keys)) + success = False + home_path = server_config['home_path'] + if not precheck: + remote_pid_path = '%s/run/ocp-server.pid' % home_path + remote_pid = client.execute_command(execute_cmd(server_config, 'cat %s' % remote_pid_path)).stdout.strip() + if remote_pid: + if client.execute_command(execute_cmd(server_config, 'ls /proc/%s' % remote_pid)): + stdio.verbose('%s is running, skip' % server) + wait_2_pass() + + # user check + for server in cluster_config.servers: + server_config = env[server] + ocp_user = server_config.get('launch_user', '') + if ocp_user: + client = clients[server] + if not client.execute_command(execute_cmd(server_config, "id -u %s" % ocp_user)): + critical('launch user', err.EC_OCP_SERVER_LAUNCH_USER_NOT_EXIST.format(server=server, user=ocp_user)) + + for server in cluster_config.servers: + client = clients[server] + server_config = env[server] + if work_dir_check: + ip = server.ip + stdio.verbose('%s dir check' % server) + if ip not in servers_dirs: + servers_dirs[ip] = {} + servers_check_dirs[ip] = {} + dirs = servers_dirs[ip] + check_dirs = servers_check_dirs[ip] + original_server_conf = cluster_config.get_server_conf(server) + + keys = ['home_path', 'log_dir', 'soft_dir'] + for key in keys: + path = server_config.get(key) + suggests = [err.SUG_CONFIG_CONFLICT_DIR.format(key=key, server=server)] + if path in dirs and dirs[path]: + critical('dir', err.EC_CONFIG_CONFLICT_DIR.format(server1=server, path=path, server2=dirs[path]['server'], key=dirs[path]['key']), suggests) + dirs[path] = { + 'server': server, + 'key': key, + } + if key not in original_server_conf: + continue + empty_check = work_dir_empty_check + while True: + if path in check_dirs: + if check_dirs[path] != True: + critical('dir', check_dirs[path], suggests) + break + + if client.execute_command(execute_cmd(server_config, 'bash -c "[ -a %s ]"' % path)): + is_dir = client.execute_command(execute_cmd(server_config, '[ -d {} ]'.format(path))) + has_write_permission = client.execute_command(execute_cmd(server_config, '[ -w {} ]'.format(path))) + if is_dir and has_write_permission: + if empty_check: + check_privilege_cmd = "ls %s" % path + if server_config.get('launch_user', ''): + check_privilege_cmd = "sudo su - %s -c 'ls %s'" % (server_config['launch_user'], path) + ret = client.execute_command(check_privilege_cmd) + if not ret: + check_dirs[path] = err.EC_OCP_SERVER_DIR_ACCESS_FORBIDE.format(server=server, path=path, cur_path=path) + elif ret.stdout.strip(): + check_dirs[path] = err.EC_FAIL_TO_INIT_PATH.format(server=server, key=key, msg=err.InitDirFailedErrorMessage.NOT_EMPTY.format(path=path)) + else: + check_dirs[path] = True + else: + check_dirs[path] = True + else: + if not is_dir: + check_dirs[path] = err.EC_FAIL_TO_INIT_PATH.format(server=server, key=key, msg=err.InitDirFailedErrorMessage.NOT_DIR.format(path=path)) + else: + check_dirs[path] = err.EC_FAIL_TO_INIT_PATH.format(server=server, key=key, msg=err.InitDirFailedErrorMessage.PERMISSION_DENIED.format(path=path)) + else: + path = os.path.dirname(path) + empty_check = False + + port = server_config['port'] + ip = server.ip + if ip not in server_port: + server_port[ip] = {} + ports = server_port[ip] + if port in server_port[ip]: + critical( + 'port', + err.EC_CONFIG_CONFLICT_PORT.format(server1=server, port=port, server2=ports[port]['server'], + key=ports[port]['key']), + [err.SUG_PORT_CONFLICTS.format()] + ) + ports[port] = { + 'server': server, + 'key': 'port' + } + if get_port_socket_inode(client, port): + critical( + 'port', + err.EC_CONFLICT_PORT.format(server=ip, port=port), + [err.SUG_USE_OTHER_PORT.format()] + ) + check_pass('port') + + try: + # java version check + java_bin = server_config.get('java_bin', '/usr/bin/java') + ret = client.execute_command(execute_cmd(server_config, '{} -version'.format(java_bin))) + stdio.verbose('java version %s' % ret) + if not ret: + critical('java', err.EC_OCP_EXPRESS_JAVA_NOT_FOUND.format(server=server), [err.SUG_OCP_EXPRESS_INSTALL_JAVA_WITH_VERSION.format(version='1.8.0')]) + version_pattern = r'version\s+\"(\d+\.\d+\.\d+)(\_\d+)' + found = re.search(version_pattern, ret.stdout) or re.search(version_pattern, ret.stderr) + if not found: + error('java', err.EC_OCP_EXPRESS_JAVA_VERSION_ERROR.format(server=server, version='1.8.0'), [err.SUG_OCP_EXPRESS_INSTALL_JAVA_WITH_VERSION.format(version='1.8.0'),]) + java_major_version = found.group(1) + stdio.verbose('java_major_version %s' % java_major_version) + java_update_version = found.group(2)[1:] + stdio.verbose('java_update_version %s' % java_update_version) + if Version(java_major_version) != Version('1.8.0') or int(java_update_version) < 161: + critical('java', err.EC_OCP_SERVER_JAVA_VERSION_ERROR.format(server=server, version='1.8.0'), [err.SUG_OCP_EXPRESS_INSTALL_JAVA_WITH_VERSION.format(version='1.8.0'),]) + except Exception as e: + stdio.error(e) + error('java', err.EC_OCP_EXPRESS_JAVA_VERSION_ERROR.format(server=server, version='1.8.0'), + [err.SUG_OCP_EXPRESS_INSTALL_JAVA_WITH_VERSION.format(version='1.8.0'), ]) + + try: + # clockdiff status check + clockdiff_bin = 'which clockdiff' + if client.execute_command(clockdiff_bin): + check_pass('clockdiff') + else: + if not client.execute_command('sudo -n true'): + critical('clockdiff', err.EC_OCP_SERVER_CLOCKDIFF_NOT_EXISTS.format(server=server)) + ret = client.execute_command('sudo' + clockdiff_bin) + if not ret: + critical('clockdiff', err.EC_OCP_SERVER_CLOCKDIFF_NOT_EXISTS.format(server=server)) + + client.execute_command('which clockdiff | xargs sudo chmod u+s') + client.execute_command("which clockdiff | xargs sudo setcap 'cap_net_raw+ep'") + except Exception as e: + stdio.error(e) + critical('clockdiff', err.EC_OCP_SERVER_CLOCKDIFF_NOT_EXISTS.format(server=server)) + + servers_memory = {} + servers_disk = {} + servers_client = {} + ip_servers = {} + + for server in cluster_config.servers: + client = clients[server] + server_config = env[server] + memory_size = parse_size(server_config.get('memory_size', '1G')) + if server_config.get('log_dir'): + log_dir = server_config['log_dir'] + else: + log_dir = os.path.join(server_config['home_path'], 'log') + need_size = parse_size(server_config.get('logging_file_total_size_cap', '1G')) + ip = server.ip + if ip not in servers_client: + servers_client[ip] = client + if ip not in servers_memory: + servers_memory[ip] = { + 'need': memory_size, + 'server_num': 1 + } + else: + servers_memory[ip]['need'] += memory_size + servers_memory[ip]['server_num'] += 1 + if ip not in servers_disk: + servers_disk[ip] = {} + if log_dir not in servers_disk[ip]: + servers_disk[ip][log_dir] = need_size + else: + servers_disk[ip][log_dir] += need_size + if ip not in ip_servers: + ip_servers[ip] = [server] + else: + ip_servers[ip].append(server) + # memory check + for ip in servers_memory: + client = servers_client[ip] + memory_needed = servers_memory[ip]['need'] + ret = client.execute_command('cat /proc/meminfo') + if ret: + server_memory_stats = {} + memory_key_map = { + 'MemTotal': 'total', + 'MemFree': 'free', + 'MemAvailable': 'available', + 'Buffers': 'buffers', + 'Cached': 'cached' + } + for key in memory_key_map: + server_memory_stats[memory_key_map[key]] = 0 + + for k, v in re.findall('(\w+)\s*:\s*(\d+\s*\w+)', ret.stdout): + if k in memory_key_map: + key = memory_key_map[k] + server_memory_stats[key] = parse_size(str(v)) + mem_suggests = [err.SUG_OCP_EXPRESS_REDUCE_MEM.format()] + if memory_needed * 0.5 > server_memory_stats['available']: + for server in ip_servers[ip]: + error('mem', err.EC_OCP_EXPRESS_NOT_ENOUGH_MEMORY_AVAILABLE.format(ip=ip, available=format_size(server_memory_stats['available']), need=format_size(memory_needed)), suggests=mem_suggests) + elif memory_needed > server_memory_stats['free'] + server_memory_stats['buffers'] + server_memory_stats['cached']: + for server in ip_servers[ip]: + error('mem', err.EC_OCP_EXPRESS_NOT_ENOUGH_MEMORY_CACHED.format(ip=ip, free=format_size(server_memory_stats['free']), cached=format_size(server_memory_stats['buffers'] + server_memory_stats['cached']), need=format_size(memory_needed)), suggests=mem_suggests) + elif memory_needed > server_memory_stats['free']: + for server in ip_servers[ip]: + alert('mem', err.EC_OCP_EXPRESS_NOT_ENOUGH_MEMORY.format(ip=ip, free=format_size(server_memory_stats['free']), need=format_size(memory_needed)), suggests=mem_suggests) + # disk check + for ip in servers_disk: + client = servers_client[ip] + disk_info = get_disk_info(all_paths=servers_disk[ip], client=client, stdio=stdio) + if disk_info: + for path in servers_disk[ip]: + disk_needed = servers_disk[ip][path] + mount_path = get_mount_path(disk_info, path) + if disk_needed > disk_info[mount_path]['avail']: + for server in ip_servers[ip]: + error('disk', err.EC_OCP_EXPRESS_NOT_ENOUGH_DISK.format(ip=ip, disk=mount_path, need=format_size(disk_needed), avail=format_size(disk_info[mount_path]['avail'])), suggests=[err.SUG_OCP_EXPRESS_REDUCE_DISK.format()]) + else: + stdio.warn(err.WC_OCP_EXPRESS_FAILED_TO_GET_DISK_INFO.format(ip)) + plugin_context.set_variable('start_env', env) + + for server in cluster_config.servers: + wait_2_pass() + + if success: + stdio.stop_loading('succeed') + return plugin_context.return_true() + else: + stdio.stop_loading('fail') + return plugin_context.return_false() diff --git a/plugins/ocp-server/4.2.1/status.py b/plugins/ocp-server/4.2.1/status.py new file mode 100644 index 0000000..a92311c --- /dev/null +++ b/plugins/ocp-server/4.2.1/status.py @@ -0,0 +1,39 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + + +from __future__ import absolute_import, division, print_function + +import os + + +def status(plugin_context, *args, **kwargs): + cluster_config = plugin_context.cluster_config + clients = plugin_context.clients + cluster_status = {} + for server in cluster_config.servers: + server_config = cluster_config.get_server_conf(server) + client = clients[server] + cluster_status[server] = 0 + pid_path = os.path.join(server_config['home_path'], 'run/ocp-server.pid') + pids = client.execute_command('cat {}'.format(pid_path)).stdout.strip().split('\n') + for pid in pids: + if pid and client.execute_command('ls /proc/{}'.format(pid)): + cluster_status[server] = 1 + return plugin_context.return_true(cluster_status=cluster_status) \ No newline at end of file diff --git a/plugins/ocp-server/4.2.1/stop.py b/plugins/ocp-server/4.2.1/stop.py new file mode 100644 index 0000000..1711442 --- /dev/null +++ b/plugins/ocp-server/4.2.1/stop.py @@ -0,0 +1,107 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + + +from __future__ import absolute_import, division, print_function + +import os +import time + + +def get_port_socket_inode(client, port, stdio): + port = hex(port)[2:].zfill(4).upper() + cmd = "bash -c 'cat /proc/net/{tcp*,udp*}' | awk -F' ' '{print $2,$10}' | grep '00000000:%s' | awk -F' ' '{print $2}' | uniq" % port + res = client.execute_command(cmd) + if not res or not res.stdout.strip(): + return False + stdio.verbose(res.stdout) + return res.stdout.strip().split('\n') + + +def confirm_port(client, pid, port, stdio): + socket_inodes = get_port_socket_inode(client, port, stdio) + if not socket_inodes: + return False + ret = client.execute_command("ls -l /proc/%s/fd/ |grep -E 'socket:\[(%s)\]'" % (pid, '|'.join(socket_inodes))) + if ret and ret.stdout.strip(): + return True + return False + + +def stop(plugin_context, *args, **kwargs): + cluster_config = plugin_context.cluster_config + clients = plugin_context.clients + stdio = plugin_context.stdio + servers = {} + stdio.start_loading('Stop ocp-server') + success = True + for server in cluster_config.servers: + server_config = cluster_config.get_server_conf(server) + client = clients[server] + home_path = server_config['home_path'] + pid_path = os.path.join(home_path, 'run/ocp-server.pid') + launch_user = server_config.get('launch_user', None) + cmd = 'cat {}'.format(pid_path) + pids = client.execute_command('sudo ' + cmd if launch_user else cmd).stdout.strip().split('\n') + success = False + for pid in pids: + cmd = 'ls /proc/{}'.format(pid) + if pid and client.execute_command('sudo ' + cmd if launch_user else cmd): + cmd = 'ls /proc/{}/fd'.format(pid) + if client.execute_command('sudo ' + cmd if launch_user else cmd): + stdio.verbose('{} ocp-server[pid: {}] stopping...'.format(server, pid)) + cmd = 'kill -9 {}'.format(pid) + client.execute_command('sudo ' + cmd if launch_user else cmd) + else: + stdio.verbose('failed to stop ocp-server[pid:{}] in {}, permission deny'.format(pid, server)) + success = False + else: + stdio.verbose('{} ocp-server is not running'.format(server)) + if not success: + stdio.stop_loading('fail') + return plugin_context.return_true() + + count = 10 + check = lambda client, pid, port: confirm_port(client, pid, port, stdio) if count < 5 else get_port_socket_inode(client, port, stdio) + time.sleep(1) + while count and servers: + tmp_servers = {} + for server in servers: + data = servers[server] + client = clients[server] + stdio.verbose('%s check whether the port is released' % server) + for key in ['port']: + if data[key] and check(data['client'], data['pid'], data[key]): + tmp_servers[server] = data + break + data[key] = '' + else: + client.execute_command('rm -rf %s' % data['path']) + stdio.verbose('%s ocp-server is stopped', server) + servers = tmp_servers + count -= 1 + if count and servers: + time.sleep(3) + if servers: + stdio.stop_loading('fail') + for server in servers: + stdio.warn('%s port not released'% server) + else: + stdio.stop_loading('succeed') + return plugin_context.return_true() diff --git a/plugins/ocp-server/4.2.1/takeover.py b/plugins/ocp-server/4.2.1/takeover.py new file mode 100644 index 0000000..8551fb3 --- /dev/null +++ b/plugins/ocp-server/4.2.1/takeover.py @@ -0,0 +1,214 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2023 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + + +from __future__ import absolute_import, division, print_function + +import os +import re +import time +import json +import uuid +import requests +from _rpm import Version +from copy import deepcopy +from requests.auth import HTTPBasicAuth + +from tool import Cursor, FileUtil, YamlLoader +from _errno import EC_OBSERVER_CAN_NOT_MIGRATE_IN + +class OcpCursor(object): + + class Response(object): + + def __init__(self, code, content): + self.code = code + self.content = content + + def __bool__(self): + return self.code == 200 + + def __init__(self, base_url="http://localhost:8080", username=None, password=None): + self.base_url = base_url.strip("/") + self.auth = None + self.username=username + self.password=password + if self.username: + self.auth = HTTPBasicAuth(username=username, password=password) + + def status(self, stdio=None): + resp = self._request('GET', '/api/v2/time', stdio=stdio) + ocp_status_ok = False + now = time.time() + check_wait_time = 180 + while time.time() - now < check_wait_time: + stdio.verbose("query ocp to check...") + try: + if resp.code == 200: + ocp_status_ok = True + break + except Exception: + stdio.verbose("ocp still not active") + time.sleep(5) + if ocp_status_ok: + stdio.verbose("check ocp server status ok") + return True + else: + stdio.verbose("ocp still not ok, check failed") + raise Exception("ocp still not ok, check failed") + + def info(self, stdio=None): + resp = self._request('GET', '/api/v2/info', stdio=stdio) + if resp.code == 200: + return resp.content + else: + raise Exception("failed to query ocp info") + + def take_over_precheck(self, data, stdio=None): + resp = self._request('POST', '/api/v2/ob/clusters/takeOverPreCheck', data=data, stdio=stdio) + if resp.code == 200: + return resp.content + else: + raise Exception("takeover precheck failed") + def get_host_types(self, stdio=None): + resp = self._request('GET', '/api/v2/compute/hostTypes', stdio=stdio) + if resp.code == 200: + return resp.content + else: + raise Exception("failed to query host types from ocp") + + def create_host_type(self, data, stdio=None): + resp = self._request('POST', '/api/v2/compute/hostTypes', data=data, stdio=stdio) + if resp.code == 200: + return resp.content + else: + raise Exception("failed to create host types in ocp") + + def list_credentials(self, stdio=None): + resp = self._request('GET', '/api/v2/profiles/me/credentials', stdio=stdio) + if resp.code == 200: + return resp.content + else: + raise Exception("failed to query credentials from ocp") + + def create_credential(self, data, stdio=None): + resp = self._request('POST', '/api/v2/profiles/me/credentials', data=data, stdio=stdio) + if resp.code == 200: + return resp.content + else: + raise Exception("failed to create credentials in ocp") + + def take_over(self, data, stdio=None): + resp = self._request('POST', '/api/v2/ob/clusters/takeOver', data=data, stdio=stdio) + if resp.code == 200: + return resp.content + + def _request(self, method, api, data=None, retry=5, stdio=None): + url = self.base_url + api + headers = {"Content-Type": "application/json"} + try: + if data is not None: + data = json.dumps(data) + stdio.verbose('send http request method: {}, url: {}, data: {}'.format(method, url, data)) + resp = requests.request(method, url, data=data, verify=False, headers=headers, auth=self.auth) + return_code = resp.status_code + content = resp.content + except Exception as e: + if retry: + retry -= 1 + return self._request(method=method, api=api, data=data, retry=retry, stdio=stdio) + stdio.exception("") + return_code = 500 + content = str(e) + if return_code != 200: + stdio.verbose("request ocp-server failed: %s" % content) + try: + content = json.loads(content.decode()) + except: + pass + return self.Response(code=return_code, content=content) + +def takeover(plugin_context, *args, **kwargs): + # init variables, include get obcluster info from deploy config + cluster_config = plugin_context.cluster_config + clients = plugin_context.clients + options = plugin_context.options + stdio = plugin_context.stdio + stdio.verbose(vars(cluster_config)) + address = getattr(options, 'address', '') + user = getattr(options, 'user', '') + password = getattr(options, 'password', '') + host_type = getattr(options, 'host_type', '') + credential_name = getattr(options, 'credential_name', '') + ocp_cursor = OcpCursor(base_url=address, username=user, password=password) + if len(clients) == 0: + stdio.error("no available clients") + return plugin_context.return_false() + ssh_client = None + for ssh_client in clients.values(): + if ssh_client != None: + break + ssh_config = ssh_client.config + # query host types, add host type if current host_type is not empty and no matched record in ocp, otherwise use the first one + host_types = ocp_cursor.get_host_types(stdio=stdio)['data']['contents'] + host_type_id = None + if host_type == "": + if len(host_types) > 0: + host_type_id = host_types[0]['id'] + else: + for t in host_types: + if host_type == t['name']: + host_type_id = t['id'] + break + if host_type_id is None: + create_host_type_data = {'name': host_type if host_type is not None else str(uuid.uuid4()).split('-')[-1]} + host_type_id = ocp_cursor.create_host_type(create_host_type_data, stdio=stdio)['data']['id'] + # query credentials + credential_id = None + if credential_name != "": + credentials = ocp_cursor.list_credentials(stdio=stdio)['data']['contents'] + for credential in credentials: + if credential['targetType'] == "HOST" and credential['name'] == credential_name: + stdio.verbose("found credential with id %d", credential['id']) + credential_id = credential['id'] + break + if credential_id is None: + name = credential_name if credential_name != "" else str(uuid.uuid4()).split('-')[-1] + credential_type = "PRIVATE_KEY" + if ssh_config.password is not None and ssh_config.password != "": + credential_type = "PASSWORD" + pass_phrase = ssh_config.password + else: + key_file = ssh_config.key_filename if ssh_config.key_filename is not None else '{0}/.ssh/id_rsa'.format(os.path.expanduser("~")) + with open(key_file, 'r') as fd: + pass_phrase = fd.read() + create_credential_data = {"targetType":"HOST","name":name,"sshCredentialProperty":{"type":credential_type, "username":ssh_config.username,"passphrase":pass_phrase}} + credential_id = ocp_cursor.create_credential(create_credential_data, stdio=stdio)['data']['id'] + server = cluster_config.servers[0] + mysql_port = cluster_config.get_global_conf().get("mysql_port") + root_password = cluster_config.get_global_conf().get("root_password") + takeover_data = {"switchConfigUrl":True,"connectionMode":"direct","rootSysPassword":root_password,"address":server.ip,"port":mysql_port,"hostInfo":{"kind":"DEDICATED_PHYSICAL_MACHINE","hostTypeId":host_type_id,"sshPort":22,"credentialId":credential_id}} + proxyro_password = cluster_config.get_global_conf().get("proxyro_password") + if proxyro_password is not None and proxyro_password != "": + takeover_data.update({"proxyroPassword": proxyro_password}) + takeover_result = ocp_cursor.take_over(takeover_data, stdio=stdio) + stdio.verbose("takeover result %s" % takeover_result) + task_id = takeover_result['data']['id'] + cluster_id = takeover_result['data']['clusterId'] + return plugin_context.return_true(task_id=task_id, cluster_id = cluster_id) diff --git a/plugins/ocp-server/4.2.1/takeover_precheck.py b/plugins/ocp-server/4.2.1/takeover_precheck.py new file mode 100644 index 0000000..93e088c --- /dev/null +++ b/plugins/ocp-server/4.2.1/takeover_precheck.py @@ -0,0 +1,162 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2023 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + + +from __future__ import absolute_import, division, print_function + +import os +import re +import time +import json +import requests +from _rpm import Version +from copy import deepcopy +from requests.auth import HTTPBasicAuth + +from tool import Cursor, FileUtil, YamlLoader +from _errno import EC_OBSERVER_CAN_NOT_MIGRATE_IN + +class OcpCursor(object): + + class Response(object): + + def __init__(self, code, content): + self.code = code + self.content = content + + def __bool__(self): + return self.code == 200 + + def __init__(self, base_url="http://localhost:8080", username=None, password=None): + self.base_url = base_url.strip('/') + self.auth = None + self.username=username + self.password=password + if self.username: + self.auth = HTTPBasicAuth(username=username, password=password) + + def status(self, stdio=None): + resp = self._request('GET', '/api/v2/time', stdio=stdio) + ocp_status_ok = False + now = time.time() + check_wait_time = 180 + while time.time() - now < check_wait_time: + stdio.verbose("query ocp to check...") + try: + if resp.code == 200: + ocp_status_ok = True + break + except Exception: + stdio.verbose("ocp still not active") + time.sleep(5) + if ocp_status_ok: + stdio.verbose("check ocp server status ok") + return True + else: + stdio.verbose("ocp still not ok, check failed") + raise Exception("ocp still not ok, check failed") + + def info(self, stdio=None): + resp = self._request('GET', '/api/v2/info', stdio=stdio) + if resp.code == 200: + return resp.content + else: + raise Exception("failed to query ocp info") + + def take_over_precheck(self, data, stdio=None): + resp = self._request('POST', '/api/v2/ob/clusters/takeOverPreCheck', data=data, stdio=stdio) + if resp.code == 200: + return resp.content + else: + msg = resp.content['error']['message'] + raise Exception("takeover precheck failed %s" % msg) + + def compute_host_types(self, data, stdio=None): + resp = self._request('POST', '/api/v2/compute/hostTypes', data=data, stdio=stdio) + if resp.code == 200: + return resp.content + + def profiles_credentials(self, data, stdio=None): + resp = self._request('POST', '/api/v2/profiles/me/credentials', data=data, stdio=stdio) + if resp.code == 200: + return resp.content + + def take_over(self, data, stdio=None): + resp = self._request('POST', '/api/v2/ob/clusters/takeOver', data=data, stdio=stdio) + if resp.code == 200: + return resp.content + + def _request(self, method, api, data=None, retry=5, stdio=None): + url = self.base_url + api + headers = {"Content-Type": "application/json"} + try: + if data is not None: + data = json.dumps(data) + stdio.verbose('send http request method: {}, url: {}, data: {}'.format(method, url, data)) + resp = requests.request(method, url, data=data, verify=False, headers=headers, auth=self.auth) + return_code = resp.status_code + content = resp.content + except Exception as e: + if retry: + retry -= 1 + return self._request(method=method, api=api, data=data, retry=retry, stdio=stdio) + stdio.exception("") + return_code = 500 + content = str(e) + if return_code != 200: + stdio.verbose("request ocp-server failed: %s" % content) + try: + content = json.loads(content.decode()) + except: + pass + return self.Response(code=return_code, content=content) + +def takeover_precheck(plugin_context, *args, **kwargs): + # init variables, include get obcluster info from deploy config + cluster_config = plugin_context.cluster_config + clients = plugin_context.clients + options = plugin_context.options + stdio = plugin_context.stdio + stdio.verbose(vars(cluster_config)) + address = getattr(options, 'address', '') + user = getattr(options, 'user', '') + password = getattr(options, 'password', '') + ocp_cursor = OcpCursor(base_url=address, username=user, password=password) + ocp_info = ocp_cursor.info(stdio=stdio) + stdio.verbose("get ocp info %s", ocp_info) + ocp_version = Version(ocp_info['buildVersion'].split("_")[0]) + if ocp_version < Version("4.2.0"): + stdio.error("unable to export obcluster to ocp, ocp version must be at least 4.2.0") + return plugin_context.return_false(ocp_version=ocp_version) + server = cluster_config.servers[0] + mysql_port = cluster_config.get_global_conf().get("mysql_port") + root_password = cluster_config.get_global_conf().get("root_password") + if root_password is None or root_password == "": + stdio.error("unable to export obcluster to ocp, root password is empty") + return plugin_context.return_false(ocp_version=ocp_version) + precheck_data = {"connectionMode":"direct","address":server.ip,"port":mysql_port,"rootSysPassword":root_password} + proxyro_password = cluster_config.get_global_conf().get("proxyro_password") + if proxyro_password is not None and proxyro_password != "": + precheck_data.update({"proxyroPassword": proxyro_password}) + try: + precheck_result = ocp_cursor.take_over_precheck(precheck_data, stdio=stdio) + stdio.verbose("precheck result %s" % precheck_result) + except Exception as ex: + return plugin_context.return_false(exception=ex) + return plugin_context.return_true(ocp_version=ocp_version) diff --git a/plugins/ocp-server/4.2.1/upgrade.py b/plugins/ocp-server/4.2.1/upgrade.py new file mode 100644 index 0000000..de5c719 --- /dev/null +++ b/plugins/ocp-server/4.2.1/upgrade.py @@ -0,0 +1,78 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + + +from __future__ import absolute_import, division, print_function + + +def upgrade(plugin_context, search_py_script_plugin, apply_param_plugin, *args, **kwargs): + namespace = plugin_context.namespace + namespaces = plugin_context.namespaces + deploy_name = plugin_context.deploy_name + repositories = plugin_context.repositories + plugin_name = plugin_context.plugin_name + + components = plugin_context.components + clients = plugin_context.clients + cluster_config = plugin_context.cluster_config + cmds = plugin_context.cmds + options = plugin_context.options + dev_mode = plugin_context.dev_mode + stdio = plugin_context.stdio + upgrade_repositories = kwargs.get('upgrade_repositories') + sys_cursor = kwargs.get('sys_cursor') + metadb_cursor = kwargs.get('metadb_cursor') + + cur_repository = upgrade_repositories[0] + dest_repository = upgrade_repositories[-1] + repository_dir = dest_repository.repository_dir + kwargs['repository_dir'] = repository_dir + + stop_plugin = search_py_script_plugin([cur_repository], 'stop')[cur_repository] + init_plugin = search_py_script_plugin([dest_repository], 'init')[dest_repository] + start_plugin = search_py_script_plugin([dest_repository], 'start')[dest_repository] + connect_plugin = search_py_script_plugin([dest_repository], 'connect')[dest_repository] + display_plugin = search_py_script_plugin([dest_repository], 'display')[dest_repository] + + apply_param_plugin(cur_repository) + if not stop_plugin(namespace, namespaces, deploy_name, repositories, components, clients, cluster_config, cmds, options, stdio, *args, **kwargs): + return plugin_context.return_false() + + try: + servers = cluster_config.servers + for server in servers: + client = clients[server] + res = client.execute_command("sudo docker ps | grep ocp-all-in-one | awk '{print 1}'").stdout.strip() + client.execute_command('sudo docker stop %s' % res) + except: + pass + + apply_param_plugin(dest_repository) + if not init_plugin(namespace, namespaces, deploy_name, repositories, components, clients, cluster_config, cmds, options, stdio, upgrade=True, *args, **kwargs): + return plugin_context.return_false() + + if not start_plugin(namespace, namespaces, deploy_name, repositories, components, clients, cluster_config, cmds, options, stdio, sys_cursor1=sys_cursor, cursor=metadb_cursor, without_ocp_parameter=True, *args, **kwargs): + return plugin_context.return_false() + + ret = connect_plugin(namespace, namespaces, deploy_name, repositories, components, clients, cluster_config, cmds, options, stdio, *args, **kwargs) + if ret: + cursor = ret.get_return('cursor') + if display_plugin(namespace, namespaces, deploy_name, repositories, components, clients, cluster_config, cmds, options, stdio, cursor=cursor, *args, **kwargs): + return plugin_context.return_true() + return plugin_context.return_false() diff --git a/plugins/ocp-server/4.2.1/upgrade_check.py b/plugins/ocp-server/4.2.1/upgrade_check.py new file mode 100644 index 0000000..7189031 --- /dev/null +++ b/plugins/ocp-server/4.2.1/upgrade_check.py @@ -0,0 +1,134 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + + +from __future__ import absolute_import, division, print_function + +import re +import time + +import _errno as err +from _rpm import Version + + +def upgrade_check(plugin_context, meta_cursor, database='meta_database', init_check_status=False, *args, **kwargs): + def check_pass(item): + status = check_status[server] + if status[item].status == err.CheckStatus.WAIT: + status[item].status = err.CheckStatus.PASS + def check_fail(item, error, suggests=[]): + status = check_status[server][item] + status.error = error + status.suggests = suggests + status.status = err.CheckStatus.FAIL + def wait_2_pass(): + status = check_status[server] + for item in status: + check_pass(item) + def alert(item, error, suggests=[]): + global success + stdio.warn(error) + def error(item, _error, suggests=[]): + global success + success = False + check_fail(item, _error, suggests) + stdio.error(_error) + def critical(item, error, suggests=[]): + global success + success = False + check_fail(item, error, suggests) + stdio.error(error) + + + check_status = {} + repositories = plugin_context.repositories + options = plugin_context.options + stdio = plugin_context.stdio + clients = plugin_context.clients + cluster_config = plugin_context.cluster_config + plugin_context.set_variable('start_check_status', check_status) + + for server in cluster_config.servers: + check_status[server] = { + 'check_operation_task': err.CheckStatus(), + 'check_machine_status': err.CheckStatus(), + 'metadb_version': err.CheckStatus(), + 'java': err.CheckStatus(), + } + + if init_check_status: + return plugin_context.return_true(start_check_status=check_status) + + stdio.start_loading('Check before upgrade ocp-server') + success = True + + for server in cluster_config.servers: + client = clients[server] + server_config = cluster_config.get_server_conf_with_default(server) + try: + # java version check + java_bin = server_config.get('java_bin', '/usr/bin/java') + ret = client.execute_command('{} -version'.format(java_bin)) + if not ret: + critical('java', err.EC_OCP_EXPRESS_JAVA_NOT_FOUND.format(server=str(server)), [err.SUG_OCP_EXPRESS_INSTALL_JAVA_WITH_VERSION.format(version='1.8.0')]) + version_pattern = r'version\s+\"(\d+\.\d+\.\d+)(\_\d+)' + found = re.search(version_pattern, ret.stdout) or re.search(version_pattern, ret.stderr) + if not found: + error('java', err.EC_OCP_EXPRESS_JAVA_VERSION_ERROR.format(server=str(server), version='1.8.0'), [err.SUG_OCP_EXPRESS_INSTALL_JAVA_WITH_VERSION.format(version='1.8.0'),]) + java_major_version = found.group(1) + java_update_version = found.group(2)[1:] + if Version(java_major_version) != Version('1.8.0') and int(java_update_version) >= 161: + critical('java', err.EC_OCP_SERVER_JAVA_VERSION_ERROR.format(server=str(server), version='1.8.0'), [err.SUG_OCP_EXPRESS_INSTALL_JAVA_WITH_VERSION.format(version='1.8.0'),]) + check_pass('java') + except Exception as e: + stdio.error(e) + error('java', err.EC_OCP_EXPRESS_JAVA_VERSION_ERROR.format(server=str(server), version='1.8.0'), + [err.SUG_OCP_EXPRESS_INSTALL_JAVA_WITH_VERSION.format(version='1.8.0'), ]) + + sql = "select count(*) num from %s.task_instance where state not in ('FAILED', 'SUCCESSFUL');" % database + if meta_cursor.fetchone(sql)['num'] > 0: + success = False + error('check_operation_task', err.EC_OCP_SERVER_RUNNING_TASK) + else: + check_pass('check_operation_task') + + sql = "select count(*) num from %s.compute_host where status not in ('available', 'online');" % database + if meta_cursor.fetchone(sql)['num'] > 0: + success = False + error('check_machine_status', err.EC_OCP_SERVER_MACHINE_STATUS) + else: + check_pass('check_machine_status') + + sql = "select ob_version();" + v1 = meta_cursor.fetchone(sql)['ob_version()'] + if Version(v1) > Version('2.2.50'): + check_pass('metadb_version') + else: + success = False + error('metadb_version', err.EC_OCP_SERVER_METADB_VERSION) + + if success: + stdio.stop_loading('succeed') + return plugin_context.return_true() + else: + stdio.stop_loading('fail') + return plugin_context.return_false() + + + diff --git a/profile/obd.sh b/profile/obd.sh index 0612086..c208f29 100644 --- a/profile/obd.sh +++ b/profile/obd.sh @@ -70,7 +70,7 @@ function _obd_complete_func prev=${!#} all_cmds["obd"]="mirror cluster test update repo demo web obdiag display-trace" - all_cmds["obd cluster"]="autodeploy tenant start deploy redeploy restart reload destroy stop edit-config list display upgrade chst check4ocp reinstall" + all_cmds["obd cluster"]="autodeploy tenant start deploy redeploy restart reload destroy stop edit-config export-to-ocp list display upgrade chst check4ocp reinstall" all_cmds["obd cluster *"]="_obd_reply_deploy_names" all_cmds["obd cluster tenant"]="create drop show create-standby switchover failover decouple" all_cmds["obd cluster tenant *"]="_obd_reply_deploy_names" @@ -87,6 +87,9 @@ function _obd_complete_func all_cmds["obd repo"]="list" all_cmds["obd test"]="mysqltest sysbench tpch tpcc" all_cmds["obd test *"]="_obd_reply_deploy_names" + all_cmds["obd web *"]="install upgrade" + all_cmds["obd web install *"]="_obd_reply_deploy_names" + all_cmds["obd web upgrade *"]="_obd_reply_deploy_names" # if [ -f "$env_file" ] && [ "$(grep '"OBD_DEV_MODE": "1"' "$env_file")" != "" ]; then all_cmds["obd"]="${all_cmds[obd]} devmode env tool" @@ -97,9 +100,11 @@ function _obd_complete_func all_cmds["obd tool command"]="_obd_reply_deploy_names" all_cmds["obd tool command *"]="_obd_reply_tool_commands" all_cmds["obd env"]="set unset show clear" - all_cmds["obd obdiag"]="gather deploy" + all_cmds["obd obdiag"]="check gather deploy analyze" all_cmds["obd obdiag gather"]="all log clog slog obproxy_log perf plan_monitor stack sysstat" all_cmds["obd obdiag gather *"]="_obd_reply_deploy_names" + all_cmds["obd obdiag analyze"]="log" + all_cmds["obd obdiag check *"]="_obd_reply_deploy_names" # fi case $prev in list) @@ -140,4 +145,4 @@ function _obd_complete_func esac -} \ No newline at end of file +} diff --git a/rpm/ob-deploy.spec b/rpm/ob-deploy.spec index bcee280..2ae5d09 100644 --- a/rpm/ob-deploy.spec +++ b/rpm/ob-deploy.spec @@ -95,6 +95,7 @@ mkdir -p ${RPM_BUILD_ROOT}/usr/obd/lib/executer \cp -rf ${RPM_DIR}/executer27 ${RPM_BUILD_ROOT}/usr/obd/lib/executer/ \cp -rf $BUILD_DIR/SOURCES/example ${RPM_BUILD_ROOT}/usr/obd/ cd ${RPM_BUILD_ROOT}/usr/obd/plugins && ln -s oceanbase oceanbase-ce && \cp -rf obproxy/3.1.0 obproxy-ce/ && \cp -rf $SRC_DIR/plugins/obproxy-ce/* obproxy-ce/ +cd ${RPM_BUILD_ROOT}/usr/obd/plugins && ln -sf ocp-server ocp-server-ce mv obproxy/3.1.0 obproxy/3.2.1 cd ${RPM_BUILD_ROOT}/usr/obd/config_parser && ln -s oceanbase oceanbase-ce cd ${RPM_BUILD_ROOT}/usr/obd/optimize && ln -s obproxy obproxy-ce @@ -131,6 +132,38 @@ echo -e 'Installation of obd finished successfully\nPlease source /etc/profile.d #/sbin/chkconfig obd on %changelog +* Fri Nov 24 2023 obd 2.4.0 + - new features: support for graphical deployment of OCP-CE V4.2.1 + - new features: support for graphical deployment of OCP-CE V4.2.1 along with its MetaDB + - new features: support for command-line deployment of OCP-CE V4.2.1 along with its MetaDB + - new features: support for upgrading previous versions to OCP-CE V4.2.1 + - new features: compatibility updates for OBDiag V1.4.0 and V1.3.0 + - new features: compatibility with kylin OS + - enhancements: improved pre-launch checks for OceanBase databases + - improvements: enhanced error messaging during SQL execution and provide SQL execution Trace + - bug fixes: fixed an issue where deploying OceanBase V4.2.0 and above with local_ip would still perform NIC checks + - bug fixes: resolved a RuntimeError that could occur when destroying clusters deployed with OBD versions prior to V2.3.0 + - bug fixes: fixed an issue where edit-config could not exit after enabling IO_DEFAULT_CONFIRM +* Fri Oct 13 2023 obd 2.3.1 + - new features: adapt to OCP Express V4.2.1 + - bug fixes: fix checks during rolling upgrade that did not behave as expected under special circumstances + - bug fixes: resolve self-upgrade extraction failure of obd on el8 operating systems + - bug fixes: unexpected exceptions in obd cluster chst with ob-configserver component + - bug fixes: unexpected exceptions in ob-configserver when connection_url is not configured +* Fri Sep 15 2023 obd 2.3.0 + - new features: support for OceanBase 4.2 network-based primary/standby solution + - new features: support for ConfigServer + - new features: support for selecting units for capacity type parameters during web-based graphical deployment +* Wed Aug 02 2023 obd 2.2.0 + - new features: adapt to OceanBase-CE V4.2 + - new features: introduce 19G storage option for small-scale deployment with OceanBase-CE V4.2 + - new features: adapt to OCP Express V4.2 + - new features: web-based graphical deployment now allows for custom component selection + - optimization: improved OBProxy startup performance on machines with low specs + - change: redeploy now requires confirmation, can be bypassed with --confirm option + - change: automatic confirmation for all commands can be enabled with obd env set IO_DEFAULT_CONFIRM 1 + - fix bug: fixed the issue where OCP Express ocp_meta_tenant setting was not effective + - fix bug: fixed incorrect recognition of custom capacity type parameters in obd demo * Mon Jun 12 2023 obd 2.1.1 - new features: support upgrade keyword 'when_come_from' and 'deprecated' - fix bug: start server failed when other servers downtime #171 diff --git a/service/api/response_utils.py b/service/api/response_utils.py index 629bf41..5168f1f 100644 --- a/service/api/response_utils.py +++ b/service/api/response_utils.py @@ -51,6 +51,7 @@ def new_not_found_exception(ex): def new_internal_server_error_exception(ex): log.get_logger().error("got internal server error exception: {0}".format(traceback.format_exc())) + log.get_logger().error("Runing Exception: {}".format(ex)) raise HTTPException(HTTPStatus.INTERNAL_SERVER_ERROR, detail="internal server error, exception: {0}".format(ex)) diff --git a/service/api/v1/installer.py b/service/api/v1/installer.py new file mode 100644 index 0000000..1fa1a47 --- /dev/null +++ b/service/api/v1/installer.py @@ -0,0 +1,66 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . +from fastapi import APIRouter, Path +from fastapi import BackgroundTasks + +from _deploy import UserConfig +from service.api.response import OBResponse +from service.api.response_utils import new_internal_server_error_exception, new_ok_response +from service.model.server import UserInfo +from service.handler import handler_utils + + +router = APIRouter() + + +# @router.get("/upgrade/info/{cluster_name}", +# response_model=OBResponse[ServerInfo], +# description='get upgrade server info', +# operation_id='get_upgrade_server_info', +# tags=['Info']) +# async def get_server_info(cluster_name: str = Path(description="ocp cluster_name")): +# try: +# handler = handler_utils.new_server_info_handler() +# service_info = handler.get_upgrade_cluster_info(cluster_name) +# if service_info.metadb: +# service_info.metadb.password = '' +# except Exception as ex: +# return new_internal_server_error_exception(ex) +# return new_ok_response(service_info) + + +@router.post("/suicide", + response_model=OBResponse, + description='exit after a while', + operation_id='suicide', + tags=['Process']) +async def suicide(backgroundtasks: BackgroundTasks): + handler = handler_utils.new_common_handler() + backgroundtasks.add_task(handler.suicide) + return new_ok_response("suicide") + + +@router.get("/get/user", + response_model=OBResponse[UserInfo], + description='get system user', + operation_id='user', + tags=['User']) +async def get_user(): + username = UserConfig.DEFAULT.get('username') + return new_ok_response(UserInfo(username=username)) diff --git a/service/api/v1/metadb.py b/service/api/v1/metadb.py new file mode 100644 index 0000000..dace5d0 --- /dev/null +++ b/service/api/v1/metadb.py @@ -0,0 +1,62 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . +from fastapi import APIRouter, Path, Query, BackgroundTasks + +from service.api.response import OBResponse, DataList +from service.api import response_utils +from service.model.metadb import MetadbDeploymentInfo, MetadbDeploymentConfig, DatabaseConnection, RecoverChangeParameter +from service.model.resource import MetaDBResource, ResourceCheckResult +from service.model.task import TaskInfo, PrecheckTaskInfo, TaskLog +from service.handler.handler_utils import new_metadb_handler + +router = APIRouter() + + +@router.post("/metadb/connections", + response_model=OBResponse[DatabaseConnection], + description='create metadb connection', + operation_id='create_metadb_connection', + tags=['Metadb']) +async def create_metadb_connection( + sys: bool = Query(False, description='whether the incoming tenant is the sys tenant'), + metadb_connection: DatabaseConnection = ... + ): + handler = new_metadb_handler() + try: + connection_info = handler.create_connection_info(metadb_connection, sys) + return response_utils.new_ok_response(connection_info) + except Exception as e: + return response_utils.new_internal_server_error_exception(e) + + +@router.get("/metadb/connections/{cluster_name}", + response_model=OBResponse[DatabaseConnection], + description='get metadb connection', + operation_id='get_metadb_connection', + tags=['Metadb']) +async def get_metadb_connection(cluster_name: str = Path(description="cluster name")): + handler = new_metadb_handler() + connection_info = handler.get_connection_info(cluster_name) + if connection_info is None: + return response_utils.new_internal_server_error_exception(Exception("deployment {0} not found".format(id))) + else: + return response_utils.new_ok_response(connection_info) + + + diff --git a/service/api/v1/ocp_deployments.py b/service/api/v1/ocp_deployments.py new file mode 100644 index 0000000..3d0acbd --- /dev/null +++ b/service/api/v1/ocp_deployments.py @@ -0,0 +1,368 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . + +from fastapi import APIRouter, Path, Query, BackgroundTasks, Body + +from service.api.response import OBResponse, DataList +from service.handler import handler_utils +from service.model.deployments import OCPDeploymnetConfig, PreCheckResult, RecoverChangeParameter, TaskInfo, \ + ConnectionInfo, InstallLog, Deployment, DeploymentInfo, DeploymentReport, DeploymentStatus, UserCheck +from service.model.task import TaskInfo, PrecheckTaskInfo, TaskLog +from service.model.database import DatabaseConnection +from service.model.ocp import OcpInfo, OcpDeploymentInfo, OcpDeploymentConfig, OcpResource, OcpInstalledInfo, OcpUpgradeLostAddress +from service.model.metadb import RecoverChangeParameter +from service.api import response_utils + +router = APIRouter() + + +@router.get("/ocp/info/{id}", + response_model=OBResponse[OcpInstalledInfo], + description='get_installed_ocp_info', + operation_id='get_installed_ocp_info', + tags=['OCP']) +async def get_installed_ocp_info(id: int = Path(description="deployment id")): + ocp_handler = handler_utils.new_ocp_handler() + try: + info = ocp_handler.get_installed_ocp_info(id) + except Exception as ex: + return response_utils.new_internal_server_error_exception(ex) + return response_utils.new_ok_response(info) + + +@router.post("/ocp_deployments/{name}", + response_model=OBResponse, + description='create ocp deployment config', + operation_id='createOcpDeploymentConfig', + tags=['OCP']) +async def create_deployment(name: str = Path(description='name'), + config: OCPDeploymnetConfig = ...): + handler = handler_utils.new_ocp_handler() + cluster = None + try: + ocp_config_path = handler.create_ocp_config_path(config) + cluster = handler.create_ocp_deployment(name, ocp_config_path) + except Exception as ex: + return response_utils.new_internal_server_error_exception(ex) + if cluster: + return response_utils.new_ok_response(cluster) + else: + return response_utils.new_bad_request_exception(Exception('deployment {0} already exists'.format(name))) + + +@router.post("/machine/check/user", + response_model=OBResponse, + description='Check if the user input exists', + operation_id='machineUser', + tags=['OCP'] + ) +async def check_user(user: UserCheck = Body(description='server, port, username, password')): + handler = handler_utils.new_ocp_handler() + exist = None + try: + exist = handler.check_user(user) + except Exception as ex: + return response_utils.new_internal_server_error_exception(ex) + if exist: + return response_utils.new_ok_response(exist) + else: + return response_utils.new_bad_request_exception(Exception('user {0} user/password error'.format(user))) + + +@router.post("/ocp/deployments/{id}/precheck", + response_model=OBResponse[TaskInfo], + description='precheck for ocp deployment', + operation_id='precheck_ocp_deployment', + tags=['OCP']) +async def precheck_ocp_deployment(background_tasks: BackgroundTasks, + id: int = Path(description="deployment id")): + try: + handler = handler_utils.new_ocp_handler() + ret = handler.ocp_precheck(id, background_tasks) + if not isinstance(ret, TaskInfo) and ret: + return response_utils.new_internal_server_error_exception(str(ret[1].args[0])) + except Exception as ex: + return response_utils.new_internal_server_error_exception(ex) + return response_utils.new_ok_response(ret) + + +@router.get("/ocp/deployments/{id}/precheck/{task_id}", + response_model=OBResponse[PrecheckTaskInfo], + description='precheck for ocp deployment', + operation_id='precheck_ocp', + tags=['OCP']) +async def get_ocp_precheck_task(id: int = Path(description="deployment id"), + task_id: int = Path(description="task id")): + handler = handler_utils.new_ocp_handler() + try: + precheck_result = handler.get_precheck_result(id, task_id) + except Exception as ex: + return response_utils.new_internal_server_error_exception(ex) + return response_utils.new_ok_response(precheck_result) + + +@router.post("/ocp/deployments/{id}/recover", + response_model=OBResponse[DataList[RecoverChangeParameter]], + description='recover ocp deployment config', + operation_id='recover_ocp_deployment', + tags=['OCP']) +async def recover_ocp_deployment(id: int = Path(description="deployment id")): + handler = handler_utils.new_ocp_handler() + try: + recover_result = handler.recover(id) + return response_utils.new_ok_response(recover_result) + except Exception as ex: + return response_utils.new_internal_server_error_exception(ex) + + +@router.post("/ocp/deployments/{id}/install", + response_model=OBResponse[TaskInfo], + description='install ocp', + operation_id='install_ocp', + tags=['OCP']) +async def install_ocp(background_tasks: BackgroundTasks, id: int = Path(description="deployment id")): + handler = handler_utils.new_ocp_handler() + ret = handler.install(id, background_tasks) + if not isinstance(ret, TaskInfo) and ret: + return response_utils.new_internal_server_error_exception(ret[1]) + return response_utils.new_ok_response(ret) + + +@router.get("/ocp/deployments/{id}/install/{task_id}", + response_model=OBResponse[TaskInfo], + description='get ocp install task', + operation_id='get_ocp_install_task', + tags=['OCP']) +async def get_ocp_install_task(id: int = Path(description="deployment id"), + task_id: int = Path(description="task id")): + handler = handler_utils.new_ocp_handler() + task_info = handler.get_install_task_info(id, task_id) + if not isinstance(task_info, TaskInfo): + return response_utils.new_internal_server_error_exception("task {0} not found".format(id)) + return response_utils.new_ok_response(task_info) + + +@router.get("/ocp/deployments/{id}/install/{task_id}/log", + response_model=OBResponse[TaskLog], + description='get ocp install task log', + operation_id='get_ocp_install_task_log', + tags=['OCP']) +async def get_ocp_install_task_log(id: int = Path(description="deployment id"), + task_id: int = Path(description="task id"), + offset: int = Query(0, description="offset to read task log")): + handler = handler_utils.new_ocp_handler() + task_info = handler.get_install_task_info(id, task_id) + if task_info is None: + return response_utils.new_internal_server_error_exception("task {0} not found".format(id)) + log_content = handler.buffer.read() + # log_info = InstallLog(log=log_content[offset:], offset=len(log_content)) + return response_utils.new_ok_response(TaskLog(log=log_content, offset=offset)) + + +@router.post("/ocp/deployments/{id}/reinstall", + response_model=OBResponse[TaskInfo], + description='reinstall ocp', + operation_id='reinstall_ocp', + tags=['OCP']) +async def reinstall_ocp(background_tasks: BackgroundTasks, id: int = Path(description="deployment id")): + handler = handler_utils.new_ocp_handler() + ret = handler.reinstall(id, background_tasks) + if not isinstance(ret, TaskInfo) and ret: + return response_utils.new_internal_server_error_exception(ret[1]) + return response_utils.new_ok_response(ret) + + +@router.get("/ocp/deployments/{id}/reinstall/{task_id}", + response_model=OBResponse[TaskInfo], + description='get ocp reinstall task', + operation_id='get_ocp_reinstall_task', + tags=['OCP']) +async def get_ocp_reinstall_task(id: int = Path(description="deployment id"), + task_id: int = Path(description="task id")): + handler = handler_utils.new_ocp_handler() + task_info = handler.get_reinstall_task_info(id, task_id) + if not isinstance(task_info, TaskInfo): + return response_utils.new_internal_server_error_exception("task {0} not found".format(id)) + return response_utils.new_ok_response(task_info) + + +@router.get("/ocp/deployments/{id}/reinstall/{task_id}/log", + response_model=OBResponse[TaskLog], + description='get ocp reinstall task log', + operation_id='get_ocp_reinstall_task_log', + tags=['OCP']) +async def get_ocp_reinstall_task_log(id: int = Path(description="deployment id"), + task_id: int = Path(description="task id"), + offset: int = Query(0, description="offset to read task log")): + handler = handler_utils.new_ocp_handler() + task_info = handler.get_reinstall_task_info(id, task_id) + if task_info is None: + return response_utils.new_internal_server_error_exception("task {0} not found".format(id)) + log_content = handler.buffer.read() + # log_info = InstallLog(log=log_content[offset:], offset=len(log_content)) + return response_utils.new_ok_response(TaskLog(log=log_content, offset=offset)) + + +@router.delete("/ocp/deployments/{id}", + response_model=OBResponse[TaskInfo], + description='destroy ocp', + operation_id='destroy_ocp', + tags=['OCP']) +async def destroy_ocp(id: int, background_tasks: BackgroundTasks): + handler = handler_utils.new_ocp_handler() + try: + info = handler.destroy(id, background_tasks) + except Exception as ex: + raise response_utils.new_internal_server_error_exception(ex) + return response_utils.new_ok_response(info) + + +@router.get("/ocp/deployments/{id}/destroy/{task_id}", + response_model=OBResponse[TaskInfo], + description='get ocp destroy task', + operation_id='get_ocp_destroy_task', + tags=['OCP']) +async def get_ocp_destroy_task(background_tasks: BackgroundTasks, + id: int = Path(description="deployment id"), + task_id: int = Path(description="task id")): + handler = handler_utils.new_ocp_handler() + info = handler.get_destroy_task_info(id, task_id) + if not isinstance(info, TaskInfo): + return response_utils.new_internal_server_error_exception(info[1]) + return response_utils.new_ok_response(info) + + +@router.post("/ocp", + response_model=OBResponse[OcpInfo], + description='create ocp info', + operation_id='create_ocp_info', + tags=['OCP']) +async def create_ocp_info(metadb: DatabaseConnection = ...): + ocp_handler = handler_utils.new_ocp_handler() + try: + data = ocp_handler.create_ocp_info(metadb) + except Exception as ex: + return response_utils.new_internal_server_error_exception(ex) + return response_utils.new_ok_response(data) + + +@router.get("/ocp/{cluster_name}", + response_model=OBResponse[OcpInfo], + description='get ocp info', + operation_id='get_ocp_info', + tags=['OCP']) +async def get_ocp_info(cluster_name: str = Path(description="ocp cluster_name")): + ocp_handler = handler_utils.new_ocp_handler() + try: + data = ocp_handler.get_ocp_info(cluster_name) + except Exception as ex: + return response_utils.new_internal_server_error_exception(ex) + return response_utils.new_ok_response(data) + + +@router.post("/ocp/{cluster_name}/upgrade/precheck", + response_model=OBResponse[TaskInfo], + description='post precheck for ocp upgrade', + operation_id='precheck_ocp_upgrade', + tags=['OCP']) +async def precheck_ocp_upgrade(background_tasks: BackgroundTasks, + cluster_name: str = Path(description="deployment cluster_name")): + handler = handler_utils.new_ocp_handler() + ret = handler.upgrade_precheck(cluster_name, background_tasks) + if not isinstance(ret, TaskInfo) and ret: + return response_utils.new_internal_server_error_exception(ret[1]) + return response_utils.new_ok_response(ret) + + +@router.get("/ocp/{cluster_name}/upgrade/precheck/{task_id}", + response_model=OBResponse[PrecheckTaskInfo], + description='get precheck for ocp upgrade', + operation_id='get_ocp_upgrade_precheck_task', + tags=['OCP']) +async def get_ocp_upgrade_precheck_task(cluster_name: str = Path(description="ocp cluster_name"), + task_id: int = Path(description="task id")): + handler = handler_utils.new_ocp_handler() + try: + precheck_result = handler.get_upgrade_precheck_result(cluster_name, task_id) + except Exception as ex: + return response_utils.new_internal_server_error_exception(ex) + return response_utils.new_ok_response(precheck_result) + + +@router.post("/ocp/{cluster_name}/upgrade", + response_model=OBResponse[TaskInfo], + description='upgrade ocp', + operation_id='upgrade_ocp', + tags=['OCP']) +async def upgrade_ocp( + background_tasks: BackgroundTasks, + cluster_name: str = Path(description="ocp cluster_name"), + version: str = Query(description="ocp upgrade version"), + usable: str = Query('', description="ocp upgrade hash") +): + handler = handler_utils.new_ocp_handler() + ret = handler.upgrade_ocp(cluster_name, version, usable, background_tasks) + if not isinstance(ret, TaskInfo) and ret: + return response_utils.new_internal_server_error_exception(ret[1]) + return response_utils.new_ok_response(ret) + + +@router.get("/ocp/{cluster_name}/upgrade/{task_id}", + response_model=OBResponse[TaskInfo], + description='get ocp upgrade task', + operation_id='get_ocp_upgrade_task', + tags=['OCP']) +async def get_ocp_upgrade_task(cluster_name: str = Path(description="ocp cluster_name"), + task_id: int = Path(description="task id")): + handler = handler_utils.new_ocp_handler() + task_info = handler.get_ocp_upgrade_task(cluster_name, task_id) + if not isinstance(task_info, TaskInfo): + return response_utils.new_internal_server_error_exception("task {0} not found".format(cluster_name)) + return response_utils.new_ok_response(task_info) + + +@router.get("/ocp/{cluster_name}/upgrade/{task_id}/log", + response_model=OBResponse[TaskLog], + description='get ocp upgrade task log', + operation_id='get_ocp_upgrade_task_log', + tags=['OCP']) +async def get_ocp_upgrade_task_log(cluster_name: str = Path(description="ocp cluster_name"), + task_id: int = Path(description="task id"), + offset: int = Query(0, description="offset to read task log")): + handler = handler_utils.new_ocp_handler() + task_info = handler.get_ocp_upgrade_task(cluster_name, task_id) + if task_info is None: + return response_utils.new_internal_server_error_exception("task {0} not found".format(cluster_name)) + log_content = handler.buffer.read() + # log_info = InstallLog(log=log_content[offset:], offset=len(log_content)) + return response_utils.new_ok_response(TaskLog(log=log_content, offset=offset)) + + +@router.get("/ocp/upgraade/agent/hosts", + response_model=OBResponse[OcpUpgradeLostAddress], + description='get ocp not upgrading host', + operation_id='get_ocp_not_upgrading_host', + tags=['OCP']) +async def get_ocp_upgrade_task_log(): + handler = handler_utils.new_ocp_handler() + try: + ret = handler.get_not_upgrade_host() + except Exception as ex: + return response_utils.new_internal_server_error_exception(ex) + return response_utils.new_ok_response(ret) \ No newline at end of file diff --git a/service/api/v1/service_info.py b/service/api/v1/service_info.py index 0ffe200..2468328 100644 --- a/service/api/v1/service_info.py +++ b/service/api/v1/service_info.py @@ -17,12 +17,14 @@ # You should have received a copy of the GNU General Public License # along with OceanBase Deploy. If not, see . -from fastapi import APIRouter +from fastapi import APIRouter, Query, Body from service.api import response_utils from service.api.response import OBResponse from service.handler import handler_utils -from service.model.service_info import ServiceInfo +from service.model.service_info import ServiceInfo, DeployName +from service.model.database import DatabaseConnection +from service.model.server import OcpServerInfo router = APIRouter() @@ -36,3 +38,58 @@ async def get_info(): handler = handler_utils.new_service_info_handler() service_info = handler.get_service_info() return response_utils.new_ok_response(service_info) + + +@router.get("/deployment/names", + response_model=OBResponse[DeployName], + description='get deployment names', + operation_id='getDeploymentNames', + tags=['Info']) +async def get_deployment_names(): + try: + handler = handler_utils.new_service_info_handler() + deploy_names = handler.get_deployments_name() + return response_utils.new_ok_response(deploy_names) + except Exception as ex: + return response_utils.new_internal_server_error_exception(ex) + + +@router.get("/deployment/metadb/connection", + response_model=OBResponse[DatabaseConnection], + description='get connection info', + operation_id='getConnectionInfo', + tags=['Info']) +async def get_metadb_connection(name: str = Query(..., description='cluster name')): + try: + handler = handler_utils.new_service_info_handler() + metadb = handler.get_metadb_connection(name) + return response_utils.new_ok_response(metadb) + except Exception as ex: + return response_utils.new_internal_server_error_exception(ex) + +@router.post("/deployment/ocp/agent/ip", + response_model=OBResponse[OcpServerInfo], + description='get ocp server info', + operation_id='getOcpServerInfo', + tags=['Info']) +async def post_metadb_connection(metadb: DatabaseConnection = Body(..., description='cluster name')): + try: + handler = handler_utils.new_service_info_handler() + metadb = handler.get_component_agent(metadb) + return response_utils.new_ok_response(metadb) + except Exception as ex: + return response_utils.new_internal_server_error_exception(ex) + + +@router.post("/deployment/upgrade/ocp", + response_model=OBResponse, + description='get obd info', + operation_id='create ocp deployment', + tags=['Info']) +async def create_ocp_deployment(name: str = Query(..., description='cluster name')): + try: + handler = handler_utils.new_service_info_handler() + metadb = handler.create_ocp_info(name) + return response_utils.new_ok_response(metadb) + except Exception as ex: + return response_utils.new_internal_server_error_exception(ex) \ No newline at end of file diff --git a/service/app.py b/service/app.py index 1f075de..368f556 100644 --- a/service/app.py +++ b/service/app.py @@ -22,6 +22,7 @@ import uvicorn from fastapi import FastAPI from fastapi.middleware.gzip import GZipMiddleware +from fastapi.middleware.cors import CORSMiddleware from starlette.staticfiles import StaticFiles from starlette_prometheus import metrics, PrometheusMiddleware @@ -33,12 +34,17 @@ from service.middleware.request_response_log import RequestResponseLogMiddleware from service.middleware.process_time import ProcessTimeMiddleware from service.handler import handler_utils +from service.middleware.ip_white import IPBlockMiddleware +from service.api.v1 import ocp_deployments +from service.api.v1 import metadb +from service.api.v1 import installer + app = FastAPI() class OBDWeb(object): - def __init__(self, obd, resource_path): + def __init__(self, obd, white_ip_list=None, resource_path="./"): CoreManager.INSTANCE = obd self.app = app self.app.add_route("/metrics", metrics) @@ -47,6 +53,10 @@ def __init__(self, obd, resource_path): self.app.include_router(common.router, prefix='/api/v1') self.app.include_router(service_info.router, prefix='/api/v1') self.app.include_router(mirror.router, prefix='/api/v1') + self.app.include_router(ocp_deployments.router, prefix='/api/v1') + self.app.include_router(metadb.router, prefix='/api/v1') + self.app.include_router(installer.router, prefix='/api/v1') + self.app.add_middleware(IPBlockMiddleware, ips=white_ip_list) self.app.add_middleware(ProcessTimeMiddleware) self.app.add_middleware(RequestResponseLogMiddleware, logger=log.get_logger()) self.app.add_middleware(PrometheusMiddleware) diff --git a/service/common/const.py b/service/common/const.py index 43b5478..7c8d150 100644 --- a/service/common/const.py +++ b/service/common/const.py @@ -39,12 +39,15 @@ OBPROXY = 'obproxy' OCP_EXPRESS = 'ocpexpress' +OCP_SERVER_CE = 'ocp-server-ce' +OCP_SERVER = 'ocp-server' OBAGENT = 'obagent' DESTROY_PLUGIN = "destroy" INIT_PLUGINS = ("init",) START_PLUGINS = ("start_check", "start", "connect", "bootstrap", "display") +UPGRADE_PLUGINS = ("upgrade") # filter component of oceanbase and obproxy version above 4.0 VERSION_FILTER = { OCEANBASE: "4.0.0.0", diff --git a/service/common/core.py b/service/common/core.py index e94f8c9..1fb008c 100644 --- a/service/common/core.py +++ b/service/common/core.py @@ -17,7 +17,6 @@ # You should have received a copy of the GNU General Public License # along with OceanBase Deploy. If not, see . from collections import defaultdict - from singleton_decorator import singleton from _stdio import BufferIO diff --git a/service/common/task.py b/service/common/task.py index a22968f..87260f7 100644 --- a/service/common/task.py +++ b/service/common/task.py @@ -137,10 +137,14 @@ def __init__(self, task_type=DEFAULT_TASK_TYPE): def __call__(self, func): @functools.wraps(func) def wrapper(*args, **kwargs): + ret = None self.lock.acquire() try: - func(*args, **kwargs) + ret = func(*args, **kwargs) + except Exception as ex: + ret = False, ex finally: self.lock.release() + return ret return wrapper diff --git a/service/handler/base_handler.py b/service/handler/base_handler.py index 56993a5..671674b 100644 --- a/service/handler/base_handler.py +++ b/service/handler/base_handler.py @@ -17,12 +17,11 @@ # You should have received a copy of the GNU General Public License # along with OceanBase Deploy. If not, see . -from collections import defaultdict - -from _plugin import PluginContextNamespace from service.common import core SPACENAME = "API" + + class BaseHandler(object): def __init__(self): self._obd = core.CoreManager().get_obd() diff --git a/service/handler/component_handler.py b/service/handler/component_handler.py index 405e240..b3c834c 100644 --- a/service/handler/component_handler.py +++ b/service/handler/component_handler.py @@ -109,6 +109,10 @@ def list_components(self): componentInfo.version_type = const.CE for componentInfo in component_dict[const.OBPROXY]: componentInfo.version_type = const.BUSINESS + for componentInfo in component_dict[const.OCP_SERVER_CE]: + componentInfo.version_type = const.CE + for componentInfo in component_dict[const.OCP_SERVER]: + componentInfo.version_type = const.BUSINESS if const.OCEANBASE in component_dict.keys() and const.OCEANBASE_CE in component_dict.keys(): component_dict[const.OCEANBASE].extend(component_dict[const.OCEANBASE_CE]) @@ -124,6 +128,13 @@ def list_components(self): elif const.OBPROXY_CE in component_dict.keys(): component_dict[const.OBPROXY] = component_dict[const.OBPROXY_CE] component_dict.pop(const.OBPROXY_CE) + if const.OCP_SERVER in component_dict.keys() and const.OCP_SERVER_CE in component_dict.keys(): + component_dict[const.OCP_SERVER].extend(component_dict[const.OCP_SERVER_CE]) + component_dict.pop(const.OCP_SERVER_CE) + component_dict[const.OCP_SERVER].sort(key=lambda x: x.version, reverse=True) + elif const.OCP_SERVER_CE in component_dict.keys(): + component_dict[const.OCP_SERVER] = component_dict[const.OCP_SERVER_CE] + component_dict.pop(const.OCP_SERVER_CE) for name, info in component_dict.items(): component_list.append(Component(name=name, info=info)) return component_list diff --git a/service/handler/handler_utils.py b/service/handler/handler_utils.py index b3bc5e9..d8f2cc1 100644 --- a/service/handler/handler_utils.py +++ b/service/handler/handler_utils.py @@ -22,6 +22,8 @@ from service.handler.service_info_handler import ServiceInfoHandler from service.handler.comment_handler import CommonHandler from service.handler.mirror_handler import MirrorHandler +from service.handler.ocp_handler import OcpHandler +from service.handler.metadb_handler import MetadbHandler def new_component_handler(): @@ -42,3 +44,15 @@ def new_service_info_handler(): def new_mirror_handler(): return MirrorHandler() + + +def new_ocp_handler(): + return OcpHandler() + + +def new_metadb_handler(): + return MetadbHandler() + + +def new_server_info_handler(): + return ServiceInfoHandler() diff --git a/service/handler/metadb_handler.py b/service/handler/metadb_handler.py new file mode 100644 index 0000000..aa943ec --- /dev/null +++ b/service/handler/metadb_handler.py @@ -0,0 +1,907 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . +import copy +import yaml +import tempfile +from collections import defaultdict +from optparse import Values +from singleton_decorator import singleton + +from service.handler.base_handler import BaseHandler +from service.common import log, task, util, const +from service.common.task import Serial as serial +from service.common.task import AutoRegister as auto_register +from service.model.ssh import SshAuthMethod +from service.model.metadb import MetadbDeploymentInfo, RecoverChangeParameter, MetadbDeploymentConfig, Flag +from service.model.deployments import OCPDeploymentStatus +from service.model.parameter import Parameter +from service.model.resource import DiskInfo, Disk, MetaDBResource, ResourceCheckResult +from service.model.database import DatabaseConnection +from service.model.task import TaskStatus, TaskResult, TaskInfo, PreCheckResult, PrecheckTaskInfo, PrecheckEventResult, TaskStepInfo +from _deploy import DeployStatus, DeployConfigStatus +from _errno import CheckStatus, FixEval +from tool import Cursor + + +@singleton +class MetadbHandler(BaseHandler): + + def generate_metadb_config_path(self, config): + cluster_config = {} + + if config is not None: + self.generate_metadb_config(cluster_config, config) + if config.auth is not None: + self.generate_auth_config(cluster_config, config.auth) + + with tempfile.NamedTemporaryFile(delete=False, prefix="ocp", suffix=".yaml", mode="w", encoding="utf-8") as f: + f.write(yaml.dump(cluster_config, sort_keys=False)) + cluster_config_yaml_path = f.name + log.get_logger().info('dump metadb config from path: %s' % cluster_config_yaml_path) + self.context['id'] = self.context['id'] + 1 if self.context['id'] else 1 + self.context['deployment_info'][self.context['id']] = {'status': OCPDeploymentStatus.INIT.value, 'config': config, 'connection': None} + self.context['meta_path'] = cluster_config_yaml_path + return cluster_config_yaml_path + + def generate_auth_config(self, cluster_config, auth): + if 'user' not in cluster_config.keys(): + cluster_config['user'] = {} + cluster_config['user']['username'] = auth.user + cluster_config['user']['password'] = auth.password + cluster_config['user']['private_key'] = '' if auth.auth_method == SshAuthMethod.PASSWORD else auth.private_key + cluster_config['user']['port'] = auth.port + + def generate_metadb_config(self, cluster_config, config): + log.get_logger().debug('generate metadb config') + oceanbase_config = dict() + config_dict = config.dict() + + if config_dict.get('servers'): + oceanbase_config['servers'] = config.servers + + if 'global' not in oceanbase_config.keys(): + oceanbase_config['global'] = {} + + for key in config_dict: + if config_dict[key] and key in {'sql_port', 'rpc_port', 'home_path', 'data_dir', 'log_dir', 'appname', + 'root_password', 'devname'}: + if key == 'sql_port': + oceanbase_config['global']['mysql_port'] = config_dict[key] + continue + if key == 'data_dir': + oceanbase_config['global']['data_dir'] = config_dict[key] + continue + if key == 'log_dir': + oceanbase_config['global']['redo_dir'] = config_dict[key] + continue + oceanbase_config['global'][key] = config_dict[key] + + if config.home_path == '': + oceanbase_config['global']['home_path'] = config.home_path + '/oceanbase' + + if config.parameters: + for parameter in config.parameters: + oceanbase_config['global'][parameter.name] = parameter.value + cluster_config[const.OCEANBASE_CE] = oceanbase_config + + def create_deployment(self, name: str, config_path: str): + log.get_logger().info('in deploy metadb stage') + deploy = self.obd.deploy_manager.get_deploy_config(name) + if deploy: + deploy_info = deploy.deploy_info + if deploy_info.status == DeployStatus.STATUS_DEPLOYED: + self.destroy_name(name, deploy) + deploy = self.obd.deploy_manager.get_deploy_config(name) + deploy_info = deploy.deploy_info + if deploy_info.status not in [DeployStatus.STATUS_CONFIGURED, DeployStatus.STATUS_DESTROYED]: + log.get_logger().error('Deploy "%s" is %s. You could not deploy an %s cluster.' % ( + name, deploy_info.status.value, deploy_info.status.value)) + raise Exception('Deploy "%s" is %s. You could not deploy an %s cluster.' % ( + name, deploy_info.status.value, deploy_info.status.value)) + if deploy_info.config_status != DeployConfigStatus.UNCHNAGE: + log.get_logger().info('Apply temp deploy configuration') + if not deploy.apply_temp_deploy_config(): + log.get_logger().error('Failed to apply new deploy configuration') + raise Exception('Failed to apply new deploy configuration') + + deploy = self.obd.deploy_manager.create_deploy_config(name, config_path) + if not deploy: + log.get_logger().error('Failed to create deploy: %s. please check you configuration file' % name) + raise Exception('Failed to create deploy: %s. please check you configuration file' % name) + self.obd.set_deploy(deploy) + log.get_logger().info('cluster config path: %s ' % config_path) + self.context['deployment_id'][self.context['id']] = name + return self.context['id'] + + def generate_secure_metadb_deployment(self, metadb_deployment): + metadb_deployment_copy = copy.deepcopy(metadb_deployment) + metadb_deployment_copy.root_password = '' + if metadb_deployment_copy.auth: + metadb_deployment_copy.auth.password = '' + return metadb_deployment_copy + + def destroy_name(self, name, deploy): + self.obd.set_options(Values({'force_kill': True})) + log.get_logger().info('start destroy %s' % name) + if self.obd.repositories: + repositories = [repository for repository in self.obd.repositories if repository.name == 'oceanbase-ce'] + self.obd.set_repositories(repositories) + self.obd._destroy_cluster(self.obd.deploy, repositories) + else: + self.obd.destroy_cluster(name) + log.get_logger().info('destroy %s end' % name) + deploy.update_deploy_status(DeployStatus.STATUS_CONFIGURED) + + def list_metadb_deployments(self): + data = [] + for id, deployment_info in self.context['deployment_info'].items(): + if deployment_info: + meta_deployment_info = MetadbDeploymentInfo() + meta_deployment_info.id = id + meta_deployment_info.status = deployment_info['status'] + deployment_info['config'].root_password = '' + if deployment_info['config'].auth: + deployment_info['config'].auth.password = '' + meta_deployment_info.config = deployment_info['config'] + meta_deployment_info.connection = deployment_info['connection'] + data.append(meta_deployment_info) + return data + + def get_server_disk_info(self, client, paths, data): + for path in paths: + for _ in client.execute_command( + "df --block-size=1g %s | awk '{if(NR>1)print}'" % path).stdout.strip().split('\n'): + _ = [i for i in _.split(' ') if i != ''] + dev = _[0] + mount_path = _[5] + total_size = _[1] + free_size = _[3] + _disk_info = DiskInfo(dev=dev, mount_path=mount_path, total_size=total_size, free_size=free_size) + data.append(Disk(path=path, disk_info=_disk_info)) + return data + + def get_server_memory_info(self, client, resource_check_results, address): + memory_free = client.execute_command( + "cat /proc/meminfo|grep MemFree|cut -f2 -d:|uniq | awk '{print $1}'").stdout.strip() + memory_higher_limit = int(int(memory_free) / 1024 / 1024) + memory_default = max(int(int(int(memory_free) / 1024 / 1024) * 0.7), 6) + memory_lower_limit = 6 + + if memory_higher_limit < memory_lower_limit: + resource_check_results.append(ResourceCheckResult( + address=address, name='memory_limit', check_result=False, + error_message=[f'{address}: memory is not enough']) + ) + return memory_higher_limit, memory_default, memory_lower_limit + + def check_dir_empty(self, client, paths, address, resource_check_results, user): + def check_directory(client, path, path_name): + check_result = ResourceCheckResult(address=address, name=path_name) + ret = client.execute_command(f'ls {path}') + if not ret or ret.stdout.strip(): + check_result.check_result = False + check_result.error_message.append(f'{address}: {path} is not empty') + return check_result + + for path in paths: + if not client.execute_command('mkdir -p %s' % path): + raise Exception('%s@%s: dir Permission denied' % (user, address)) + resource_check_results.append(check_directory(client, paths[0], 'home_path')) + resource_check_results.append(check_directory(client, paths[1], 'data_dir')) + resource_check_results.append(check_directory(client, paths[2], 'log_diir')) + return resource_check_results + + def cal_cluster_resource(self, resource_check_results, address, paths, data): + flag = Flag.not_matched.value + data_size_default = 10 + log_size_default = 20 + if data[0].disk_info.mount_path == data[1].disk_info.mount_path == data[2].disk_info.mount_path: + data_size_default = int((int(data[0].disk_info.free_size) - 20) * 0.6) + log_size_default = int((int(data[0].disk_info.free_size) - 20) * 0.4) + flag = Flag.same_disk.value + elif data[1].disk_info.mount_path == data[2].disk_info.mount_path: + data_size_default = int((int(data[1].disk_info.free_size) - 20) * 0.6) + log_size_default = int((int(data[2].disk_info.free_size) - 20) * 0.4) + flag = Flag.data_and_log_same_disk.value + elif data[0].disk_info.mount_path == data[1].disk_info.mount_path or data[0].disk_info.mount_path == data[ + 2].disk_info.mount_path: + data_size_default = int(data[1].disk_info.free_size) - 20 + log_size_default = int(data[2].disk_info.free_size) - 20 + flag = Flag.home_data_or_home_log_same_disk.value + elif data[1].disk_info.mount_path != data[2].disk_info.mount_path: + data_size_default = int(int(data[1].disk_info.free_size) * 0.9) + log_size_default = int(int(data[2].disk_info.free_size) * 0.9) + flag = Flag.data_log_different_disk.value + + if data_size_default > int(data[1].disk_info.free_size) or data_size_default < 1: + resource_check_results[-2].check_result = False + resource_check_results[-2].error_message.append(f'{address}:{paths[1]} disk resource is not enough') + + if log_size_default > int(data[2].disk_info.free_size) or log_size_default < 20: + resource_check_results[-1].check_result = False + resource_check_results[-1].error_message.append(f'{address}:{paths[2]} disk resource is not enough') + return data_size_default, log_size_default, flag + + def check_machine_resource(self, id): + if id not in self.context['deployment_id']: + raise Exception(f'no such deployment for id {id}') + deploy = self.obd.deploy + if not deploy: + raise Exception("no such deploy for name:{0}".format(self.context['deployment_id'][id])) + deploy_config = deploy.deploy_config + pkgs, repositories, errors = self.obd.search_components_from_mirrors(deploy_config, only_info=True) + if errors: + raise Exception("{}".format('\n'.join(errors))) + self.obd.search_param_plugin_and_apply(repositories, deploy_config) + self.obd.set_repositories(repositories) + + install_plugins = self.obd.get_install_plugin_and_install(repositories, pkgs) + + ssh_clients, connect_status = self.obd.get_clients_with_connect_status(deploy_config, repositories) + + config = self.context['deployment_info'][id]['config'] + paths = [config.home_path, config.data_dir, config.log_dir] + + resource_check_results = [] + data = [] + metadb_resource = [] + for server in ssh_clients: + client = ssh_clients[server] + address = server.ip + + self.check_dir_empty(client, paths, address, resource_check_results, config.auth.user) + self.get_server_disk_info(client, paths, data) + data_size_default, log_size_default, flag = self.cal_cluster_resource(paths, address, resource_check_results, data) + memory_higher_limit, memory_default, memory_lower_limit = self.get_server_memory_info(client, address, resource_check_results) + metadb_resource.append(MetaDBResource( + address=address, disk=data, memory_limit_lower_limit=memory_lower_limit, + memory_limit_higher_limit=memory_higher_limit, data_size_default=data_size_default, + memory_limit_default=memory_default, log_size_default=log_size_default, flag=flag + )) + self.context[id]['metadb_resource'] = metadb_resource + return resource_check_results + + def get_machine_resource(self, id): + if self.context[id]['metadb_resource']: + return self.context[id]['metadb_resource'] + self.check_machine_resource(id) + return self.context[id]['metadb_resource'] if self.context[id]['metadb_resource'] else [] + + @serial("precheck") + def precheck(self, id, background_tasks): + task_manager = task.get_task_manager() + cluster_name = self.context['deployment_id'][id] + if not cluster_name: + raise Exception(f"no such deploy for id: {id}") + task_info = task_manager.get_task_info(cluster_name, task_type="precheck") + if task_info is not None and task_info.status != TaskStatus.FINISHED: + raise Exception(f"task {cluster_name} exists and not finished") + deploy = self.obd.deploy + if not deploy: + raise Exception(f"no such deploy: {cluster_name}") + deploy_config = deploy.deploy_config + pkgs, repositories, errors = self.obd.search_components_from_mirrors(deploy_config, only_info=True) + if errors: + raise Exception("{}".format('\n'.join(errors))) + repositories.extend(pkgs) + repositories = self.obd.sort_repository_by_depend(repositories, deploy_config) + for repository in repositories: + real_servers = set() + cluster_config = deploy_config.components[repository.name] + for server in cluster_config.servers: + if server.ip in real_servers: + raise Exception( + "Deploying multiple {} instances on the same server is not supported.'".format(repository.name)) + real_servers.add(server.ip) + self.obd.search_param_plugin_and_apply(repositories, deploy_config) + self.obd.set_repositories(repositories) + + start_check_plugins = self.obd.search_py_script_plugin(repositories, 'start_check', no_found_act='warn') + + self._precheck(cluster_name, repositories, start_check_plugins, init_check_status=True) + info = task_manager.get_task_info(cluster_name, task_type="precheck") + if info is not None and info.exception is not None: + exception = copy.deepcopy(info.exception) + info.exception = None + raise exception + task_manager.del_task_info(cluster_name, task_type="precheck") + background_tasks.add_task(self._precheck, cluster_name, repositories, start_check_plugins, init_check_status=False) + self.context['deployment']['task_id'] = self.context['deployment']['task_id'] + 1 if self.context['deployment']['task_id'] else 1 + task_status = TaskStatus.RUNNING.value + task_res = TaskResult.RUNNING.value + task_message = 'precheck' + ret = TaskInfo(id=self.context['deployment']['task_id'], status=task_status, result=task_res, message=task_message) + self.context['task_info'][self.context['deployment'][ret.id]] = ret + return ret + + def _init_check_status(self, check_key, servers, check_result={}): + check_status = defaultdict(lambda: defaultdict(lambda: None)) + for server in servers: + if server in check_result: + status = check_result[server] + else: + status = CheckStatus() + check_status[server] = {check_key: status} + return check_status + + def __build_connection_info(self, id, component, info): + if info is None: + log.get_logger().warn("component {0} info from display is None".format(component)) + return None + self.context['sys_cursor'] = Cursor(ip=info['ip'], port=info['port'], user=info['user'], password=info['password'], + stdio=self.obd.stdio) + return DatabaseConnection(id=id, host=info['ip'], port=info['port'], user=info['user'], password=info['password'], database='oceanbase') + + @auto_register('precheck') + def _precheck(self, name, repositories, start_check_plugins, init_check_status=False): + if init_check_status: + self._init_precheck(repositories, start_check_plugins) + else: + self._do_precheck(repositories, start_check_plugins) + + def _init_precheck(self, repositories, start_check_plugins): + param_check_status = {} + servers_set = set() + for repository in repositories: + if repository not in start_check_plugins: + continue + repository_status = {} + res = self.obd.call_plugin(start_check_plugins[repository], repository, init_check_status=True, work_dir_check=True, clients={}) + if not res and res.get_return("exception"): + raise res.get_return("exception") + servers = self.obd.deploy.deploy_config.components.get(repository.name).servers + for server in servers: + repository_status[server] = {'param': CheckStatus()} + servers_set.add(server) + param_check_status[repository.name] = repository_status + + self.context['deployment']['param_check_status'] = param_check_status + server_connect_status = {} + for server in servers_set: + server_connect_status[server] = {'ssh': CheckStatus()} + self.context['deployment']['connect_check_status'] = {'ssh': server_connect_status} + self.context['deployment']['servers_set'] = servers_set + + def _do_precheck(self, repositories, start_check_plugins): + ssh_clients, connect_status = self.obd.get_clients_with_connect_status(self.obd.deploy.deploy_config, repositories, fail_exit=False) + check_status = self._init_check_status('ssh', self.context['deployment']['servers_set'], connect_status) + self.context['deployment']['connect_check_status'] = {'ssh': check_status} + for k, v in connect_status.items(): + if v.status == v.FAIL: + return + gen_config_plugins = self.obd.search_py_script_plugin(repositories, 'generate_config') + if len(repositories) != len(gen_config_plugins): + raise Exception("param_check: config error, check stop!") + + param_check_status, check_pass = self.obd.deploy_param_check_return_check_status(repositories, self.obd.deploy.deploy_config, gen_config_plugins=gen_config_plugins) + param_check_status_result = {} + for comp_name in param_check_status: + status_res = param_check_status[comp_name] + param_check_status_result[comp_name] = self._init_check_status('param', status_res.keys(), status_res) + self.context['deployment']['param_check_status'] = param_check_status_result + + if not check_pass: + return + + for repository in repositories: + ret = self.obd.call_plugin(gen_config_plugins[repository], repository, generate_check=False, + generate_consistent_config=True, auto_depend=True) + if ret is None: + raise Exception("generate config error") + elif not ret and ret.get_return("exception"): + raise ret.get_return("exception") + if not self.obd.deploy.deploy_config.dump(): + raise Exception('generate config dump error,place check disk space!') + + for repository in repositories: + res = self.obd.call_plugin(start_check_plugins[repository], repository, init_check_status=False, work_dir_check=True, precheck=True) + if not res and res.get_return("exception"): + raise res.get_return("exception") + + def get_precheck_result(self, id, task_id): + precheck_result = PrecheckTaskInfo() + deploy = self.obd.deploy + name = self.context['deployment_id'][id] + if not name: + raise Exception(f"no such deploy for id: {id}") + if not deploy: + deploy = self.obd.deploy_manager.get_deploy_config(name) + self.obd.set_deploy(deploy) + components = deploy.deploy_config.components + param_check_status = None + connect_check_status = None + task_info = self.context['task_info'][self.context['deployment'][task_id]] + if not task_info: + raise Exception(f"no such task_info for task_id: {task_id}") + + if 'deployment' in self.context.keys(): + param_check_status = self.context['deployment']['param_check_status'] + connect_check_status = self.context['deployment']['connect_check_status'] + connect_check_status_flag = True + for component in components: + namespace_union = {} + namespace = self.obd.get_namespace(component) + if namespace: + variables = namespace.variables + if 'start_check_status' in variables.keys(): + namespace_union = util.recursive_update_dict(namespace_union, variables.get('start_check_status')) + if param_check_status is not None: + namespace_union = util.recursive_update_dict(namespace_union, param_check_status[component]) + if connect_check_status is not None and connect_check_status_flag and 'ssh' in connect_check_status.keys(): + namespace_union = util.recursive_update_dict(namespace_union, connect_check_status['ssh']) + connect_check_status_flag = False + + if namespace_union: + for server, result in namespace_union.items(): + if result is None: + log.get_logger().warn("precheck for server: {} is None".format(server.ip)) + continue + check_result = self.parse_precheck_result(component, task_info, server, result) + precheck_result.precheck_result = check_result + precheck_result.task_info = task_info + return precheck_result + + def parse_precheck_result(self, component, task_info, server, result): + check_result = [] + all_passed = True + task_info.info = [] + task_info.finished = '' + for k, v in result.items(): + check_info = PreCheckResult(name='{}:{}'.format(component, k), server=server.ip) + task_info.current = '{}:{}'.format(component, k) + info = TaskStepInfo(name='{}:{}'.format(component, k)) + if v.status == v.PASS: + check_info.result = PrecheckEventResult.PASSED + info.status = TaskStatus.FINISHED + info.result = TaskResult.SUCCESSFUL + task_info.finished += k + ' ' + elif v.status == v.FAIL: + check_info.result = PrecheckEventResult.FAILED + check_info.code = v.error.code + check_info.advisement = v.error.msg + check_info.recoverable = len(v.suggests) > 0 and v.suggests[0].auto_fix + all_passed = False + info.status = TaskStatus.FINISHED + info.result = TaskResult.FAILED + task_info.finished += k + ' ' + elif v.status == v.WAIT: + check_info.result = PrecheckEventResult.RUNNING + task_info.status = TaskStatus.RUNNING + task_info.result = TaskResult.RUNNING + info.status = TaskStatus.RUNNING + info.result = TaskResult.RUNNING + task_info.info.append(info) + check_result.append(check_info) + status_flag = [i.result for i in task_info.info] + if TaskResult.RUNNING not in status_flag: + task_info.status = TaskStatus.FINISHED + task_info.result = TaskResult.SUCCESSFUL if all_passed else TaskResult.FAILED + check_result.sort(key=lambda p: p.result) + return check_result + + def recover(self, id): + deploy = self.obd.deploy + name = self.context['deployment_id'][id] + if not name: + raise Exception(f"no such deploy for id: {id}") + if not deploy: + deploy = self.obd.deploy_manager.get_deploy_config(name) + self.obd.set_deploy(deploy) + + components = deploy.deploy_config.components + param_check_status = {} + if 'deployment' in self.context.keys(): + param_check_status = self.context['deployment']['param_check_status'] + recover_change_parameter_list = [] + for component in components: + namespace_union = {} + if component in self.obd.namespaces: + namespace = self.obd.get_namespace(component) + if namespace: + util.recursive_update_dict(namespace_union, namespace.variables.get('start_check_status', {})) + util.recursive_update_dict(namespace_union, param_check_status.get('component', {})) + + for server, precheck_result in namespace_union.items(): + if precheck_result is None: + log.get_logger().warn('component : {},precheck_result is None'.format(component)) + continue + for k, v in precheck_result.items(): + if v.status == v.FAIL and v.suggests is not None and v.suggests[0].auto_fix and v.suggests[0].fix_eval: + for fix_eval in v.suggests[0].fix_eval: + if fix_eval.operation == FixEval.SET: + config_json = None + old_value = None + if fix_eval.is_global: + deploy.deploy_config.update_component_global_conf(name, fix_eval.key, fix_eval.value, save=False) + else: + deploy.deploy_config.update_component_server_conf(name, server, fix_eval.key, fix_eval.value, save=False) + else: + config_json, old_value = self.modify_config(id, fix_eval) + + if config_json is None: + log.get_logger().warn('config json is None') + continue + recover_change_parameter = RecoverChangeParameter(name=fix_eval.key, old_value=old_value, new_value=fix_eval.value) + recover_change_parameter_list.append(recover_change_parameter) + deploy.deploy_config.dump() + self.recreate_deployment(id) + + return recover_change_parameter_list + + def recreate_deployment(self, id): + config = self.context['deployment_info'][id]['config'] if self.context['deployment_info'] is not None else None + name = self.context['deployment_id'][id] + if config is not None: + cluster_config_yaml_path = self.generate_metadb_config_path(config) + self.create_deployment(name, cluster_config_yaml_path) + + def modify_config(self, id, fix_eval): + if fix_eval.key == "parameters": + raise Exception("try to change parameters") + config = self.context['deployment_info'][id]['config'] if self.context['deployment_info'] is not None else None + if config is None: + log.get_logger().warn("config is none, no need to modify") + raise Exception('config is none') + config_dict = config.dict() + old_value = None + if fix_eval.key in config_dict: + del config_dict[fix_eval.key] + elif "parameters" in config_dict.keys() and config_dict["parameters"] is not None: + for index, parameter_dict in enumerate(config_dict["parameters"]): + parameter = Parameter(**parameter_dict) + if parameter.name == fix_eval.key: + del config_dict['parameters'][index] + self.context['deployment_info'][id]['config'] = MetadbDeploymentConfig(**config_dict) + return config_dict, old_value + + @serial("install") + def install(self, id, background_tasks): + task_manager = task.get_task_manager() + task_info = task_manager.get_task_info(id, task_type="install") + if task_info is not None and task_info.status != TaskStatus.FINISHED: + raise Exception("task {0} exists and not finished".format(id)) + task_manager.del_task_info(id, task_type="install") + background_tasks.add_task(self._do_install, id) + self.context['deployment']['task_id'] = self.context['deployment']['task_id'] + 1 if self.context['deployment']['task_id'] else 1 + task_status = TaskStatus.RUNNING.value + task_res = TaskResult.RUNNING.value + task_message = 'install' + ret = TaskInfo(id=self.context['deployment']['task_id'], status=task_status, result=task_res, total='init start_check, start, connect, bootstrap, display', message=task_message) + self.context['task_info'][self.context['deployment'][ret.id]] = ret + return ret + + @auto_register("install") + def _do_install(self, id): + name = self.context['deployment_id'][id] + log.get_logger().info("clean io buffer before start install") + self.buffer.clear() + log.get_logger().info("clean namespace for init") + for c in self.obd.deploy.deploy_config.components: + for plugin in const.INIT_PLUGINS: + self.obd.namespaces[c].set_return(plugin, None) + log.get_logger().info("clean namespace for start") + for component in self.obd.deploy.deploy_config.components: + for plugin in const.START_PLUGINS: + self.obd.namespaces[component].set_return(plugin, None) + + log.get_logger().info("start do deploy %s", name) + opt = Values() + setattr(opt, "clean", True) + setattr(opt, "force", True) + self.obd.set_options(opt) + deploy_success = self.obd.deploy_cluster(name) + if not deploy_success: + log.get_logger().warn("deploy %s failed", name) + log.get_logger().info("start %s", name) + + repositories = self.obd.load_local_repositories(self.obd.deploy.deploy_info, False) + repositories = [repository for repository in repositories if repository.name == 'oceanbase-ce'] + start_success = True + for repository in repositories: + opt = Values() + setattr(opt, "components", repository.name) + setattr(opt, "strict_check", False) + self.obd.set_options(opt) + ret = self.obd._start_cluster(self.obd.deploy, repositories) + if not ret: + log.get_logger().warn("failed to start component: %s", repository.name) + start_success = False + else: + display_ret = self.obd.namespaces[repository.name].get_return("display") + connection_info = self.__build_connection_info(id, repository.name, display_ret.get_return("info")) + if connection_info is not None: + self.context["connection_info"][id] = connection_info + if not start_success: + raise Exception("task {0} start failed".format(name)) + self.obd.deploy.update_deploy_status(DeployStatus.STATUS_RUNNING) + log.get_logger().info("finish do start %s", name) + + def get_install_task_info(self, id, task_id): + name = self.context['deployment_id'][id] + task_info = self.context['task_info'][self.context['deployment'][task_id]] + if task_info is None: + raise Exception("task {0} not found".format(task_id)) + task_info.status = TaskStatus.RUNNING + task_info.result = TaskResult.RUNNING + task_info.info = [] + failed = 0 + + self.context['deployment']['failed'] = 0 if not self.context['deployment']['failed'] else \ + self.context['deployment']['failed'] + + for component in self.obd.deploy.deploy_config.components: + if component in self.obd.namespaces: + for plugin in const.INIT_PLUGINS: + task_info.current = f'{component}-{plugin}' + step_info = TaskStepInfo(name=f'{component}-{plugin}', status=TaskStatus.RUNNING, result=TaskResult.RUNNING) + if self.obd.namespaces[component].get_return(plugin) is not None: + if not self.obd.namespaces[component].get_return(plugin): + failed += 1 + step_info.result = TaskResult.FAILED + else: + step_info.result = TaskResult.SUCCESSFUL + step_info.status = TaskStatus.FINISHED + task_info.info.append(step_info) + task_info.finished += f'{component}-{plugin} ' + + for component in self.obd.deploy.deploy_config.components: + if component in self.obd.namespaces: + for plugin in const.START_PLUGINS: + step_info = TaskStepInfo(name=f'{component}-{plugin}', status=TaskStatus.RUNNING, result=TaskResult.RUNNING) + task_info.current = f'{component}-{plugin}' + if component not in self.obd.namespaces: + break + if self.obd.namespaces[component].get_return(plugin) is not None: + if not self.obd.namespaces[component].get_return(plugin): + step_info.result = TaskResult.FAILED + failed += 1 + else: + step_info.result = TaskResult.SUCCESSFUL + step_info.status = TaskStatus.FINISHED + task_info.info.append(step_info) + task_info.finished += f'{component}-{plugin} ' + + if self.obd.deploy.deploy_info.status == DeployStatus.STATUS_RUNNING: + task_info.result = TaskResult.SUCCESSFUL + task_info.status = TaskStatus.FINISHED + + if failed or self.context['deployment']['failed'] >= 300: + self.context['deployment']['failed'] = 0 + task_info.result = TaskResult.FAILED + task_info.status = TaskStatus.FINISHED + return task_info + + @serial("reinstall") + def reinstall(self, id, background_tasks): + log.get_logger().info('start reinstall') + task_manager = task.get_task_manager() + task_info = task_manager.get_task_info(id, task_type="reinstall") + if task_info is not None and task_info.status != TaskStatus.FINISHED: + raise Exception("task {0} exists and not finished".format(id)) + task_manager.del_task_info(id, task_type="reinstall") + background_tasks.add_task(self._do_reinstall, id) + self.context['deployment']['task_id'] = self.context['deployment']['task_id'] + 1 if \ + self.context['deployment'][ + 'task_id'] else 1 + task_status = TaskStatus.RUNNING.value + task_res = TaskResult.RUNNING.value + task_message = 'reinstall' + ret = TaskInfo(id=self.context['deployment']['task_id'], status=task_status, result=task_res, + total='destroy init start_check, start, connect, bootstrap, display', message=task_message) + self.context['task_info'][self.context['deployment'][ret.id]] = ret + return ret + + @auto_register("reinstall") + def _do_reinstall(self, id): + log.get_logger().info("clean io buffer before start reinstall") + self.buffer.clear() + log.get_logger().info("clean namespace for init") + for c in self.obd.deploy.deploy_config.components: + for plugin in const.INIT_PLUGINS: + if c in self.obd.namespaces: + self.obd.namespaces[c].set_return(plugin, None) + log.get_logger().info("clean namespace for start") + for component in self.obd.deploy.deploy_config.components: + for plugin in const.START_PLUGINS: + if component in self.obd.namespaces: + self.obd.namespaces[component].set_return(plugin, None) + + name = self.context['deployment_id'][id] + log.get_logger().info('start destroy %s' % name) + opt = Values() + setattr(opt, "force_kill", True) + setattr(opt, "force", True) + setattr(opt, "clean", True) + self.obd.set_options(opt) + if not self.obd.redeploy_cluster(name): + raise Exception('reinstall failed') + + self.obd.deploy.update_deploy_status(DeployStatus.STATUS_RUNNING) + log.get_logger().info("finish do start %s", name) + + def get_reinstall_task_info(self, id, task_id): + name = self.context['deployment_id'][id] + task_info = self.context['task_info'][self.context['deployment'][task_id]] + if task_info is None: + raise Exception("task {0} not found".format(task_id)) + task_info.status = TaskStatus.RUNNING + task_info.result = TaskResult.RUNNING + task_info.info = [] + task_info.finished = '' + failed = 0 + self.context['deployment']['failed'] = 0 if not self.context['deployment']['failed'] else \ + self.context['deployment']['failed'] + + for c in self.obd.deploy.deploy_config.components: + step_info = TaskStepInfo(name=f'{c}-{const.DESTROY_PLUGIN}', status=TaskStatus.RUNNING, + result=TaskResult.RUNNING) + if c in self.obd.namespaces: + if self.obd.namespaces[c].get_return(const.DESTROY_PLUGIN) is not None: + task_info.status = TaskStatus.RUNNING + task_info.current = f'{c}-{const.DESTROY_PLUGIN}' + step_info.status = TaskStatus.FINISHED + if not self.obd.namespaces[c].get_return(const.DESTROY_PLUGIN): + step_info.result = TaskResult.FAILED + failed += 1 + else: + step_info.result = TaskResult.SUCCESSFUL + task_info.info.append(step_info) + task_info.finished += f'{c}-{const.DESTROY_PLUGIN} ' + + for component in self.obd.deploy.deploy_config.components: + if component in self.obd.namespaces: + for plugin in const.INIT_PLUGINS: + task_info.current = f'{component}-{plugin}' + step_info = TaskStepInfo(name=f'{component}-{plugin}', status=TaskStatus.RUNNING, + result=TaskResult.RUNNING) + if self.obd.namespaces[component].get_return(plugin) is not None: + if not self.obd.namespaces[component].get_return(plugin): + failed += 1 + step_info.result = TaskResult.FAILED + else: + step_info.result = TaskResult.SUCCESSFUL + else: + self.context['deployment']['failed'] += 1 + step_info.status = TaskStatus.FINISHED + task_info.info.append(step_info) + task_info.finished += f'{component}-{plugin} ' + + for component in self.obd.deploy.deploy_config.components: + for plugin in const.START_PLUGINS: + step_info = TaskStepInfo(name=f'{component}-{plugin}', status=TaskStatus.RUNNING, + result=TaskResult.RUNNING) + task_info.current = f'{component}-{plugin}' + if component not in self.obd.namespaces: + break + if self.obd.namespaces[component].get_return(plugin) is not None: + if not self.obd.namespaces[component].get_return(plugin): + step_info.result = TaskResult.FAILED + failed += 1 + else: + step_info.result = TaskResult.SUCCESSFUL + step_info.status = TaskStatus.FINISHED + task_info.info.append(step_info) + task_info.finished += f'{component}-{plugin} ' + + if self.obd.deploy.deploy_info.status == DeployStatus.STATUS_RUNNING: + task_info.result = TaskResult.SUCCESSFUL + task_info.status = TaskStatus.FINISHED + + if failed or self.context['deployment']['failed'] >= 300: + self.context['deployment']['failed'] = 0 + task_info.result = TaskResult.FAILED + task_info.status = TaskStatus.FINISHED + return task_info + + @serial("destroy") + def destroy(self, id, background_tasks): + task_manager = task.get_task_manager() + task_info = task_manager.get_task_info(id, task_type="destroy") + if task_info is not None and task_info.status != TaskStatus.FINISHED: + raise Exception("task {0} exists and not finished".format(id)) + task_manager.del_task_info(id, task_type="destroy") + background_tasks.add_task(self._destroy_cluster, id) + self.context['deployment']['task_id'] = self.context['deployment']['task_id'] + 1 if self.context['deployment'][ + 'task_id'] else 1 + task_status = TaskStatus.RUNNING.value + task_res = TaskResult.RUNNING.value + task_message = 'destroy' + ret = TaskInfo(id=self.context['deployment']['task_id'], status=task_status, result=task_res, + total='destroy', message=task_message) + self.context['task_info'][self.context['deployment'][ret.id]] = ret + return ret + + @auto_register("destroy") + def _destroy_cluster(self, id): + + name = self.context['deployment_id'][id] + if not name: + raise Exception(f"no such deploy for id: {id}") + deploy = self.obd.deploy_manager.get_deploy_config(name) + if not deploy: + raise Exception("no such deploy for id: {0}".format(id)) + self.obd.set_deploy(deploy) + + repositories = self.obd.load_local_repositories(deploy.deploy_info) + self.obd.set_repositories(repositories) + self.obd.set_options(Values({'force_kill': True})) + self.obd.search_param_plugin_and_apply(repositories, deploy.deploy_config) + + ret = self.obd._destroy_cluster(deploy, repositories) + if not ret: + raise Exception("destroy cluster {0} failed".format(name)) + deploy.update_deploy_status(DeployStatus.STATUS_CONFIGURED) + self.obd.set_options(Values()) + + def get_destroy_task_info(self, id, task_id): + name = self.context['deployment_id'][id] + task_info = self.context['task_info'][self.context['deployment'][task_id]] + if task_info is None: + raise Exception("task {0} not found".format(task_id)) + task_info.status = TaskStatus.RUNNING + task_info.result = TaskResult.RUNNING + task_info.info = [] + task_info.finished = '' + + failed = 0 + for c in self.obd.deploy.deploy_config.components: + step_info = TaskStepInfo(name=f'{c}-{const.DESTROY_PLUGIN}', status=TaskStatus.RUNNING, result=TaskResult.RUNNING) + if c in self.obd.namespaces: + if self.obd.namespaces[c].get_return(const.DESTROY_PLUGIN) is not None: + task_info.status = TaskStatus.RUNNING + task_info.current = f'{c}-{const.DESTROY_PLUGIN}' + step_info.status = TaskStatus.FINISHED + if not self.obd.namespaces[c].get_return(const.DESTROY_PLUGIN): + step_info.result = TaskResult.FAILED + failed += 1 + else: + step_info.result = TaskResult.SUCCESSFUL + task_info.info.append(step_info) + task_info.finished += f'{c}-{const.DESTROY_PLUGIN} ' + if self.obd.deploy.deploy_info.status == DeployStatus.STATUS_CONFIGURED: + task_info.result = TaskResult.SUCCESSFUL + task_info.status = TaskStatus.FINISHED + + if failed: + task_info.result = TaskResult.FAILED + task_info.status = TaskStatus.FINISHED + return task_info + + def create_connection_info(self, info, sys=False): + self.context["connection_info"][info.cluster_name] = info + log.get_logger().info( + f'connection host: {info.host}, port: {info.port}, user: {info.user}, password: {info.password}' + ) + if sys and '@' in info.user and info.user.split('@')[1] != 'sys': + raise Exception('The incoming user must belong to the sys tenant.') + self.context['meta_database'] = info.database + self.context['metadb_cursor'] = Cursor(ip=info.host, port=info.port, user=info.user, password=info.password, stdio=self.obd.stdio) + connection_info = DatabaseConnection(id=info.cluster_name, host=info.host, port=info.port, user=info.user, password=info.password, database=info.database) + connection_info_copy = copy.deepcopy(connection_info) + connection_info_copy.password = '' + return connection_info_copy + + def get_connection_info(self, cluster_name): + if not self.context["connection_info"]: + return None + if not self.context["connection_info"].get(cluster_name): + return None + connection_info_copy = copy.deepcopy(self.context['connection_info'][cluster_name]) + connection_info_copy.password = '' + return connection_info_copy \ No newline at end of file diff --git a/service/handler/ocp_handler.py b/service/handler/ocp_handler.py new file mode 100644 index 0000000..8f33b8e --- /dev/null +++ b/service/handler/ocp_handler.py @@ -0,0 +1,1633 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . +import copy +import os +from optparse import Values +from singleton_decorator import singleton +import tempfile +import yaml +import json +from collections import defaultdict + +from service.handler.base_handler import BaseHandler +from service.common import log, task, util, const +from service.common.task import Serial as serial +from service.common.task import AutoRegister as auto_register +from service.model.deployments import Parameter, OCPDeploymentStatus, OCPDeploymnetConfig +from service.model.database import DatabaseConnection +from service.model.ssh import SshAuthMethod +from service.model.ocp import ObserverResource, OcpResource, MetadbResource, OcpInfo, OcpInstalledInfo, OcpUpgradeLostAddress +from service.model.metadb import RecoverChangeParameter +from service.model.resource import DiskInfo, ServerResource +from service.model.task import TaskStatus, TaskResult, TaskInfo, PreCheckResult, PrecheckTaskInfo, PrecheckEventResult, TaskStepInfo +from _deploy import DeployStatus, DeployConfigStatus, UserConfig +from _errno import CheckStatus, FixEval +from _repository import Repository +from ssh import SshClient, SshConfig +from tool import Cursor + + +@singleton +class OcpHandler(BaseHandler): + + def create_ocp_config_path(self, config): + cluster_config = {} + log.get_logger().info('meta connections: %s' % self.context['connection_info']) + log.get_logger().info('meta_password: %s' % self.context['meta_password']) + + home_path = config.home_path + launch_user = config.launch_user + if config.auth is not None: + self.generate_auth_config(cluster_config, config.auth) + if config.components.oceanbase is not None: + self.generate_metadb_config(cluster_config, config.components.oceanbase, home_path) + if config.components.obproxy is not None and config.components.oceanbase is not None: + self.generate_obproxy_config(cluster_config, config.components.obproxy, home_path, config.components.oceanbase.component) + if config.components.ocpserver is not None: + ob_component = obp_component = None + if config.components.obproxy is not None: + ob_component = config.components.oceanbase.component + if config.components.obproxy is not None: + obp_component = config.components.obproxy.component + self.generate_ocp_config(cluster_config, config.components.ocpserver, home_path, launch_user, ob_component, obp_component) + + cluster_config_yaml_path = '' + log.get_logger().info('dump ocp-server config from path: %s' % cluster_config_yaml_path) + with tempfile.NamedTemporaryFile(delete=False, prefix="ocp-server", suffix="yaml", mode="w", encoding="utf-8") as f: + f.write(yaml.dump(cluster_config, sort_keys=False)) + cluster_config_yaml_path = f.name + self.context['id'] = self.context['id'] + 1 if self.context['id'] else 1 + log.get_logger().info('ocp-server id: %s' % self.context['id']) + status = self.context['ocp_deployment_info'][self.context['id']]['status'] \ + if self.context['ocp_deployment_info'][self.context['id']] and self.context['ocp_deployment_info'][self.context['id']]['status'] \ + else OCPDeploymentStatus.INIT + + self.context['ocp_path'] = cluster_config_yaml_path + self.context['ocp_deployment_info'][self.context['id']] = {'status': status, 'config': config} + return cluster_config_yaml_path + + def generate_auth_config(self, cluster_config, auth): + if 'user' not in cluster_config.keys(): + cluster_config['user'] = {} + cluster_config['user']['username'] = auth.user + cluster_config['user']['password'] = auth.password + cluster_config['user']['port'] = auth.port + + def generate_metadb_config(self, cluster_config, oceanbase, home_path): + oceanbase_config = dict() + config_dict = oceanbase.dict() + for key in config_dict: + if config_dict[key] and key in ('version', 'release', 'package_hash'): + oceanbase_config[key] = config_dict[key] + servers = [] + if oceanbase.topology: + for zone in oceanbase.topology: + root_service = zone.rootservice + servers.append(root_service) + for zone in oceanbase.topology: + root_service = zone.rootservice + if root_service not in oceanbase_config.keys(): + oceanbase_config[root_service] = {} + oceanbase_config[root_service]['zone'] = zone.name + for server in zone.servers: + ip = server.ip + if ip not in oceanbase_config.keys(): + oceanbase_config[ip] = {} + if ip != root_service: + servers.append(server.ip) + oceanbase_config[ip]['zone'] = zone.name + if server.parameters: + for parameter in server.parameters: + for key, value in parameter: + oceanbase_config[ip][key] = value + oceanbase_config['servers'] = servers + if 'global' not in oceanbase_config.keys(): + oceanbase_config['global'] = {} + + for key in config_dict: + if config_dict[key] and key in ['mysql_port', 'rpc_port', 'home_path', 'data_dir', 'redo_dir', 'appname', + 'root_password']: + oceanbase_config['global'][key] = config_dict[key] + + if oceanbase.home_path == '': + oceanbase_config['global']['home_path'] = home_path + '/oceanbase' + + if oceanbase.parameters: + for parameter in oceanbase.parameters: + if not parameter.adaptive: + oceanbase_config['global'][parameter.key] = parameter.value + if oceanbase.component == const.OCEANBASE_CE: + cluster_config[const.OCEANBASE_CE] = oceanbase_config + elif oceanbase.component == const.OCEANBASE: + cluster_config[const.OCEANBASE] = oceanbase_config + else: + log.get_logger().error('oceanbase component : %s not exist' % oceanbase.component) + raise Exception('oceanbase component : %s not exist' % oceanbase.component) + + def generate_obproxy_config(self, cluster_config, obproxy_config, home_path, ob_componet): + comp_config = dict() + config_dict = obproxy_config.dict() + for key in config_dict: + if config_dict[key] and key in ('servers', 'version', 'package_hash', 'release'): + comp_config[key] = config_dict[key] + + if 'global' not in comp_config.keys(): + comp_config['global'] = dict() + + for key in config_dict: + if config_dict[key] and key in ('cluster_name', 'prometheus_listen_port', 'listen_port', 'home_path'): + comp_config['global'][key] = config_dict[key] + + if obproxy_config.home_path == '': + comp_config['global']['home_path'] = home_path + '/obproxy' + + for parameter in obproxy_config.parameters: + if not parameter.adaptive: + comp_config['global'][parameter.key] = parameter.value + if 'depends' not in comp_config.keys(): + comp_config['depends'] = list() + comp_config['depends'].append(ob_componet) + if obproxy_config.component == const.OBPROXY_CE: + cluster_config[const.OBPROXY_CE] = comp_config + elif obproxy_config.component == const.OBPROXY: + cluster_config[const.OBPROXY] = comp_config + else: + log.get_logger().error('obproxy component : %s not exist' % obproxy_config.component) + raise Exception('obproxy component : %s not exist' % obproxy_config.component) + + def generate_ocp_config(self, cluster_config, config, home_path, launch_user, ob_component=None, obp_component=None): + log.get_logger().debug('generate ocp config') + ocp_config = dict() + config_dict = config.dict() + for key in config_dict: + if config_dict[key] and key in ('servers', 'version', 'package_hash', 'release'): + ocp_config[key] = config_dict[key] + + if 'global' not in ocp_config.keys(): + ocp_config['global'] = {} + + for key in config_dict: + if config_dict[key] and key in ('port', 'admin_password', 'memory_size', 'manage_info', 'home_path', 'soft_dir', 'log_dir'): + ocp_config['global'][key] = config_dict[key] + + if config.metadb: + ocp_config['global']['jdbc_url'] = 'jdbc:oceanbase://' + config_dict['metadb']['host'] + ':' + str(config_dict['metadb']['port']) + '/' + config_dict['metadb']['database'] + ocp_config['global']['jdbc_username'] = config_dict['metadb']['user'] + ocp_config['global']['jdbc_password'] = config_dict['metadb']['password'] + + if config.meta_tenant: + ocp_config['global']['ocp_meta_tenant'] = {} + ocp_config['global']['ocp_meta_tenant']['tenant_name'] = config_dict['meta_tenant']['name']['tenant_name'] + ocp_config['global']['ocp_meta_tenant']['max_cpu'] = config_dict['meta_tenant']['resource']['cpu'] + ocp_config['global']['ocp_meta_tenant']['memory_size'] = str(config_dict['meta_tenant']['resource']['memory']) + 'G' + ocp_config['global']['ocp_meta_username'] = config_dict['meta_tenant']['name']['user_name'] + ocp_config['global']['ocp_meta_password'] = config_dict['meta_tenant']['password'] + ocp_config['global']['ocp_meta_db'] = config_dict['meta_tenant']['name']['user_database'] if config_dict['meta_tenant']['name']['user_database'] != '' else 'meta_database' + self.context['meta_tenant'] = config_dict['meta_tenant']['name']['tenant_name'] + + if config.monitor_tenant: + ocp_config['global']['ocp_monitor_tenant'] = {} + ocp_config['global']['ocp_monitor_tenant']['tenant_name'] = config_dict['monitor_tenant']['name']['tenant_name'] + ocp_config['global']['ocp_monitor_tenant']['max_cpu'] = config_dict['monitor_tenant']['resource']['cpu'] + ocp_config['global']['ocp_monitor_tenant']['memory_size'] = str(config_dict['monitor_tenant']['resource']['memory']) + 'G' + ocp_config['global']['ocp_monitor_username'] = config_dict['monitor_tenant']['name']['user_name'] + ocp_config['global']['ocp_monitor_password'] = config_dict['monitor_tenant']['password'] + ocp_config['global']['ocp_monitor_db'] = config_dict['monitor_tenant']['name']['user_database'] if config_dict['monitor_tenant']['name']['user_database'] != '' else 'monitor_database' + self.context['monitor_tenant'] = config_dict['monitor_tenant']['name']['tenant_name'] + + if config.home_path == '': + ocp_config['global']['home_path'] = home_path + '/ocp-server' + + if launch_user: + ocp_config['global']['launch_user'] = launch_user + + if config.soft_dir == '': + ocp_config['global']['soft_dir'] = ocp_config['global']['home_path'] + '/data/files/' + + if config.log_dir == '': + ocp_config['global']['log_dir'] = ocp_config['global']['home_path'] + '/log' + + if config.parameters: + for parameter in config.parameters: + if not parameter.adaptive: + ocp_config['global'][parameter.key] = parameter.value + if not ob_component: + if config_dict['metadb']: + ocp_config['global']['jdbc_url'] = 'jdbc:oceanbase://' + config_dict['metadb']['host'] + ':' + str( + config_dict['metadb']['port']) + '/' + config_dict['metadb']['database'] + ocp_config['global']['jdbc_username'] = config_dict['metadb']['user'] + ocp_config['global']['jdbc_password'] = config_dict['metadb']['password'] + if 'depends' not in ocp_config.keys() and ob_component and obp_component: + ocp_config['depends'] = list() + ocp_config['depends'].append(ob_component) + ocp_config['depends'].append(obp_component) + if config.component == const.OCP_SERVER_CE: + cluster_config[const.OCP_SERVER_CE] = ocp_config + elif config.component == const.OCP_SERVER: + cluster_config[const.OCP_SERVER] = ocp_config + else: + log.get_logger().error('ocp-server component : %s not exist' % config.component) + raise Exception('ocp-server component : %s not exist' % config.component) + + def create_ocp_deployment(self, name: str, config_path: str): + log.get_logger().debug('deploy cluster') + deploy = self.obd.deploy_manager.get_deploy_config(name) + if deploy: + deploy_info = deploy.deploy_info + if deploy_info.status == DeployStatus.STATUS_DEPLOYED: + log.get_logger().debug('start destroy(ocp) %s' % name) + self.obd.set_options(Values({'force_kill': True})) + if self.obd.repositories: + self.obd.set_repositories(self.obd.repositories) + self.obd._destroy_cluster(self.obd.deploy, self.obd.repositories) + else: + self.obd.destroy_cluster(name) + log.get_logger().info('destroy %s(ocp) end' % name) + deploy.update_deploy_status(DeployStatus.STATUS_CONFIGURED) + deploy = self.obd.deploy_manager.get_deploy_config(name) + deploy_info = deploy.deploy_info + if deploy_info.status not in [DeployStatus.STATUS_CONFIGURED, DeployStatus.STATUS_DESTROYED]: + log.get_logger().error('Deploy "%s" is %s. You could not deploy an %s cluster.' % ( + name, deploy_info.status.value, deploy_info.status.value)) + raise Exception('Deploy "%s" is %s. You could not deploy an %s cluster.' % ( + name, deploy_info.status.value, deploy_info.status.value)) + if deploy_info.config_status != DeployConfigStatus.UNCHNAGE: + log.get_logger().debug('Apply temp deploy configuration') + if not deploy.apply_temp_deploy_config(): + log.get_logger().error('Failed to apply new deploy configuration') + raise Exception('Failed to apply new deploy configuration') + + deploy = self.obd.deploy_manager.create_deploy_config(name, config_path) + if not deploy: + log.get_logger().error('Failed to create deploy: %s. please check you configuration file' % name) + raise Exception('Failed to create deploy: %s. please check you configuration file' % name) + self.obd.set_deploy(deploy) + log.get_logger().info('ocp server cluster config path: %s ' % config_path) + self.context['ocp_deployment_id'][self.context['id']] = name + return self.context['id'] + + def check_user(self, user): + self.context['upgrade_servers'] = user.servers + for ip in user.servers: + log.get_logger().info('ip: %s, port: %s, user: %s, password: %s' % (ip, user.port, user.user, user.password)) + self.context['upgrade_user'] = user.user + self.context['upgrade_user_password'] = user.password + self.context['upgrade_ssh_port'] = user.port if user.port else 22 + config = SshConfig(host=ip, port=user.port, username=user.user, password=user.password) + client = SshClient(config) + if not (client.execute_command('sudo -n true') or client.execute_command('[ `id -u` == "0" ]')): + raise Exception('Please execute `bash -c \'echo "{user} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers`\' as root in {ip}.'.format(user=user.user, ip=ip)) + res = client.connect(self.obd.stdio, exit=False) + if res != True: + return False + return True + + def generate_secure_ocp_deployment(self, ocp_deployment): + log.get_logger().info('generate secure ocp_deployment') + config = copy.deepcopy(ocp_deployment) + config.admin_password = '' + if config.meta_tenant: + config.meta_tenant.password = '' + if config.monitor_tenant: + config.monitor_tenant.password = '' + if config.components.oceanbase.password: + config.components.oceanbase.password = '' + if config.auth: + config.auth.password = '' + return config + + def list_ocp_deployments(self): + log.get_logger().info('list secure ocp_deployment') + data = [] + for id, ocp_deployment_info in self.context['ocp_deployment_info'].items(): + if ocp_deployment_info: + copy_ocp_deployment_info = copy.deepcopy(ocp_deployment_info) + copy_ocp_deployment_info['config'].admin_password = '' + if copy_ocp_deployment_info['config'].meta_tenant: + copy_ocp_deployment_info['config'].meta_tenant.password = '' + if copy_ocp_deployment_info['config'].monitor_tenant: + copy_ocp_deployment_info['config'].monitor_tenant.password = '' + if copy_ocp_deployment_info['config'].metadb.password: + copy_ocp_deployment_info['config'].metadb.password = '' + if copy_ocp_deployment_info['config'].auth: + copy_ocp_deployment_info['config'].auth.password = '' + data.append(ocp_deployment_info) + return data + + def get_ocp_deployment(self, id): + log.get_logger().info('get id(%s) secure ocp_deployment' % id) + if id not in self.context['ocp_deployment_info']: + raise Exception(f'id: {id} not deployment') + data = self.context['ocp_deployment_info'][id] + copy_data = copy.deepcopy(data) + copy_data['config'].admin_password = '' + if copy_data['config'].meta_tenant: + copy_data['config'].meta_tenant.password = '' + if copy_data['config'].monitor_tenant: + copy_data['config'].monitor_tenant.password = '' + if copy_data['config'].metadb.password: + copy_data['config'].metadb.password = '' + if copy_data['config'].auth: + copy_data['config'].auth.password = '' + return copy_data['config'] + + @serial("ocp_precheck") + def ocp_precheck(self, id, background_tasks): + task_manager = task.get_task_manager() + app_name = self.context['ocp_deployment_id'][id] + log.get_logger().info('precheck start: %s' % app_name) + if not app_name: + raise Exception(f"no such deploy for id: {id}") + task_info = task_manager.get_task_info(app_name, task_type="ocp_precheck") + if task_info is not None and task_info.status != TaskStatus.FINISHED: + raise Exception(f"task {app_name} exists and not finished") + deploy = self.obd.deploy + if not deploy: + raise Exception("no such deploy for name:{0}".format(app_name)) + deploy_config = deploy.deploy_config + pkgs, repositories, errors = self.obd.search_components_from_mirrors(deploy_config, only_info=True) + if errors: + raise Exception("{}".format('\n'.join(errors))) + repositories.extend(pkgs) + repositories = self.obd.sort_repository_by_depend(repositories, deploy_config) + for repository in repositories: + real_servers = set() + cluster_config = deploy_config.components[repository.name] + for server in cluster_config.servers: + if server.ip in real_servers: + raise Exception( + "Deploying multiple {} instances on the same server is not supported.'".format( + repository.name)) + return False + real_servers.add(server.ip) + self.obd.search_param_plugin_and_apply(repositories, deploy_config) + self.obd.set_repositories(repositories) + + start_check_plugins = self.obd.search_py_script_plugin(repositories, 'start_check', no_found_act='warn') + log.get_logger().info('start_check plugins: %s' % start_check_plugins) + self._precheck(app_name, repositories, start_check_plugins, init_check_status=True) + info = task_manager.get_task_info(app_name, task_type="ocp_precheck") + if info is not None and info.exception is not None: + exception = copy.deepcopy(info.exception) + info.exception = None + raise exception + task_manager.del_task_info(app_name, task_type="ocp_precheck") + background_tasks.add_task(self._precheck, app_name, repositories, start_check_plugins, init_check_status=False) + self.context['ocp_deployment']['task_id'] = self.context['ocp_deployment']['task_id'] + 1 if self.context['ocp_deployment']['task_id'] else 1 + log.get_logger().info('task id: %d' % self.context['ocp_deployment']['task_id']) + task_status = TaskStatus.RUNNING.value + task_res = TaskResult.RUNNING.value + task_message = 'ocp_precheck' + ret = TaskInfo(id=self.context['ocp_deployment']['task_id'], status=task_status, result=task_res, message=task_message, total='port, java, disk, mem, oceanbase version') + log.get_logger().info('task ret: %s' % ret) + self.context['task_info'][self.context['ocp_deployment'][ret.id]] = ret + return ret + + def _init_check_status(self, check_key, servers, check_result={}): + check_status = defaultdict(lambda: defaultdict(lambda: None)) + for server in servers: + if server in check_result: + status = check_result[server] + else: + status = CheckStatus() + check_status[server] = {check_key: status} + return check_status + + @auto_register('ocp_precheck') + def _precheck(self, name, repositories, start_check_plugins, init_check_status=False): + if init_check_status: + self._init_precheck(repositories, start_check_plugins) + else: + self._do_precheck(repositories, start_check_plugins) + + def _init_precheck(self, repositories, start_check_plugins): + log.get_logger().info('init precheck') + param_check_status = {} + servers_set = set() + for repository in repositories: + if repository not in start_check_plugins: + continue + repository_status = {} + res = self.obd.call_plugin(start_check_plugins[repository], repository, init_check_status=True, work_dir_check=True, clients={}) + if not res and res.get_return("exception"): + raise res.get_return("exception") + servers = self.obd.deploy.deploy_config.components.get(repository.name).servers + for server in servers: + repository_status[server] = {'param': CheckStatus()} + servers_set.add(server) + param_check_status[repository.name] = repository_status + + self.context['ocp_deployment']['param_check_status'] = param_check_status + server_connect_status = {} + for server in servers_set: + server_connect_status[server] = {'ssh': CheckStatus()} + self.context['ocp_deployment']['connect_check_status'] = {'ssh': server_connect_status} + self.context['ocp_deployment']['servers_set'] = servers_set + + def _do_precheck(self, repositories, start_check_plugins): + log.get_logger().info('start precheck') + log.get_logger().info('ssh check') + ssh_clients, connect_status = self.obd.get_clients_with_connect_status(self.obd.deploy.deploy_config, repositories, fail_exit=False) + log.get_logger().info('connect_status: ', connect_status) + check_status = self._init_check_status('ssh', self.context['ocp_deployment']['servers_set'], connect_status) + self.context['ocp_deployment']['connect_check_status'] = {'ssh': check_status} + for k, v in connect_status.items(): + if v.status == v.FAIL: + self.context['ocp_deployment_ssh'][self.context['id']] = 'fail' + log.get_logger().info('ssh check failed') + return + log.get_logger().info('ssh check succeed') + gen_config_plugins = self.obd.search_py_script_plugin(repositories, 'generate_config') + if len(repositories) != len(gen_config_plugins): + raise Exception("param_check: config error, check stop!") + + param_check_status, check_pass = self.obd.deploy_param_check_return_check_status(repositories, self.obd.deploy.deploy_config, gen_config_plugins=gen_config_plugins) + param_check_status_result = {} + for comp_name in param_check_status: + status_res = param_check_status[comp_name] + param_check_status_result[comp_name] = self._init_check_status('param', status_res.keys(), status_res) + self.context['ocp_deployment']['param_check_status'] = param_check_status_result + + log.get_logger().info('precheck param check status: %s' % param_check_status) + log.get_logger().info('precheck param check status res: %s' % check_pass) + if not check_pass: + return + + for repository in repositories: + ret = self.obd.call_plugin(gen_config_plugins[repository], repository, generate_check=False, + generate_consistent_config=True, auto_depend=True) + if ret is None: + raise Exception("generate config error") + elif not ret and ret.get_return("exception"): + raise ret.get_return("exception") + if not self.obd.deploy.deploy_config.dump(): + raise Exception('generate config dump error,place check disk space!') + + log.get_logger().info('generate config succeed') + ssh_clients = self.obd.get_clients(self.obd.deploy.deploy_config, repositories) + for repository in repositories: + log.get_logger().info('begin start_check: %s' % repository.name) + res = self.obd.call_plugin(start_check_plugins[repository], repository, init_check_status=False, + work_dir_check=True, precheck=True, clients=ssh_clients, sys_cursor=self.context['metadb_cursor']) + if not res and res.get_return("exception"): + raise res.get_return("exception") + log.get_logger().info('end start_check: %s' % repository.name) + + def get_precheck_result(self, id, task_id): + log.get_logger().info('get ocp precheck result') + precheck_result = PrecheckTaskInfo() + deploy = self.obd.deploy + name = self.context['ocp_deployment_id'][id] + if not name: + raise Exception(f"no such deploy for id: {id}") + if not deploy: + deploy = self.obd.deploy_manager.get_deploy_config(name) + self.obd.set_deploy(deploy) + components = deploy.deploy_config.components + + param_check_status = None + connect_check_status = None + check_result = [] + task_info = self.context['task_info'][self.context['ocp_deployment'][task_id]] + all_passed = [] + precheck_result.task_info = task_info + task_info.info = [] + + if 'ocp_deployment' in self.context.keys(): + param_check_status = self.context['ocp_deployment']['param_check_status'] + connect_check_status = self.context['ocp_deployment']['connect_check_status'] + for component in components: + namespace_union = {} + namespace = self.obd.get_namespace(component) + if namespace: + variables = namespace.variables + if 'start_check_status' in variables.keys(): + namespace_union = util.recursive_update_dict(namespace_union, variables.get('start_check_status')) + if param_check_status: + namespace_union = util.recursive_update_dict(namespace_union, param_check_status[component]) + if connect_check_status and 'ssh' in connect_check_status.keys(): + namespace_union = util.recursive_update_dict(namespace_union, connect_check_status['ssh']) + + log.get_logger().info('namespace_union: %s' % namespace_union) + if namespace_union: + for server, result in namespace_union.items(): + if result is None: + log.get_logger().warn("precheck for server: {} is None".format(server.ip)) + continue + all_passed.append(self.parse_precheck_result(component, check_result, task_info, server, result)) + check_result.sort(key=lambda p: p.result) + precheck_result.precheck_result = check_result + status_flag = [i.status for i in task_info.info] + if TaskStatus.RUNNING not in status_flag: + task_info.status = TaskStatus.FINISHED + task_info.result = TaskResult.SUCCESSFUL if all(all_passed) else TaskResult.FAILED + precheck_result.task_info = task_info + if self.context['ocp_deployment_ssh'][id] == 'fail' and TaskStatus.FINISHED in status_flag: + precheck_result.task_info.result = TaskResult.FAILED + precheck_result.task_info.status = TaskStatus.FINISHED + return precheck_result + + def parse_precheck_result(self, component, check_result, task_info, server, result): + all_passed = True + task_info.finished = '' + for k, v in result.items(): + check_info = PreCheckResult(name='{}:{}'.format(component, k), server=server.ip) + task_info.current = '{}:{}'.format(component, k) + log.get_logger().info('precheck result current: %s' % task_info.current) + info = TaskStepInfo(name='{}:{}'.format(component, k)) + if v.status == v.PASS: + check_info.result = PrecheckEventResult.PASSED + info.status = TaskStatus.FINISHED + info.result = TaskResult.SUCCESSFUL + task_info.finished += k + ' ' + elif v.status == v.FAIL: + check_info.result = PrecheckEventResult.FAILED + check_info.code = v.error.code + check_info.advisement = v.error.msg + check_info.recoverable = len(v.suggests) > 0 and v.suggests[0].auto_fix + all_passed = False + info.status = TaskStatus.FINISHED + info.result = TaskResult.FAILED + task_info.finished += k + ' ' + elif v.status == v.WAIT: + check_info.result = PrecheckEventResult.RUNNING + task_info.status = TaskStatus.RUNNING + task_info.result = TaskResult.RUNNING + info.status = TaskStatus.RUNNING + info.result = TaskResult.RUNNING + task_info.info.append(info) + check_result.append(check_info) + return all_passed + + def recover(self, id): + log.get_logger().info('recover config') + deploy = self.obd.deploy + name = self.context['ocp_deployment_id'][id] + if not deploy: + deploy = self.obd.deploy_manager.get_deploy_config(name) + self.obd.set_deploy(deploy) + + components = deploy.deploy_config.components + param_check_status = {} + if 'ocp_deployment' in self.context.keys(): + param_check_status = self.context['ocp_deployment']['param_check_status'] + recover_change_parameter_list = [] + for component in components: + namespace_union = {} + if component in self.obd.namespaces: + namespace = self.obd.get_namespace(component) + if namespace: + util.recursive_update_dict(namespace_union, namespace.variables.get('start_check_status', {})) + util.recursive_update_dict(namespace_union, param_check_status.get('component', {})) + + for server, precheck_result in namespace_union.items(): + if precheck_result is None: + log.get_logger().warn('component : {},precheck_result is None'.format(component)) + continue + for k, v in precheck_result.items(): + log.get_logger().info('k: %s, v: %s' % (k, v)) + log.get_logger().info('status: %s' % v.status) + if v.status == v.FAIL and v.suggests is not None and v.suggests[0].auto_fix and v.suggests[0].fix_eval: + log.get_logger().info('auto_fix : %s' % v.suggests[0].auto_fix) + log.get_logger().info('fix_eval: %s' % v.suggests[0].fix_eval) + for fix_eval in v.suggests[0].fix_eval: + if fix_eval.operation == FixEval.SET: + config_json = None + old_value = None + if fix_eval.is_global: + deploy.deploy_config.update_component_global_conf(name, fix_eval.key, fix_eval.value, save=False) + else: + deploy.deploy_config.update_component_server_conf(name, server, fix_eval.key, fix_eval.value, save=False) + else: + config_json, old_value = self.modify_config(component, id, fix_eval) + + if config_json is None: + log.get_logger().warn('config json is None') + continue + recover_change_parameter = RecoverChangeParameter(name=fix_eval.key, old_value=old_value, new_value=fix_eval.value) + recover_change_parameter_list.append(recover_change_parameter) + self.context['ocp_deployment_info'][id]['config'] = OCPDeploymnetConfig(**json.loads(json.dumps(config_json))) + deploy.deploy_config.dump() + self.recreate_deployment(id) + + return recover_change_parameter_list + + def recreate_deployment(self, id): + log.get_logger().info('recreate ocp deployment') + config = self.context['ocp_deployment_info'][id]['config'] if self.context['ocp_deployment_info'][id]['config'] is not None else None + log.get_logger().info('config: %s' % config) + if config is not None: + cluster_config_yaml_path = self.create_ocp_config_path(config) + self.create_ocp_deployment(self.context['ocp_deployment_id'][id], cluster_config_yaml_path) + + def modify_config(self, component, id, fix_eval): + log.get_logger().info('modify ocp config') + if fix_eval.key == "parameters": + raise Exception("try to change parameters") + config = self.context['ocp_deployment_info'][id] if self.context['ocp_deployment_info'] is not None else None + if config is None: + log.get_logger().warn("config is none, no need to modify") + raise Exception('config is none') + log.get_logger().info('%s ocp config: %s' % (id, config)) + config = config['config'] + config_dict = config.dict() + if config_dict['components'] is None: + log.get_logger().warn("component is none, no need to modify") + raise Exception('component is none') + old_value = None + for value in config_dict['components'].values(): + if value is not None and 'component' in value.keys() and value['component'] == component: + log.get_logger().info('old value: %s' % value) + if fix_eval.key in value.keys(): + log.get_logger().info('new value: %s' % fix_eval.value) + old_value = value[fix_eval.key] + value[fix_eval.key] = fix_eval.value + elif "parameters" in value.keys() and value["parameters"] is not None: + log.get_logger().info('new value: %s' % fix_eval.value) + for parameter_dict in value["parameters"]: + parameter = Parameter(**parameter_dict) + if parameter.key == fix_eval.key: + if fix_eval.operation == FixEval.DEL: + old_value = parameter.value + value["parameters"].remove(parameter_dict) + else: + parameter_dict[fix_eval.key] = fix_eval.value + return config_dict, old_value + return None, None + + @serial("install") + def install(self, id, background_tasks): + task_manager = task.get_task_manager() + task_info = task_manager.get_task_info(id, task_type="install") + if task_info is not None and task_info.status != TaskStatus.FINISHED: + raise Exception("task {0} exists and not finished".format(id)) + task_manager.del_task_info(id, task_type="install") + self.context['ocp_deployment']['task_id'] = self.context['ocp_deployment']['task_id'] + 1 if self.context['ocp_deployment']['task_id'] else 1 + background_tasks.add_task(self._do_install, id, self.context['ocp_deployment']['task_id']) + task_status = TaskStatus.RUNNING.value + task_res = TaskResult.RUNNING.value + task_message = 'install' + ret = TaskInfo(id=self.context['ocp_deployment']['task_id'], status=task_status, result=task_res, total='init start_check, start, connect, bootstrap, display', message=task_message) + self.context['task_info'][self.context['ocp_deployment'][ret.id]] = ret + return ret + + @auto_register("install") + def _do_install(self, id, task_id): + self.context['deploy_status'] = self.context['process_installed'] = '' + log.get_logger().info("clean io buffer before start install") + self.buffer.clear() + log.get_logger().info("clean namespace for init") + for c in self.obd.deploy.deploy_config.components: + for plugin in const.INIT_PLUGINS: + if c in self.obd.namespaces: + self.obd.namespaces[c].set_return(plugin, None) + log.get_logger().info("clean namespace for start") + for component in self.obd.deploy.deploy_config.components: + for plugin in const.START_PLUGINS: + if component in self.obd.namespaces: + self.obd.namespaces[component].set_return(plugin, None) + + name = self.context['ocp_deployment_id'][id] + deploy = self.obd.deploy + log.get_logger().info("start deploy %s", name) + opt = Values() + setattr(opt, "clean", True) + setattr(opt, "force", True) + self.obd.set_options(opt) + try: + deploy_success = self.obd.deploy_cluster(name) + if not deploy_success: + log.get_logger().warn("deploy %s failed", name) + raise Exception('deploy failed') + except: + self.context['deploy_status'] = 'failed' + raise Exception('deploy failed') + log.get_logger().info("deploy %s succeed", name) + + repositories = self.obd.load_local_repositories(self.obd.deploy.deploy_info, False) + repositories = self.obd.sort_repository_by_depend(repositories, self.obd.deploy.deploy_config) + start_success = True + oceanbase_repository = None + for repository in repositories: + log.get_logger().info("begin start %s", repository.name) + opt = Values() + setattr(opt, "components", repository.name) + setattr(opt, "strict_check", False) + setattr(opt, "metadb_cursor", self.context['metadb_cursor']) + self.obd.set_options(opt) + if repository.name == const.OCEANBASE_CE: + oceanbase_repository = repository + ret = self.obd._start_cluster(self.obd.deploy, repositories) + if not ret: + log.get_logger().warn("failed to start component: %s", repository.name) + start_success = False + log.get_logger().info("end start %s", repository.name) + if not start_success: + if len(repositories) > 1 and oceanbase_repository: + drop_tenant_plugins = self.obd.search_py_script_plugin([repository for repository in repositories if repository.name == const.OCEANBASE_CE], 'drop_tenant', no_found_act='warn') + config = self.context['ocp_deployment_info'][id]['config'].components.oceanbase + cursor = Cursor(ip=config.topology[0].servers[0].ip, port=config.mysql_port, user='root', + password=config.root_password, stdio=self.obd.stdio) + opt = Values() + setattr(opt, "tenant_name", self.context['meta_tenant']) + self.obd.set_options(opt) + self.obd.call_plugin(drop_tenant_plugins[oceanbase_repository], oceanbase_repository, cursor=cursor) + opt = Values() + setattr(opt, "tenant_name", self.context['monitor_tenant']) + self.obd.set_options(opt) + self.obd.call_plugin(drop_tenant_plugins[oceanbase_repository], oceanbase_repository, cursor=cursor) + raise Exception("task {0} start failed".format(name)) + self.obd.deploy.update_deploy_status(DeployStatus.STATUS_RUNNING) + log.get_logger().info("finish do start %s", name) + if not self.context['ocp_deployment_info'][id]['config'].components.ocpserver.metadb: + log.get_logger().info("begin take_over metadb") + ocp_info = self.get_installed_ocp_info(id) + self.obd.options._update_loose({"address": ocp_info.url[0], "user": ocp_info.account, "password": ocp_info.password}) + self.obd.export_to_ocp(name) + log.get_logger().info("finish take_over metadb") + deploy = self.obd.deploy_manager.get_deploy_config(name) + self.obd.set_deploy(deploy) + self.context['process_installed'] = 'done' + + def get_install_task_info(self, id, task_id): + log.get_logger().info('get ocp install task info') + name = self.context['ocp_deployment_id'][id] + task_info = self.context['task_info'][self.context['ocp_deployment'][task_id]] + if task_info is None: + raise Exception("task {0} not found".format(task_id)) + task_info.status = TaskStatus.RUNNING + task_info.result = TaskResult.RUNNING + task_info.info = [] + task_info.finished = '' + failed = 0 + self.context['ocp_deployment']['failed'] = 0 if not self.context['ocp_deployment']['failed'] else self.context['ocp_deployment']['failed'] + if not self.obd.deploy: + return task_info + for component in self.obd.deploy.deploy_config.components: + if component in self.obd.namespaces: + for plugin in const.INIT_PLUGINS: + task_info.current = f'{component}-{plugin}' + step_info = TaskStepInfo(name=f'{component}-{plugin}', status=TaskStatus.RUNNING, result=TaskResult.RUNNING) + if self.obd.namespaces[component].get_return(plugin) is not None: + if not self.obd.namespaces[component].get_return(plugin): + failed += 1 + step_info.result = TaskResult.FAILED + else: + step_info.result = TaskResult.SUCCESSFUL + else: + self.context['ocp_deployment']['failed'] += 1 + step_info.status = TaskStatus.FINISHED + task_info.info.append(step_info) + task_info.finished += f'{component}-{plugin} ' + + for component in self.obd.deploy.deploy_config.components: + for plugin in const.START_PLUGINS: + step_info = TaskStepInfo(name=f'{component}-{plugin}', status=TaskStatus.RUNNING, result=TaskResult.RUNNING) + task_info.current = f'{component}-{plugin}' + if component not in self.obd.namespaces: + break + if self.obd.namespaces[component].get_return(plugin) is not None: + if not self.obd.namespaces[component].get_return(plugin): + step_info.result = TaskResult.FAILED + failed += 1 + else: + step_info.result = TaskResult.SUCCESSFUL + step_info.status = TaskStatus.FINISHED + task_info.info.append(step_info) + task_info.finished += f'{component}-{plugin} ' + + if self.obd.deploy.deploy_info.status == DeployStatus.STATUS_RUNNING and self.context['process_installed'] == 'done': + task_info.result = TaskResult.SUCCESSFUL + task_info.status = TaskStatus.FINISHED + + if failed or self.context['ocp_deployment']['failed'] >= 1500 or self.context['deploy_status'] == 'failed': + self.context['ocp_deployment']['failed'] = 0 + task_info.result = TaskResult.FAILED + task_info.status = TaskStatus.FINISHED + return task_info + + @serial("reinstall") + def reinstall(self, id, background_tasks): + log.get_logger().info('start reinstall') + task_manager = task.get_task_manager() + task_info = task_manager.get_task_info(id, task_type="reinstall") + if task_info is not None and task_info.status != TaskStatus.FINISHED: + raise Exception("task {0} exists and not finished".format(id)) + task_manager.del_task_info(id, task_type="reinstall") + background_tasks.add_task(self._do_reinstall, id) + self.context['ocp_deployment']['task_id'] = self.context['ocp_deployment']['task_id'] + 1 if self.context['ocp_deployment'][ + 'task_id'] else 1 + task_status = TaskStatus.RUNNING.value + task_res = TaskResult.RUNNING.value + task_message = 'reinstall' + ret = TaskInfo(id=self.context['ocp_deployment']['task_id'], status=task_status, result=task_res, + total='destroy init start_check, start, connect, bootstrap, display', message=task_message) + self.context['task_info'][self.context['ocp_deployment'][ret.id]] = ret + return ret + + @auto_register("reinstall") + def _do_reinstall(self, id): + log.get_logger().info("clean io buffer before start reinstall") + self.buffer.clear() + log.get_logger().info("clean namespace for init") + for c in self.obd.deploy.deploy_config.components: + for plugin in const.INIT_PLUGINS: + if c in self.obd.namespaces: + self.obd.namespaces[c].set_return(plugin, None) + log.get_logger().info("clean namespace for start") + for component in self.obd.deploy.deploy_config.components: + for plugin in const.START_PLUGINS: + if component in self.obd.namespaces: + self.obd.namespaces[component].set_return(plugin, None) + + name = self.context['ocp_deployment_id'][id] + repositories = self.obd.repositories + log.get_logger().info('start destroy %s' % name) + opt = Values() + setattr(opt, "force_kill", True) + self.obd.set_options(opt) + if not self.obd._destroy_cluster(self.obd.deploy, repositories): + raise Exception('destroy failed') + + self.obd.set_repositories([]) + deploy = self.obd.deploy_manager.create_deploy_config(name, self.context['ocp_path']) + if not deploy: + raise Exception("no such deploy for name:{0}".format(name)) + deploy_config = deploy.deploy_config + pkgs, repositories, errors = self.obd.search_components_from_mirrors(deploy_config, only_info=True) + if errors: + raise Exception("{}".format('\n'.join(errors))) + repositories.extend(pkgs) + repositories = self.obd.sort_repository_by_depend(repositories, deploy_config) + for repository in repositories: + real_servers = set() + cluster_config = deploy_config.components[repository.name] + for server in cluster_config.servers: + if server.ip in real_servers: + raise Exception( + "Deploying multiple {} instances on the same server is not supported.'".format( + repository.name)) + real_servers.add(server.ip) + self.obd.search_param_plugin_and_apply(repositories, deploy_config) + self.obd.set_repositories(repositories) + + gen_config_plugins = self.obd.search_py_script_plugin(repositories, 'generate_config') + for repository in repositories: + ret = self.obd.call_plugin(gen_config_plugins[repository], repository, generate_check=False, + generate_consistent_config=True, auto_depend=True) + if ret is None: + raise Exception("generate config error") + elif not ret and ret.get_return("exception"): + raise ret.get_return("exception") + if not self.obd.deploy.deploy_config.dump(): + raise Exception('generate config dump error,place check disk space!') + + log.get_logger().info("start deploy %s", name) + opt = Values() + setattr(opt, "clean", True) + setattr(opt, "force", True) + self.obd.set_options(opt) + deploy_success = self.obd.deploy_cluster(name) + if not deploy_success: + log.get_logger().warn("deploy %s failed", name) + raise Exception('deploy failed') + log.get_logger().info("deploy %s succeed", name) + + repositories = self.obd.load_local_repositories(self.obd.deploy.deploy_info, False) + repositories = self.obd.sort_repository_by_depend(repositories, self.obd.deploy.deploy_config) + start_success = True + for repository in repositories: + opt = Values() + setattr(opt, "components", repository.name) + setattr(opt, "strict_check", False) + setattr(opt, "metadb_cursor", self.context['metadb_cursor']) + self.obd.set_options(opt) + ret = self.obd._start_cluster(self.obd.deploy, repositories) + if not ret: + log.get_logger().warn("failed to start component: %s", repository.name) + start_success = False + if not start_success: + raise Exception("task {0} start failed".format(name)) + + self.obd.deploy.update_deploy_status(DeployStatus.STATUS_RUNNING) + self.context['process_installed'] = 'done' + log.get_logger().info("finish do start %s", name) + + def get_reinstall_task_info(self, id, task_id): + name = self.context['ocp_deployment_id'][id] + task_info = self.context['task_info'][self.context['ocp_deployment'][task_id]] + if task_info is None: + raise Exception("task {0} not found".format(task_id)) + task_info.status = TaskStatus.RUNNING + task_info.result = TaskResult.RUNNING + task_info.info = [] + task_info.finished = '' + failed = 0 + self.context['ocp_deployment']['failed'] = 0 if not self.context['ocp_deployment']['failed'] else self.context['ocp_deployment']['failed'] + + for c in self.obd.deploy.deploy_config.components: + step_info = TaskStepInfo(name=f'{c}-{const.DESTROY_PLUGIN}', status=TaskStatus.RUNNING, + result=TaskResult.RUNNING) + if c in self.obd.namespaces: + if self.obd.namespaces[c].get_return(const.DESTROY_PLUGIN) is not None: + task_info.status = TaskStatus.RUNNING + task_info.current = f'{c}-{const.DESTROY_PLUGIN}' + step_info.status = TaskStatus.FINISHED + if not self.obd.namespaces[c].get_return(const.DESTROY_PLUGIN): + step_info.result = TaskResult.FAILED + failed += 1 + else: + step_info.result = TaskResult.SUCCESSFUL + task_info.info.append(step_info) + task_info.finished += f'{c}-{const.DESTROY_PLUGIN} ' + + for component in self.obd.deploy.deploy_config.components: + if component in self.obd.namespaces: + for plugin in const.INIT_PLUGINS: + task_info.current = f'{component}-{plugin}' + step_info = TaskStepInfo(name=f'{component}-{plugin}', status=TaskStatus.RUNNING, result=TaskResult.RUNNING) + if self.obd.namespaces[component].get_return(plugin) is not None: + if not self.obd.namespaces[component].get_return(plugin): + failed += 1 + step_info.result = TaskResult.FAILED + else: + step_info.result = TaskResult.SUCCESSFUL + else: + self.context['ocp_deployment']['failed'] += 1 + step_info.status = TaskStatus.FINISHED + task_info.info.append(step_info) + task_info.finished += f'{component}-{plugin} ' + + for component in self.obd.deploy.deploy_config.components: + for plugin in const.START_PLUGINS: + step_info = TaskStepInfo(name=f'{component}-{plugin}', status=TaskStatus.RUNNING, result=TaskResult.RUNNING) + task_info.current = f'{component}-{plugin}' + if component not in self.obd.namespaces: + break + if self.obd.namespaces[component].get_return(plugin) is not None: + if not self.obd.namespaces[component].get_return(plugin): + step_info.result = TaskResult.FAILED + failed += 1 + else: + step_info.result = TaskResult.SUCCESSFUL + step_info.status = TaskStatus.FINISHED + task_info.info.append(step_info) + task_info.finished += f'{component}-{plugin} ' + + if self.obd.deploy.deploy_info.status == DeployStatus.STATUS_RUNNING and self.context['process_installed'] == 'done': + task_info.result = TaskResult.SUCCESSFUL + task_info.status = TaskStatus.FINISHED + + if failed or self.context['ocp_deployment']['failed'] >= 1500: + self.context['ocp_deployment']['failed'] = 0 + task_info.result = TaskResult.FAILED + task_info.status = TaskStatus.FINISHED + return task_info + + @serial("destroy") + def destroy(self, id, background_tasks): + task_manager = task.get_task_manager() + task_info = task_manager.get_task_info(id, task_type="destroy") + if task_info is not None and task_info.status != TaskStatus.FINISHED: + raise Exception("task {0} exists and not finished".format(id)) + task_manager.del_task_info(id, task_type="destroy") + background_tasks.add_task(self._destroy_cluster, id) + self.context['ocp_deployment']['task_id'] = self.context['ocp_deployment']['task_id'] + 1 \ + if self.context['ocp_deployment']['task_id'] else 1 + task_status = TaskStatus.RUNNING.value + task_res = TaskResult.RUNNING.value + task_message = 'destroy' + ret = TaskInfo(id=self.context['ocp_deployment']['task_id'], status=task_status, result=task_res, + total='destroy', message=task_message) + self.context['task_info'][self.context['ocp_deployment'][ret.id]] = ret + return ret + + @auto_register("destroy") + def _destroy_cluster(self, id): + name = self.context['ocp_deployment_id'][id] + if not name: + raise Exception(f"no such deploy for id: {id}") + deploy = self.obd.deploy_manager.get_deploy_config(name) + if not deploy: + raise Exception("no such deploy for id: {0}".format(id)) + self.obd.set_deploy(deploy) + + repositories = self.obd.load_local_repositories(deploy.deploy_info) + self.obd.set_repositories(repositories) + self.obd.set_options(Values({'force_kill': True})) + self.obd.search_param_plugin_and_apply(repositories, deploy.deploy_config) + # set namespace return value to none before do destroy + for component in self.obd.deploy.deploy_config.components: + if component in self.obd.namespaces: + self.obd.namespaces[component].set_return(const.DESTROY_PLUGIN, None) + + ret = self.obd._destroy_cluster(deploy, repositories) + if not ret: + raise Exception("destroy cluster {0} failed".format(name)) + deploy.update_deploy_status(DeployStatus.STATUS_CONFIGURED) + self.obd.set_options(Values()) + + def get_destroy_task_info(self, id, task_id): + name = self.context['ocp_deployment_id'][id] + task_info = self.context['task_info'][self.context['ocp_deployment'][task_id]] + if task_info is None: + raise Exception("task {0} not found".format(task_id)) + task_info.status = TaskStatus.RUNNING + task_info.result = TaskResult.RUNNING + task_info.info = [] + task_info.finished = '' + + failed = 0 + for c in self.obd.deploy.deploy_config.components: + step_info = TaskStepInfo(name=f'{c}-{const.DESTROY_PLUGIN}', status=TaskStatus.RUNNING, result=TaskResult.RUNNING) + if c in self.obd.namespaces: + if self.obd.namespaces[c].get_return(const.DESTROY_PLUGIN) is not None: + task_info.status = TaskStatus.RUNNING + task_info.current = f'{c}-{const.DESTROY_PLUGIN}' + step_info.status = TaskStatus.FINISHED + if not self.obd.namespaces[c].get_return(const.DESTROY_PLUGIN): + step_info.result = TaskResult.FAILED + failed += 1 + else: + step_info.result = TaskResult.SUCCESSFUL + task_info.info.append(step_info) + task_info.finished += f'{c}-{const.DESTROY_PLUGIN} ' + if self.obd.deploy.deploy_info.status == DeployStatus.STATUS_CONFIGURED: + task_info.result = TaskResult.SUCCESSFUL + task_info.status = TaskStatus.FINISHED + + if failed: + task_info.result = TaskResult.FAILED + task_info.status = TaskStatus.FINISHED + return task_info + + def create_ocp_info(self, metadb): + deploy = self.obd.deploy + if not deploy: + raise Exception("no such deploy") + self.obd.set_deploy(deploy) + + deploy = self.obd.deploy + if not deploy: + raise Exception(f"no such deploy") + deploy_config = deploy.deploy_config + pkgs, repositories, errors = self.obd.search_components_from_mirrors(deploy_config, only_info=True) + if errors: + raise Exception("{}".format('\n'.join(errors))) + repositories.extend(pkgs) + repositories = self.obd.sort_repository_by_depend(repositories, deploy_config) + + ocp_servers = [] + for repository in repositories: + cluster_config = deploy_config.components[repository.name] + for server in cluster_config.servers: + ocp_servers.append(server.ip) + + current_version = repositories[0].version + self.context['ocp_info'][metadb.cluster_name] = OcpInfo(cluster_name=metadb.cluster_name, status=self.context['ocp_deployment_info'][self.context['id']]['status'], current_version=current_version, ocp_servers=ocp_servers) + return self.context['ocp_info'][metadb.cluster_name] + + def get_ocp_info(self, cluster_name): + if self.context['ocp_info'][cluster_name]: + return self.context['ocp_info'][cluster_name] + + @serial("upgrade_precheck") + def upgrade_precheck(self, cluster_name, background_tasks): + task_manager = task.get_task_manager() + if not cluster_name: + raise Exception(f"no such deploy for cluster_name: {cluster_name}") + task_info = task_manager.get_task_info(cluster_name, task_type="upgrade_precheck") + if task_info is not None and task_info.status != TaskStatus.FINISHED: + raise Exception(f"task {cluster_name} exists and not finished") + deploy = self.obd.deploy + if not deploy: + raise Exception(f"no such deploy: {cluster_name}") + deploy_config = deploy.deploy_config + pkgs, repositories, errors = self.obd.search_components_from_mirrors(deploy_config, only_info=True) + if errors: + raise Exception("{}".format('\n'.join(errors))) + repositories.extend(pkgs) + repositories = self.obd.sort_repository_by_depend(repositories, deploy_config) + try: + ssh_clients = self.obd.get_clients(deploy_config, repositories) + except: + deploy_config.user.username = self.context['upgrade_user'] + deploy_config.user.password = self.context['upgrade_user_password'] + ssh_clients = self.obd.get_clients(deploy_config, repositories) + deploy_config.dump() + for repository in repositories: + real_servers = set() + cluster_config = deploy_config.components[repository.name] + for server in cluster_config.servers: + if server.ip in real_servers: + raise Exception( + "Deploying multiple {} instances on the same server is not supported.'".format( + repository.name)) + return False + real_servers.add(server.ip) + self.obd.search_param_plugin_and_apply(repositories, deploy_config) + repositories = [repository for repository in repositories if repository.name in ['ocp-server', 'ocp-server-ce']] + self.obd.set_repositories(repositories) + + start_check_plugins = self.obd.search_py_script_plugin(repositories, 'upgrade_check', no_found_act='warn') + + self._upgrade_precheck(cluster_name, repositories, start_check_plugins, init_check_status=True) + info = task_manager.get_task_info(cluster_name, task_type="upgrade_check") + if info is not None and info.exception is not None: + raise info.exception + task_manager.del_task_info(cluster_name, task_type="upgrade_check") + background_tasks.add_task(self._upgrade_precheck, cluster_name, repositories, start_check_plugins, + init_check_status=False) + self.context['ocp_deployment']['task_id'] = self.context['ocp_deployment']['task_id'] + 1 if self.context['ocp_deployment'][ + 'task_id'] else 1 + task_status = TaskStatus.RUNNING.value + task_res = TaskResult.RUNNING.value + task_message = 'upgrade_check' + ret = TaskInfo(id=self.context['ocp_deployment']['task_id'], status=task_status, result=task_res, + message=task_message, total='task, machine, ob_version') + self.context['task_info'][self.context['ocp_deployment'][ret.id]] = ret + return ret + + @auto_register('upgrade_precheck') + def _upgrade_precheck(self, name, repositories, start_check_plugins, init_check_status=False): + if init_check_status: + self._init_upgrade_precheck(repositories, start_check_plugins) + else: + self._do_upgrade_precheck(repositories, start_check_plugins) + + def _init_upgrade_precheck(self, repositories, start_check_plugins): + param_check_status = {} + servers_set = set() + for repository in repositories: + if repository not in start_check_plugins: + continue + repository_status = {} + res = self.obd.call_plugin(start_check_plugins[repository], repository, init_check_status=True, meta_cursor=self.context['metadb_cursor']) + if not res and res.get_return("exception"): + raise res.get_return("exception") + servers = self.obd.deploy.deploy_config.components.get(repository.name).servers + for server in servers: + repository_status[server] = {'param': CheckStatus()} + servers_set.add(server) + param_check_status[repository.name] = repository_status + + def _do_upgrade_precheck(self, repositories, start_check_plugins): + gen_config_plugins = self.obd.search_py_script_plugin(repositories, 'generate_config') + if len(repositories) != len(gen_config_plugins): + raise Exception("param_check: config error, check stop!") + + for repository in repositories: + ret = self.obd.call_plugin(gen_config_plugins[repository], repository, generate_check=False, generate_consistent_config=True, auto_depend=True) + if ret is None: + raise Exception("generate config error") + elif not ret and ret.get_return("exception"): + raise ret.get_return("exception") + if not self.obd.deploy.deploy_config.dump(): + raise Exception('generate config dump error,place check disk space!') + + for repository in repositories: + res = self.obd.call_plugin(start_check_plugins[repository], repository, database=self.context['meta_database'] ,meta_cursor=self.context['metadb_cursor']) + if not res and res.get_return("exception"): + raise res.get_return("exception") + + def get_upgrade_precheck_result(self, cluster_name, task_id): + precheck_result = PrecheckTaskInfo() + deploy = self.obd.deploy + if not deploy: + deploy = self.obd.deploy_manager.get_deploy_config(cluster_name) + self.obd.set_deploy(deploy) + components = deploy.deploy_config.components + task_info = self.context['task_info'][self.context['ocp_deployment'][task_id]] + check_result = [] + task_info.info = [] + if not task_info: + raise Exception(f"no such task_info for task_id: {task_id}") + + all_passed = False + for component in components: + namespace_union = {} + namespace = self.obd.get_namespace(component) + if namespace: + variables = namespace.variables + if 'start_check_status' in variables.keys(): + namespace_union = util.recursive_update_dict(namespace_union, variables.get('start_check_status')) + if namespace_union: + for server, result in namespace_union.items(): + if result is None: + log.get_logger().warn("precheck for server: {} is None".format(server.ip)) + continue + all_passed = self.parse_precheck_result(component, check_result, task_info, server, result) + precheck_result.precheck_result = check_result + precheck_result.task_info = task_info + status_flag = [i.status for i in task_info.info] + log.get_logger().info('task status: %s' % status_flag) + if TaskResult.RUNNING not in status_flag: + task_info.status = TaskStatus.FINISHED + task_info.result = TaskResult.SUCCESSFUL if all_passed else TaskResult.FAILED + return precheck_result + + @serial("upgrade") + def upgrade_ocp(self, cluster_name, version, usable, background_tasks): + task_manager = task.get_task_manager() + task_info = task_manager.get_task_info(cluster_name, task_type="ocp_upgrade") + if task_info is not None and task_info.status != TaskStatus.FINISHED: + raise Exception(f"task {cluster_name} exists and not finished") + task_manager.del_task_info(cluster_name, task_type="upgrade") + self.obd.set_options(Values({"component": 'ocp-server', "version": version, "usable": usable})) + background_tasks.add_task(self._upgrade, 'id', cluster_name) + self.context['ocp_deployment']['task_id'] = self.context['ocp_deployment']['task_id'] + 1 if self.context['ocp_deployment']['task_id'] else 1 + task_status = TaskStatus.RUNNING.value + task_res = TaskResult.RUNNING.value + task_message = 'upgrade' + ret = TaskInfo(id=self.context['ocp_deployment']['task_id'], status=task_status, result=task_res, total='upgrade', message=task_message) + self.context['task_info'][self.context['ocp_deployment'][ret.id]] = ret + return ret + + @auto_register('upgrade') + def _upgrade(self, id, app_name): + self.context['upgrade']['succeed'] = None + log.get_logger().info("clean io buffer before start install") + self.buffer.clear() + log.get_logger().info("clean namespace for init") + for c in self.obd.deploy.deploy_config.components: + for plugin in const.INIT_PLUGINS: + if c in self.obd.namespaces: + self.obd.namespaces[c].set_return(plugin, None) + log.get_logger().info("clean namespace for start") + for component in self.obd.deploy.deploy_config.components: + for plugin in const.START_PLUGINS: + if component in self.obd.namespaces: + self.obd.namespaces[component].set_return(plugin, None) + + deploy = self.obd.deploy + if not deploy: + raise Exception(f"no such deploy: {app_name}") + deploy_config = deploy.deploy_config + deploy_info = deploy.deploy_info + pkgs, repositories, errors = self.obd.search_components_from_mirrors(deploy_config, only_info=True) + if errors: + raise Exception("{}".format('\n'.join(errors))) + repositories.extend(pkgs) + repositories = self.obd.sort_repository_by_depend(repositories, deploy_config) + self.obd.search_param_plugin_and_apply(repositories, deploy_config) + repositories = [repository for repository in repositories if repository.name in ['ocp-server', 'ocp-server-ce']] + self.obd.set_repositories(repositories) + setattr(self.obd.options, 'component', repositories[0].name) + + try: + if deploy_info.status == DeployStatus.STATUS_RUNNING: + if self._ocp_upgrade_use_obd(repositories, deploy): + log.get_logger().info("finish do upgrade %s", app_name) + else: + if not self._ocp_upgrade_from_new_deployment(repositories, deploy, pkgs, app_name): + self.context['upgrade']['succeed'] = False + return + log.get_logger().info("finish do upgrade %s", app_name) + self.obd.deploy.update_deploy_status(DeployStatus.STATUS_RUNNING) + self.context['upgrade']['succeed'] = True + except: + log.get_logger().info("upgrade %s failed", app_name) + self.context['upgrade']['succeed'] = False + + def _ocp_upgrade_use_obd(self, repositories, deploy): + deploy_config = deploy.deploy_config + deploy_info = deploy.deploy_info + component = getattr(self.obd.options, 'component') + version = getattr(self.obd.options, 'version') + if component == const.OCP_SERVER and (version == '4.0.3' or version == '4.2.0' or version == '4.2.1'): + component = const.OCP_SERVER_CE + deploy_config.components[const.OCP_SERVER_CE] = deploy_config.components[const.OCP_SERVER] + deploy_config._src_data[const.OCP_SERVER_CE] = deploy_config._src_data[const.OCP_SERVER] + usable = getattr(self.obd.options, 'usable', '') + disable = getattr(self.obd.options, 'disable', '') + + opt = Values() + setattr(opt, "skip_create_tenant", True) + self.obd.set_options(opt) + + current_repository = None + for current_repository in repositories: + if current_repository.version == '4.0.3': + setattr(opt, "switch_monitor_tenant_flag", 'True') + self.obd.set_options(opt) + if current_repository.name == component: + break + + if not version: + self.obd._call_stdio('error', 'Specify the target version.') + raise Exception('Specify the upgrade version.') + + if usable: + usable = usable.split(',') + if disable: + disable = disable.split(',') + + self.obd._call_stdio('verbose', 'search target version') + images = self.obd.search_images(component, version=version, disable=disable, usable=usable) + if not images: + self.obd._call_stdio('error', 'No such package %s-%s' % (component, version)) + raise Exception('No such package %s-%s' % (component, version)) + if len(images) > 1: + self.obd._call_stdio( + 'print_list', + images, + ['name', 'version', 'release', 'arch', 'md5'], + lambda x: [x.name, x.version, x.release, x.arch, x.md5], + title='%s %s Candidates' % (component, version) + ) + self.obd._call_stdio('error', 'Too many match') + raise Exception('Too many match') + + if isinstance(images[0], Repository): + pkg = self.obd.mirror_manager.get_exact_pkg(name=images[0].name, md5=images[0].md5) + if pkg: + repositories = [] + pkgs = [pkg] + else: + repositories = [images[0]] + pkgs = [] + else: + repositories = [] + pkg = self.obd.mirror_manager.get_exact_pkg(name=images[0].name, md5=images[0].md5) + pkgs = [pkg] + + install_plugins = self.obd.get_install_plugin_and_install(repositories, pkgs) + if not install_plugins: + raise Exception('install plugin error') + + dest_repository = repositories[0] + if dest_repository is None: + self.obd._call_stdio('error', 'Target version not found') + raise Exception('Target version not found') + + if dest_repository == current_repository: + self.obd._call_stdio('print', 'The current version is already %s.\nNoting to do.' % current_repository) + raise Exception('The current version is already %s.\nNoting to do.' % current_repository) + ssh_clients = self.obd.get_clients(deploy_config, [current_repository]) + cluster_config = deploy_config.components[current_repository.name] + + upgrade_repositories = [current_repository] + upgrade_repositories.append(dest_repository) + self.obd.set_repositories(upgrade_repositories) + + self.obd._call_stdio( + 'print_list', + upgrade_repositories, + ['name', 'version', 'release', 'arch', 'md5', 'mark'], + lambda x: [x.name, x.version, x.release, x.arch, x.md5, + 'start' if x == current_repository else 'dest' if x == dest_repository else ''], + title='Packages Will Be Used' + ) + + index = 1 + upgrade_ctx = { + 'route': [], + 'upgrade_repositories': [ + { + 'version': repository.version, + 'hash': repository.md5 + } for repository in upgrade_repositories + ], + 'index': 1 + } + deploy.start_upgrade(component, **upgrade_ctx) + + install_plugins = self.obd.get_install_plugin_and_install(upgrade_repositories, []) + if not install_plugins: + raise Exception('install upgrade plugin error') + + if not self.obd.install_repositories_to_servers(deploy_config, upgrade_repositories[1:], install_plugins, + ssh_clients, self.obd.options): + raise Exception('install upgrade plugin error to server') + + repository = upgrade_repositories[upgrade_ctx['index']] + repositories = [repository] + upgrade_plugin = self.obd.search_py_script_plugin(repositories, 'upgrade')[repository] + self.obd.set_repositories(repositories) + ret = self.obd.call_plugin( + upgrade_plugin, repository, + search_py_script_plugin=self.obd.search_py_script_plugin, + local_home_path=self.obd.home_path, + current_repository=current_repository, + upgrade_repositories=upgrade_repositories, + apply_param_plugin=lambda repository: self.obd.search_param_plugin_and_apply([repository], + deploy_config), + metadb_cursor=self.context['metadb_cursor'], + sys_cursor=self.context['sys_cursor'] + ) + deploy.update_upgrade_ctx(**upgrade_ctx) + if not ret: + self.obd.deploy.update_deploy_status(DeployStatus.STATUS_RUNNING) + raise Exception('call upgrade plugin error') + deploy.stop_upgrade(dest_repository) + if version == '4.2.1': + if const.OCP_SERVER in deploy_config._src_data: + del deploy_config._src_data[const.OCP_SERVER] + if const.OCP_SERVER in deploy_config.components: + del deploy_config.components[const.OCP_SERVER] + if const.OCP_SERVER in deploy_info.components: + del deploy_info.components[const.OCP_SERVER] + if const.OCEANBASE_CE in deploy_config.components: + del deploy_config.components[const.OCEANBASE_CE] + if const.OCEANBASE_CE in deploy_config._src_data and const.OBPROXY_CE not in deploy_info.components: + del deploy_config._src_data[const.OCEANBASE_CE] + if const.OCEANBASE_CE in deploy_info.components and const.OBPROXY_CE not in deploy_info.components: + del deploy_info.components[const.OCEANBASE_CE] + deploy_config.dump() + return True + + def _ocp_upgrade_from_new_deployment(self, repositories, deploy, pkgs, name): + deploy_config = deploy.deploy_config + try: + + component = getattr(self.obd.options, 'component') + version = getattr(self.obd.options, 'version') + usable = getattr(self.obd.options, 'usable', '') + disable = getattr(self.obd.options, 'disable', '') + if not version: + self.obd._call_stdio('error', 'Specify the target version.') + raise Exception('Specify the upgrade version.') + + if usable: + usable = usable.split(',') + if disable: + disable = disable.split(',') + + self.obd._call_stdio('verbose', 'search target version') + images = self.obd.search_images(component, version=version, disable=disable, usable=usable) + if not images: + self.obd._call_stdio('error', 'No such package %s-%s' % (component, version)) + raise Exception('No such package %s-%s' % (component, version)) + if len(images) > 1: + self.obd._call_stdio( + 'print_list', + images, + ['name', 'version', 'release', 'arch', 'md5'], + lambda x: [x.name, x.version, x.release, x.arch, x.md5], + title='%s %s Candidates' % (component, version) + ) + self.obd._call_stdio('error', 'Too many match') + raise Exception('Too many match') + + if isinstance(images[0], Repository): + pkg = self.obd.mirror_manager.get_exact_pkg(name=images[0].name, md5=images[0].md5) + if pkg: + repositories = [] + pkgs = [pkg] + else: + repositories = [images[0]] + pkgs = [] + else: + repositories = [] + pkg = self.obd.mirror_manager.get_exact_pkg(name=images[0].name, md5=images[0].md5) + pkgs = [pkg] + + self.obd.set_repositories(repositories) + ssh_clients = self.obd.get_clients(deploy_config, repositories) + + # kill docker and ocp process on upgrade servers + for server in self.context['upgrade_servers']: + ssh_config = SshConfig(server, username=self.context['upgrade_user'], password=self.context['upgrade_user_password'], port=self.context['upgrade_ssh_port']) + ssh_client = SshClient(ssh_config) + log.get_logger().info("kill ocp process on host: {}".format(server)) + kill_docker_res = ssh_client.execute_command("sudo docker ps | grep ocp-all-in-one | awk '{print $1}' | xargs sudo docker stop") + log.get_logger().info("stop container get result {0} {1} {2}".format(kill_docker_res.code, kill_docker_res.stdout, kill_docker_res.stderr)) + kill_process_res = ssh_client.execute_command("ps -ef | grep java | grep 'ocp-server.jar' | grep -v grep | awk '{print $2}' | xargs kill -9 ") + log.get_logger().info("stop ocp process get result {0} {1} {2}".format(kill_process_res.code, kill_process_res.stdout, kill_process_res.stderr)) + + install_plugins = self.obd.get_install_plugin_and_install(repositories, pkgs) + if not install_plugins: + return False + if not self.obd.install_repositories_to_servers(deploy_config, repositories[1:], install_plugins, + ssh_clients, self.obd.options): + return False + start_success = True + repositories = list(set(repositories)) + for repository in repositories: + opt = Values() + setattr(opt, "components", repository.name) + setattr(opt, "strict_check", False) + setattr(opt, "clean", True) + setattr(opt, "force", True) + self.obd.set_options(opt) + log.get_logger().info('begin deploy') + ret = self.obd.deploy_cluster(name) + log.get_logger().info('finished deploy') + if not ret: + log.get_logger().error("failed to deploy component: %s", repository.name) + raise Exception("failed to deploy component: %s", repository.name) + opt = Values() + setattr(opt, "skip_create_tenant", True) + setattr(opt, "without_ocp_parameter", True) + self.obd.set_options(opt) + log.get_logger().info('begin start ocp') + ret = self.obd.start_cluster(name) + log.get_logger().info('finished start ocp') + if not ret: + log.get_logger().error("failed to start component: %s", repository.name) + raise Exception("failed to deploy component: %s", repository.name) + return True + except Exception as e: + return False + + def get_ocp_upgrade_task(self, cluster_name, task_id): + task_info = self.context['task_info'][self.context['ocp_deployment'][task_id]] + if task_info is None: + raise Exception("task {0} not found".format(task_id)) + task_info.status = TaskStatus.RUNNING + task_info.result = TaskResult.RUNNING + task_info.info = [] + task_info.finished = '' + + self.context['ocp_upgrade']['failed'] = 0 if not self.context['ocp_upgrade']['failed'] else self.context['ocp_upgrade']['failed'] + for component in self.obd.deploy.deploy_config.components: + plugin = const.UPGRADE_PLUGINS + step_info = TaskStepInfo(name=f'{component}-{plugin}', status=TaskStatus.RUNNING, result=TaskResult.RUNNING) + task_info.current = f'{component}-{plugin}' + if component not in self.obd.namespaces: + break + if self.obd.namespaces[component].get_return('stop') is not None: + log.get_logger().info('stop: %s' % self.obd.namespaces[component].get_return('stop')) + if not self.obd.namespaces[component].get_return('stop'): + step_info.result = TaskResult.FAILED + else: + step_info.result = TaskResult.SUCCESSFUL + step_info.status = TaskStatus.FINISHED + else: + self.context['ocp_upgrade']['failed'] += 1 + + if self.obd.namespaces[component].get_return('start') is not None: + log.get_logger().info('start: %s' % self.obd.namespaces[component].get_return('start')) + if not self.obd.namespaces[component].get_return('start'): + step_info.result = TaskResult.FAILED + else: + step_info.result = TaskResult.SUCCESSFUL + step_info.status = TaskStatus.FINISHED + else: + self.context['ocp_upgrade']['failed'] += 1 + + if self.obd.namespaces[component].get_return('display') is not None: + log.get_logger().info('display: %s' % self.obd.namespaces[component].get_return('display')) + if not self.obd.namespaces[component].get_return('display'): + step_info.result = TaskResult.FAILED + else: + step_info.result = TaskResult.SUCCESSFUL + step_info.status = TaskStatus.FINISHED + else: + self.context['ocp_upgrade']['failed'] += 1 + + task_info.info.append(step_info) + task_info.finished += f'{component}-{plugin} ' + + status_flag = [i.result for i in task_info.info] + if TaskResult.FAILED in status_flag or self.context['ocp_upgrade']['failed'] >= 3000 or self.context['upgrade']['succeed'] is False: + task_info.result = TaskResult.FAILED + task_info.status = TaskStatus.FINISHED + + if self.obd.deploy.deploy_info.status == DeployStatus.STATUS_RUNNING and self.context['upgrade']['succeed']: + task_info.result = TaskResult.SUCCESSFUL + task_info.status = TaskStatus.FINISHED + return task_info + + def get_installed_ocp_info(self, id): + config = self.context['ocp_deployment_info'][id]['config'] + servers = config.components.ocpserver.servers + port = config.components.ocpserver.port + password = config.components.ocpserver.admin_password + address = ['http://' + str(server) + ':' + str(port) for server in servers] + return OcpInstalledInfo(url=address, password=password) + + def get_not_upgrade_host(self): + sql = "select inner_ip_address, ssh_port, version from {0}.compute_host, " \ + "{0}.compute_host_agent where compute_host.id = compute_host_agent.host_id".format(self.context['meta_database']) + log.get_logger().info('sql: %s' % sql) + ret = self.context['metadb_cursor'].fetchall(sql) + + data = OcpUpgradeLostAddress(address=[]) + if ret is False: + raise Exception('error get cursor') + if ret: + log.get_logger().info('ret: %s' % ret) + for _ in ret: + data.address.append(_['inner_ip_address']) + return data + + + + diff --git a/service/handler/service_info_handler.py b/service/handler/service_info_handler.py index 0dc0687..74c549f 100644 --- a/service/handler/service_info_handler.py +++ b/service/handler/service_info_handler.py @@ -17,11 +17,25 @@ # You should have received a copy of the GNU General Public License # along with OceanBase Deploy. If not, see . -from _deploy import UserConfig -from service.handler.base_handler import BaseHandler +import re +import os +import copy from singleton_decorator import singleton -from service.model.service_info import ServiceInfo +from _deploy import UserConfig, DeployStatus +from tool import Cursor, NetUtil +from ssh import LocalClient, SshConfig, SshClient +from service.handler.base_handler import BaseHandler +from service.common import log, const +from service.model.service_info import ServiceInfo, DeployName +from service.model.server import OcpServerInfo, InstallerMode, ComponentInfo, MsgInfo +from service.model.metadb import DatabaseConnection +from service.model.ocp import OcpDeploymentConfig +from service.model.deployments import OCPDeploymnetConfig, OcpServer, OcpComponentConfig, Auth +from service.model.parameter import Parameter +from service.model.ssh import SshAuth +from service.model.tenant import TenantConfig, TenantUser, TenantResource +from service.handler.ocp_handler import OcpHandler @singleton @@ -31,3 +45,265 @@ def get_service_info(self): info = ServiceInfo(user=UserConfig.DEFAULT.get('username')) return info + def version_convert_to_int(self, version): + return int(version.split('.')[0]) * 1000 ** 2 + int(version.split('.')[1]) * 1000 + int( + version.split('.')[2]) + + def version_compare(self, v1, v2): + v1_int = self.version_convert_to_int(v1) + v2_int = self.version_convert_to_int(v2) + return v1_int - v2_int + + def install_repositories(self): + pkgs = self.obd.mirror_manager.get_pkgs_info('ocp-server') + versions = [pkg.version for pkg in pkgs] + return versions + + def execute_command_in_docker(self, contain_id, shell_command): + return LocalClient.execute_command( + "sudo docker exec %s bash -c '%s'" % (contain_id, shell_command)).stdout.strip() + + def get_missing_required_parameters(self, parameters): + results = [] + for key in ["jdbc_url", "jdbc_username", "jdbc_password"]: + if parameters.get(key) is None: + results.append(key) + return results + + def get_ocp_depend_config(self, cluster_config, stdio): + # depends config + env = {} + depend_observer = False + depend_info = {} + ob_servers_conf = {} + for comp in ["oceanbase", "oceanbase-ce"]: + ob_zones = {} + if comp in cluster_config.depends: + depend_observer = True + ob_servers = cluster_config.get_depend_servers(comp) + for ob_server in ob_servers: + ob_servers_conf[ob_server] = ob_server_conf = cluster_config.get_depend_config(comp, ob_server) + if 'server_ip' not in depend_info: + depend_info['server_ip'] = ob_server.ip + depend_info['mysql_port'] = ob_server_conf['mysql_port'] + depend_info['root_password'] = ob_server_conf['root_password'] + zone = ob_server_conf['zone'] + if zone not in ob_zones: + ob_zones[zone] = ob_server + break + for comp in ['obproxy', 'obproxy-ce']: + if comp in cluster_config.depends: + obproxy_servers = cluster_config.get_depend_servers(comp) + obproxy_server = obproxy_servers[0] + obproxy_server_config = cluster_config.get_depend_config(comp, obproxy_server) + depend_info['server_ip'] = obproxy_server.ip + depend_info['mysql_port'] = obproxy_server_config['listen_port'] + break + + for server in cluster_config.servers: + server_config = copy.deepcopy(cluster_config.get_server_conf_with_default(server)) + original_server_config = cluster_config.get_original_server_conf(server) + missed_keys = self.get_missing_required_parameters(original_server_config) + if missed_keys: + if 'jdbc_url' in missed_keys and depend_observer: + server_config['jdbc_url'] = 'jdbc:oceanbase://{}:{}/{}'.format(depend_info['server_ip'], + depend_info['mysql_port'], + server_config['ocp_meta_db']) + server_config['jdbc_username'] = '%s@%s' % ( + server_config['ocp_meta_username'], server_config['ocp_meta_tenant']['tenant_name']) + server_config['jdbc_password'] = server_config['ocp_meta_password'] + server_config['root_password'] = depend_info.get('root_password', '') + env[server] = server_config + return env + + def generate_config(self, cluster_name): + log.get_logger().info('do command upgrade with context: {}'.format(self.context)) + servers = self.context['upgrade_servers'] + if len(servers) == 0: + raise Exception("no server to upgrade") + ssh_port = self.context['upgrade_ssh_port'] + username = self.context['upgrade_user'] + password = self.context['upgrade_user_password'] + log.get_logger().info('use command to get info') + + # get monitordb connection info from metadb + monitor_user_config = self.context['metadb_cursor'].fetchone("select default_value, value from {0}.config_properties where `key` = 'ocp.monitordb.username'".format(self.context['connection_info'][cluster_name].database)) + monitor_user = monitor_user_config['value'] if monitor_user_config['value'] else monitor_user_config['default_value'] + monitor_password_config = self.context['metadb_cursor'].fetchone("select default_value, value from {0}.config_properties where `key` = 'ocp.monitordb.password'".format(self.context['connection_info'][cluster_name].database)) + monitor_password = monitor_password_config['value'] if monitor_password_config['value'] else monitor_password_config['default_value'] + monitor_database_config = self.context['metadb_cursor'].fetchone("select default_value, value from {0}.config_properties where `key` = 'ocp.monitordb.database'".format(self.context['connection_info'][cluster_name].database)) + monitor_database = monitor_database_config['value'] if monitor_database_config['value'] else monitor_database_config['default_value'] + log.get_logger().info('successfully get monior config from metadb') + + server_port_config = self.context['metadb_cursor'].fetchone("select default_value, value from {0}.config_properties where `key` = 'server.port'".format(self.context['connection_info'][cluster_name].database)) + server_port = server_port_config['value'] if server_port_config['value'] else server_port_config['default_value'] + log.get_logger().info('successfully get ocp-server port: %s' % server_port) + + # get memory info and home_path using ssh client + ssh_config = SshConfig(servers[0], username=self.context['upgrade_user'], password=self.context['upgrade_user_password'], port=self.context['upgrade_ssh_port']) + ssh_client = SshClient(ssh_config) + res = ssh_client.execute_command("ps -ef | grep java | grep 'ocp-server.*.jar' | grep -v grep") + if not res: + raise Exception("failed to query ocp process info") + memory_xmx = res.stdout.split("Xmx")[1].split(" ")[0] + home_path = res.stdout.split("/lib/ocp-server")[0].split(' ')[-1] + + # check whether ocp docker exists + res = ssh_client.execute_command("sudo docker ps | grep ocp-all-in-one ") + if res: + log.get_logger().info("found ocp docker") + home_path = "/home/{0}/ocp-server".format(self.context['upgrade_user']) if self.context['upgrade_user'] != 'root' else "/root/ocp-server" + auth = Auth(user=username, port=ssh_port, password=password) + jdbc_username = self.context['connection_info'][cluster_name].user + user_name = jdbc_username.split('@')[0] + tenant_name = jdbc_username.split('@')[1].split('#')[0] if '#' in jdbc_username else jdbc_username.split('@')[1] + tenant_user = TenantUser(tenant_name=tenant_name, user_name=user_name, user_database=self.context['connection_info'][cluster_name].database) + meta_tenant = TenantConfig(name=tenant_user, password=self.context['connection_info'][cluster_name].password) + + monitor_tenant_name = monitor_user.split('@')[1].split('#')[0] if '#' in monitor_user else monitor_user.split('@')[1] + monitor_tenant_username = monitor_user.split('@')[0] + monitor_tenant_user = TenantUser(tenant_name=monitor_tenant_name, user_name=monitor_tenant_username, user_database=monitor_database) + monitor_tenant = TenantConfig(name=monitor_tenant_user, password=monitor_password) + ocp_server = OcpServer(component='ocp-server-ce', metadb=self.context['connection_info'][cluster_name], meta_tenant=meta_tenant, monitor_tenant=monitor_tenant, admin_password='********', + home_path=home_path, servers=servers, port=server_port, memory_size=memory_xmx) + components = OcpComponentConfig(ocpserver=ocp_server) + data = OCPDeploymnetConfig(auth=auth, components=components) + log.get_logger().info('create deployment config: %s' % data) + + ocp_handler = OcpHandler() + try: + cluster_config_yaml_path = ocp_handler.create_ocp_config_path(data) + log.get_logger().info('upgrade path: %s' % cluster_config_yaml_path) + deployment_id = ocp_handler.create_ocp_deployment(cluster_name, cluster_config_yaml_path) + log.get_logger().info('upgrade id: %s' % deployment_id) + except Exception as ex: + log.get_logger().error(ex) + + def create_ocp_info(self, cluster_name): + deploy = self.obd.deploy_manager.get_deploy_config(cluster_name) + log.get_logger().info('deploy: %s' % deploy) + if deploy and deploy.deploy_info.status in [DeployStatus.STATUS_RUNNING, DeployStatus.STATUS_UPRADEING]: + deploy_config = deploy.deploy_config + if const.OCP_SERVER in deploy_config.components: + cluster_config = deploy_config.components[const.OCP_SERVER] + global_config = cluster_config.get_global_conf() + if not global_config.get('ocp_meta_username', ''): + jdbc_url = global_config['jdbc_url'] + matched = re.match(r"^jdbc:\S+://(\S+?)(|:\d+)/(\S+)", jdbc_url) + if matched: + cluster_config.update_global_conf('ocp_meta_db', matched.group(3)) + cluster_config.update_global_conf('ocp_meta_username', global_config['jdbc_username'].split('@')[0]) + cluster_config.update_global_conf('ocp_meta_password', global_config['jdbc_password']) + cluster_config.update_global_conf('ocp_meta_tenant', + {'tenant_name': global_config['jdbc_username'].split('@')[1]}) + self.obd.set_deploy(deploy) + else: + self.generate_config(cluster_name) + + def get_deployments_name(self): + deploys = self.obd.deploy_manager.get_deploy_configs() + log.get_logger().info('deploys: %s' % deploys) + ret = DeployName() + for _ in deploys: + if _.deploy_info.status == DeployStatus.STATUS_RUNNING and \ + (const.OCP_SERVER in _.deploy_config.components or const.OCP_SERVER_CE in _.deploy_config.components): + ret.name.append(_.name) + return ret + + def get_metadb_connection(self, name): + metadb = DatabaseConnection(cluster_name=name) + deploy = self.obd.deploy_manager.get_deploy_config(name) + log.get_logger().info('deploys: %s' % deploy) + if deploy is None: + res = LocalClient.execute_command("sudo docker ps | grep ocp-all-in-one | awk '{print $1}'").stdout.strip() + log.get_logger().info('docker ps: %s' % res) + if res: + metadb.host = self.execute_command_in_docker(res, 'env | grep OCP_METADB_HOST').split('=')[1] + metadb.port = self.execute_command_in_docker(res, 'env | grep OCP_METADB_PORT').split('=')[1] + metadb.user = self.execute_command_in_docker(res, 'env | grep OCP_METADB_USER').split('=')[1] + metadb.password = self.execute_command_in_docker(res, 'env | grep OCP_METADB_PASSWORD').split('=')[1] + metadb.database = self.execute_command_in_docker(res, 'env | grep OCP_METADB_DBNAME').split('=')[1] + try: + self.context['metadb_cursor'] = Cursor(ip=metadb.host, port=metadb.port, user=metadb.user, + password=metadb.password, stdio=self.obd.stdio) + except: + log.get_logger().error('Automatic database connection failed, please input manually.') + metadb_copy = copy.deepcopy(metadb) + metadb_copy.password = '' + return metadb_copy + return metadb + deploy_config = deploy.deploy_config + if const.OCP_SERVER in deploy_config.components: + cluster_config = deploy_config.components[const.OCP_SERVER] + elif const.OCP_SERVER_CE in deploy_config.components: + cluster_config = deploy_config.components[const.OCP_SERVER_CE] + else: + return metadb + servers = cluster_config.servers + start_env = self.get_ocp_depend_config(cluster_config, self.obd.stdio) + for server in servers: + server_config = start_env[server] + jdbc_url = server_config['jdbc_url'] + metadb.user = server_config['jdbc_username'] + metadb.password = server_config['jdbc_password'] + matched = re.match(r"^jdbc:\S+://(\S+?)(|:\d+)/(\S+)", jdbc_url) + if matched: + metadb.host = matched.group(1) + metadb.port = int(matched.group(2)[1:]) + metadb.database = matched.group(3) + if server_config.get('ocp_meta_tenant', ''): + if 'sys' in metadb.user: + try: + self.context['sys_cursor'] = Cursor(ip=metadb.host, port=metadb.port, user=metadb.user, password=metadb.password, stdio=self.obd.stdio) + except: + log.get_logger().error('Automatic database connection failed, please input manually.') + metadb.user = server_config['ocp_meta_username'] + '@' + server_config['ocp_meta_tenant']['tenant_name'] + metadb.password = server_config['ocp_meta_password'] + metadb.database = server_config['ocp_meta_db'] + self.context["connection_info"][metadb.cluster_name] = metadb + try: + self.context['metadb_cursor'] = Cursor(ip=metadb.host, port=metadb.port, user=metadb.user, password=metadb.password, stdio=self.obd.stdio) + except: + log.get_logger().error('Automatic database connection failed, please input manually.') + break + metadb_copy = copy.deepcopy(metadb) + metadb_copy.password = '' + return metadb_copy + + def get_component_agent(self, metadb): + try: + user = '' + self.context["connection_info"][metadb.cluster_name] = metadb + self.context['meta_database'] = metadb.database + self.context['metadb_cursor'] = Cursor(ip=metadb.host, port=metadb.port, user=metadb.user, password=metadb.password, + stdio=self.obd.stdio) + log.get_logger().info('cursor: %s' % self.context['metadb_cursor']) + monitor_tenant_sql = "select `value` from %s.config_properties where `key` = 'ocp.monitordb.username'" % metadb.database + monitor_tenant = self.context['metadb_cursor'].fetchone(monitor_tenant_sql, raise_exception=True) + log.get_logger().info('monitor_tenant: %s' % monitor_tenant) + tips = False + if monitor_tenant and monitor_tenant.get('value') in metadb.user: + tips = True + sql = "select id from %s.distributed_server" % metadb.database + res = self.context['metadb_cursor'].fetchall(sql, raise_exception=True) + log.get_logger().info('ocp server ip: %s' % res) + component_servers = [] + component_info = [] + for _ in res: + component_servers.append(_['id'].split(':')[0]) + component_info.append(ComponentInfo(name=const.OCP_SERVER_CE, ip=component_servers)) + ocp_version = self.context['metadb_cursor'].fetchone( + "select `value` from %s.config_properties where `key` = 'ocp.version'" % metadb.database, raise_exception=True)['value'] + log.get_logger().info('ocp version: %s' % ocp_version) + log.get_logger().info('get obd user') + deploy = self.obd.deploy_manager.get_deploy_config(metadb.cluster_name) + log.get_logger().info('deploy: %s' % deploy) + if deploy and deploy.deploy_info.status in [DeployStatus.STATUS_RUNNING, DeployStatus.STATUS_UPRADEING]: + deploy_config = deploy.deploy_config + user = deploy_config.user.username + return OcpServerInfo(user=user, ocp_version=ocp_version, component=component_info, tips=tips) + except Exception as e: + log.get_logger().error('failed to get ocp info: %s' % e) + log.get_logger().error('Please ensure the use of the meta tenant.') + raise Exception('Failed to get ocp info, Please ensure the use of the meta tenant.') + diff --git a/service/middleware/ip_white.py b/service/middleware/ip_white.py new file mode 100644 index 0000000..2640086 --- /dev/null +++ b/service/middleware/ip_white.py @@ -0,0 +1,41 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . +import re + +from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint +from starlette.requests import Request +from starlette.exceptions import HTTPException + + +class IPBlockMiddleware(BaseHTTPMiddleware): + def __init__(self, app, ips): + self.app = app + self.ip_whitelist = ips + super().__init__(app) + + async def dispatch(self, request: Request, call_next: RequestResponseEndpoint): + remote_ip = request.client.host + if self.ip_whitelist: + for ip_regx in self.ip_whitelist: + if re.match(ip_regx, remote_ip): + break + else: + raise HTTPException(status_code=403, detail="Forbidden IP") + response = await call_next(request) + return response \ No newline at end of file diff --git a/service/model/backup.py b/service/model/backup.py new file mode 100644 index 0000000..7b93542 --- /dev/null +++ b/service/model/backup.py @@ -0,0 +1,28 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . +from typing import List, Optional +from enum import auto +from fastapi_utils.enums import StrEnum +from pydantic import BaseModel + + +class BackupMethod(StrEnum): + DUMP = auto() + DATA_BACKUP = auto() + diff --git a/service/model/database.py b/service/model/database.py new file mode 100644 index 0000000..2452e70 --- /dev/null +++ b/service/model/database.py @@ -0,0 +1,33 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . +from typing import List, Optional +from enum import auto +from fastapi import Body +from fastapi_utils.enums import StrEnum +from pydantic import BaseModel + + +class DatabaseConnection(BaseModel): + cluster_name = Body('', description="cluster name of the connection in installer") + host: str = Body('', description="host") + port: int = Body(0, description="port") + user: str = Body('', description="user") + password: str = Body('', description="password") + database: str = Body('oceanbase', description="database") + diff --git a/service/model/deployments.py b/service/model/deployments.py index ee73333..ab4c310 100644 --- a/service/model/deployments.py +++ b/service/model/deployments.py @@ -25,6 +25,8 @@ from fastapi_utils.enums import StrEnum from service.common.task import TaskStatus, TaskResult +from service.model.tenant import TenantConfig +from service.model.database import DatabaseConnection class Auth(BaseModel): @@ -33,6 +35,10 @@ class Auth(BaseModel): port: int = Body(22, description='ssh port') +class UserCheck(Auth): + servers: List[str] = Body(..., description="server ip, ex:[ '1.1.1.1','2.2.2.2']") + + class PrecheckTaskResult(StrEnum): PASSED = auto() FAILED = auto() @@ -58,6 +64,7 @@ class OceanbaseServers(BaseModel): ip: str = Body(..., description='server ip') parameters: dict = None + class Zone(BaseModel): name: str = Body(..., description='zone name') rootservice: str = Body(..., description='root service') @@ -232,4 +239,49 @@ class Config: orm_mode = True +class OCPDeploymentStatus(StrEnum): + INIT = auto() + DEPLOYING = auto() + FINISHED = auto() + + +class ClusterManageInfo(BaseModel): + machine: Optional[int] = Body(None, description='manage machine num') + + +class OcpServer(BaseModel): + component: str = Body('ocp-server', description='ocp-server component name') + version: str = Body('', description='version') + package_hash: str = Body('', description='ocp-server package md5') + release: str = Body('', description='ocp-server release no') + home_path: str = Body('', description='install ocp-server home path') + soft_dir: str = Body('', description='software path') + log_dir: str = Body('', description='log dir') + ocp_site_url: str = Body('', description='ocp server url') + port: int = Body(..., description='server port') + admin_password: str = Body(..., description='admin password') + parameters: List[Parameter] = Body(None, description='config parameter') + memory_size: str = Body('2G', description='ocp server memory size') + ocp_cpu: int = Body(0, description='ocp server cpu num') + meta_tenant: Optional[TenantConfig] = Body(None, description="meta tenant config") + monitor_tenant: Optional[TenantConfig] = Body(None, description="monitor tenant config") + manage_info: Optional[ClusterManageInfo] = Body(None, description='manage cluster info') + servers: List[str] = Body(..., description="server ip, ex:[ '1.1.1.1','2.2.2.2']") + metadb: Optional[DatabaseConnection] = Body(None, description="connection info of metadb") + + +class OcpComponentConfig(BaseModel): + oceanbase: Optional[OceanBase] + obproxy: Optional[ObProxy] + ocpserver: OcpServer + + +class OCPDeploymnetConfig(BaseModel): + auth: Auth + components: OcpComponentConfig + home_path: str = Body('', description='global home path') + launch_user: Optional[str] = Body(None, description='process user') + + + diff --git a/service/model/metadb.py b/service/model/metadb.py new file mode 100644 index 0000000..3c89ae4 --- /dev/null +++ b/service/model/metadb.py @@ -0,0 +1,69 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . +from typing import List, Optional +from enum import auto, Enum +from fastapi import Body +from fastapi_utils.enums import StrEnum +from pydantic import BaseModel + +from service.model.ssh import SshAuth +from service.model.database import DatabaseConnection +from service.model.parameter import Parameter +from service.model.deployments import OCPDeploymentStatus + + +class PrecheckTaskResult(StrEnum): + PASSED = auto() + FAILED = auto() + RUNNING = auto() + + +class Flag(Enum): + not_matched = 0 + same_disk = 1 + data_and_log_same_disk = 2 + home_data_or_home_log_same_disk = 3 + data_log_different_disk = 4 + + +class MetadbDeploymentConfig(BaseModel): + auth: SshAuth = Body(None, description="ssh auth info") + cluster_name: str = Body("obcluster", description="cluster name") + servers: List[str] = Body(..., description = "servers to deploy") + root_password: str = Body("", description="password of user root@sys") + home_path: str = Body("", description="home path to install") + data_dir: Optional[str] = Body("", description="data directory") + log_dir: Optional[str] = Body("", description="log directory") + sql_port: int = Body(2881, description="sql port") + rpc_port: int = Body(2882, description="rpc port") + devname: str = Body('', description='devname') + parameters: Optional[List[Parameter]] = Body(None, description='config parameter') + + +class MetadbDeploymentInfo(BaseModel): + id: int = Body(0, description="metadb deployment id") + status: OCPDeploymentStatus = Body(OCPDeploymentStatus.INIT, description="metadb deployment status, ex: INIT, FINISHED") + config: MetadbDeploymentConfig = Body(None, description="metadb deployment") + connection: Optional[DatabaseConnection] = Body(None, description="connection info of metadb") + + +class RecoverChangeParameter(BaseModel): + name: str = Body(..., description='repaired item') + old_value: str = Body(None, description='old value item') + new_value: str = Body(None, description='new value item') diff --git a/service/model/ocp.py b/service/model/ocp.py new file mode 100644 index 0000000..de87cd9 --- /dev/null +++ b/service/model/ocp.py @@ -0,0 +1,109 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . +from typing import List, Optional, Union +from enum import auto +from fastapi import Body +from fastapi_utils.enums import StrEnum +from pydantic import BaseModel + +from service.model.ssh import SshAuth +from service.model.parameter import Parameter +from service.model.deployments import OCPDeploymentStatus +from service.model.tenant import TenantConfig +from service.model.resource import ServerResource +from service.model.task import TaskStatus, TaskResult +from service.model.database import DatabaseConnection +from service.model.backup import BackupMethod + + +class OcpDeploymentConfig(BaseModel): + auth: SshAuth = Body(None, description="ssh auth info") + metadb: Union[int, DatabaseConnection] = Body(..., description="connection info of metadb") + meta_tenant: Optional[TenantConfig] = Body(None, description="meta tenant config") + monitor_tenant: Optional[TenantConfig] = Body(None, description="monitor tenant config") + appname: str = Body("ocp", description="ocp app name") + admin_password: str = Body('', description="ocp login password") + servers: List[str] = Body(..., description="servers to deploy") + home_path: str = Body("", description="home path to install") + server_port: int = Body(8080, description="server port") + parameters: Optional[List[Parameter]] + + +class OcpDeploymentInfo(BaseModel): + id: int = Body(0, description="metadb deployment id") + status: OCPDeploymentStatus = Body(OCPDeploymentStatus.INIT, description="ocp deployment status, ex: INIT, DEPLOYING, FINISHED") + config: Optional[OcpDeploymentConfig] = Body(..., description="ocp deployment config") + monitor_display: bool = Body(True, description="monitor tenant configured") + + +class ObserverResource(BaseModel): + address: str = Body(..., description="observer address") + cpu_total: float = Body(..., description="total cpu") + cpu_free: float = Body(..., description="free cpu") + memory_total: int = Body(..., description="total memory size") + memory_free: int = Body(..., description="free memory size") + + +class MetadbResource(BaseModel): + servers: List[ObserverResource] = Body(..., description="observer resource") + + +class OcpResource(BaseModel): + servers: List[ServerResource] = Body(..., description="server resource") + metadb: MetadbResource = Body(..., description="metadb resource") + + +class OcpDeploymentReport(BaseModel): + status: TaskStatus = Body(..., description="task status") + result: TaskResult = Body(..., description="task result") + servers: List[str] = Body(..., description="ocp server addresses") + user: str = Body(..., description="ocp admin user") + password: str = Body(..., description="ocp admin password") + + +class OcpInfo(BaseModel): + cluster_name: str = Body('', description="ocp deployment cluster_name") + status: OCPDeploymentStatus = Body(OCPDeploymentStatus.INIT, description="ocp deployment status, ex:INIT, FINISHED") + current_version: str = Body(..., description="current ocp version") + ocp_servers: List[str] = Body(..., description="ocp servers") + agent_servers: List[str] = Body(None, description="servers deployed agent") + + +class OcpBackupConfig(BaseModel): + method: BackupMethod = Body(BackupMethod.DUMP, description="backup method, ex: DUMP, DATA_BACKUP") + destination: str = Body(..., description="backup destination") + tenants: List[str] = Body(..., description="backup tenants") + root_password: Optional[str] = Body(..., description="root password of metadb") + + +class OcpBackupInfo(BaseModel): + id: int = Body(0, description="backup id") + status: OCPDeploymentStatus = Body(OCPDeploymentStatus.INIT, description="backup status, ex: INIT, RUNNING, FINISHED") + config: OcpBackupConfig = Body(..., description="backup config") + + +class OcpInstalledInfo(BaseModel): + url: List[str] = Body(..., description="Access address, eq: ip:port") + account: str = Body('admin', description="account") + password: str = Body(..., description="account password") + + +class OcpUpgradeLostAddress(BaseModel): + address: List[str] = Body([], description="lost ip address") + diff --git a/service/model/parameter.py b/service/model/parameter.py new file mode 100644 index 0000000..9aeb360 --- /dev/null +++ b/service/model/parameter.py @@ -0,0 +1,29 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . +from typing import List, Optional +from enum import auto +from fastapi import Body +from fastapi_utils.enums import StrEnum +from pydantic import BaseModel + + +class Parameter(BaseModel): + name: str = Body(..., description="parameter name") + value: str = Body(..., description="parameter value") + diff --git a/service/model/resource.py b/service/model/resource.py new file mode 100644 index 0000000..01d42cd --- /dev/null +++ b/service/model/resource.py @@ -0,0 +1,61 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . +from typing import List +from fastapi import Body +from pydantic import BaseModel + + +class DiskInfo(BaseModel): + dev: str = Body(..., description="dev") + mount_path: str = Body(..., description="mount path") + total_size: str = Body(..., description="total size") + free_size: str = Body(..., description="free size") + + +class ServerResource(BaseModel): + address: str = Body(..., description="server address") + cpu_total: float = Body(..., description="total cpu") + cpu_free: float = Body(..., description="free cpu") + memory_total: str = Body(..., description="total memory size") + memory_free: str = Body(..., description="free memory size") + disk: List[DiskInfo] = Body(..., description="disk info") + + +class Disk(BaseModel): + path: str = Body(..., description="path") + disk_info: DiskInfo = Body(..., description="disk info") + + +class MetaDBResource(BaseModel): + address: str = Body(..., description="server address") + disk: List[Disk] = Body(..., description="path: disk_info") + memory_limit_lower_limit: int = Body(..., description="memory_limit lower limit") + memory_limit_higher_limit: int = Body(..., description="memory_limit higher limit") + memory_limit_default: int = Body(..., description="default memory_limit") + data_size_default: int = Body(..., description="default data size") + log_size_default: int = Body(..., description="default log size") + flag: int = Body(..., description="which solution to use") + + +class ResourceCheckResult(BaseModel): + address: str = Body(..., description='server ip') + name: str = Body(..., description="resource check type name, eq memory_limit, data_dir, home_path, log_dir..") + check_result: bool = Body(True, description="check result, true/false") + error_message: List[str] = Body([], description='error message, eq path not enough') + diff --git a/service/model/server.py b/service/model/server.py new file mode 100644 index 0000000..0e500d1 --- /dev/null +++ b/service/model/server.py @@ -0,0 +1,36 @@ +from fastapi import Body +from fastapi_utils.enums import StrEnum +from typing import List, Optional +from pydantic import BaseModel +from enum import auto + +from service.model.metadb import DatabaseConnection + + +class InstallerMode(StrEnum): + STANDARD = auto() + COMPACT = auto() + + +class ComponentInfo(BaseModel): + name: str = Body("ocp-server", description="ocp component") + ip: List[str] = Body([], description="server address") + + +class OcpServerInfo(BaseModel): + user: str = Body('', description="deploy user") + ocp_version: str = Body('', description="ocp-server current version") + component: List[ComponentInfo] = Body([], description="component info") + tips: bool = Body(False, description='display tips') + msg: str = Body('', description="failed message") + + +class MsgInfo(BaseModel): + msg: str = Body(..., description="failed message") + status: int = Body(..., description='eq: 0, 1') + + +class UserInfo(BaseModel): + username: str = Body(..., description='system user') + + diff --git a/service/model/service_info.py b/service/model/service_info.py index 327d98f..e1d8fb4 100644 --- a/service/model/service_info.py +++ b/service/model/service_info.py @@ -19,7 +19,12 @@ from fastapi import Body from pydantic import BaseModel +from typing import List class ServiceInfo(BaseModel): user: str = Body(..., description='user name') + + +class DeployName(BaseModel): + name: List[str] = Body([], description="deploy name list") diff --git a/service/model/ssh.py b/service/model/ssh.py new file mode 100644 index 0000000..8ea9a7c --- /dev/null +++ b/service/model/ssh.py @@ -0,0 +1,38 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . +from typing import List, Optional +from enum import auto +from fastapi import Body +from fastapi_utils.enums import StrEnum +from pydantic import BaseModel + + +class SshAuthMethod(StrEnum): + PUBKEY = auto() + PASSWORD = auto() + + +class SshAuth(BaseModel): + user: str = Body("", description="username") + auth_method: SshAuthMethod = Body(SshAuthMethod.PASSWORD, description="auth method") + password: str = Body("", description="password") + private_key: str = Body("", description="private key") + port: int = Body(0, description="ssh port") + + diff --git a/service/model/task.py b/service/model/task.py new file mode 100644 index 0000000..1e1c2ce --- /dev/null +++ b/service/model/task.py @@ -0,0 +1,76 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . +from typing import List +from enum import auto +from fastapi_utils.enums import StrEnum +from fastapi import Body +from pydantic import BaseModel + + +class TaskStatus(StrEnum): + RUNNING = auto() + FINISHED = auto() + + +class TaskResult(StrEnum): + SUCCESSFUL=auto() + FAILED=auto() + RUNNING=auto() + + +class PrecheckEventResult(StrEnum): + PASSED = auto() + FAILED = auto() + RUNNING = auto() + + +class TaskStepInfo(BaseModel): + name: str = Body('', description="task step") + status: TaskStatus = Body('', description="task step status") + result: TaskResult = Body('', description="task step result") + + +class TaskInfo(BaseModel): + id: int = Body(..., description="task id") + status: TaskStatus = Body(..., description="task status") + result: TaskResult = Body(..., description="task result") + total: str = Body('port, mem, disk, ulimit, aio, net, ntp, dir, param, ssh', description="total steps") + finished: str = Body('', description="finished steps") + current: str = Body('', description="current step") + message: str = Body('', description="task message") + info: List[TaskStepInfo] = Body([], description="") + + +class PreCheckResult(BaseModel): + name: str = Body(..., description="precheck event name") + server: str = Body("", description="precheck server") + result: PrecheckEventResult = Body('', description="precheck event result") + recoverable: bool = Body(False, description="precheck event recoverable") + code: str = Body('', description="error code") + advisement: str = Body("", description="advisement of precheck event failure") + + +class PrecheckTaskInfo(BaseModel): + task_info: TaskInfo = Body('', description="task detailed info") + precheck_result: List[PreCheckResult] = Body([], description="precheck result") + + +class TaskLog(BaseModel): + log: str = Body("", description="task log content") + offset: int = Body(0, description="offset of current log") diff --git a/service/model/tenant.py b/service/model/tenant.py new file mode 100644 index 0000000..2491737 --- /dev/null +++ b/service/model/tenant.py @@ -0,0 +1,42 @@ +# coding: utf-8 +# OceanBase Deploy. +# Copyright (C) 2021 OceanBase +# +# This file is part of OceanBase Deploy. +# +# OceanBase Deploy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OceanBase Deploy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OceanBase Deploy. If not, see . +from typing import List, Optional +from enum import auto +from fastapi import Body +from fastapi_utils.enums import StrEnum +from pydantic import BaseModel + + +# only support cpu and memory currently +class TenantResource(BaseModel): + cpu: float = Body(2, description="cpu resource of a tenant") + memory: int = Body(4, description="memory resource of a tenant in GB") + + +class TenantUser(BaseModel): + tenant_name: str = Body(..., description="tenant name") + user_name: str = Body('root', description="user name") + user_database: str = Body('', description='user database') + + +class TenantConfig(BaseModel): + name: TenantUser = Body(..., description="tenant name") + password: Optional[str] = Body('', description="tenant password") + resource: Optional[TenantResource] = Body(TenantResource(), description="tenant resource") + diff --git a/ssh.py b/ssh.py index ac9264d..46a0c2d 100644 --- a/ssh.py +++ b/ssh.py @@ -40,10 +40,10 @@ from multiprocessing import Queue, Process from multiprocessing.pool import ThreadPool -from tool import COMMAND_ENV, DirectoryUtil, FileUtil +from tool import COMMAND_ENV, DirectoryUtil, FileUtil, NetUtil, Timeout from _stdio import SafeStdio from _errno import EC_SSH_CONNECT -from _environ import ENV_DISABLE_RSYNC +from _environ import ENV_DISABLE_RSYNC, ENV_DISABLE_RSA_ALGORITHMS, ENV_HOST_IP_MODE __all__ = ("SshClient", "SshConfig", "LocalClient", "ConcurrentExecutor") @@ -261,6 +261,44 @@ def get_file(local_path, remote_path, stdio=None): def get_dir(local_path, remote_path, stdio=None): return LocalClient.put_dir(remote_path, local_path, stdio=stdio) + @staticmethod + def run_command(command, env=None, timeout=None, print_stderr=True, elimit=0, olimit=0, stdio=None): + stdio.verbose('local execute: %s ' % command) + stdout = "" + process = None + try: + with Timeout(timeout): + process = Popen(command, env=LocalClient.init_env(env), shell=True, stdout=PIPE, stderr=PIPE) + while process.poll() is None: + lines = process.stdout.readline() + line = lines.strip() + if line: + stdio.print(line.decode("utf8", 'ignore')) + stderr = process.stderr.read().decode("utf8", 'ignore') + code = process.returncode + verbose_msg = 'exit code {}'.format(code) + if code != 0 and stderr: + verbose_msg += ', error output:\n' + stdio.verbose(verbose_msg) + if print_stderr: + stdio.print(stderr) + if elimit == 0: + stderr = "" + elif elimit > 0: + stderr = stderr[-elimit:] + except Exception as e: + if process: + process.terminate() + stdout = '' + stderr = str(e) + code = 255 + verbose_msg = 'exited code 255, error output:\n%s' % stderr + stdio.verbose(verbose_msg) + stdio.exception('') + finally: + if process: + process.terminate() + return SshReturn(code, stdout, stderr) class RemoteTransporter(enum.Enum): CLIENT = 0 @@ -277,6 +315,7 @@ class SshClient(SafeStdio): DEFAULT_PATH = '/sbin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:' LOCAL_HOST = ['127.0.0.1', 'localhost', '127.1', '127.0.1'] + DISABLED_ALGORITHMS = dict(pubkeys=["rsa-sha2-512", "rsa-sha2-256"]) def __init__(self, config, stdio=None): self.config = config @@ -288,13 +327,16 @@ def __init__(self, config, stdio=None): self._remote_transporter = None self.task_queue = None self.result_queue = None - self._is_local = self.is_localhost() and self.config.username == getpass.getuser() - + self._is_local = self.is_local() if self._is_local: self.env = {} else: self.env = {'PATH': self.DEFAULT_PATH} self._update_env() + + self._disabled_rsa_algorithms = None + if COMMAND_ENV.get(ENV_DISABLE_RSA_ALGORITHMS) == '1': + self._disabled_rsa_algorithms = self.DISABLED_ALGORITHMS super(SshClient, self).__init__() def _init_queue(self): @@ -346,19 +388,21 @@ def __str__(self): def is_localhost(self, stdio=None): return self.config.host in self.LOCAL_HOST - def _login(self, stdio=None): + def _login(self, stdio=None, exit=True): if self.is_connected: return True err = None try: self.ssh_client.set_missing_host_key_policy(AutoAddPolicy()) + stdio.verbose('host: %s, port: %s, user: %s, password: %s' % (self.config.host, self.config.port, self.config.username, self.config.password)) self.ssh_client.connect( self.config.host, port=self.config.port, username=self.config.username, password=self.config.password, key_filename=self.config.key_filename, - timeout=self.config.timeout + timeout=self.config.timeout, + disabled_algorithms=self._disabled_rsa_algorithms ) self.is_connected = True except AuthenticationException: @@ -371,7 +415,10 @@ def _login(self, stdio=None): stdio.exception('') err = EC_SSH_CONNECT.format(user=self.config.username, ip=self.config.host, message=e) if err: - stdio.critical(err) + if exit: + stdio.critical(err) + return err + stdio.error(err) return err return self.is_connected @@ -384,10 +431,14 @@ def _open_sftp(self, stdio=None): return True return False - def connect(self, stdio=None): + def is_local(self): + return self.is_localhost() and self.config.username == getpass.getuser() or \ + (COMMAND_ENV.get(ENV_HOST_IP_MODE, '0') == '1' and self.config.host == NetUtil.get_host_ip()) + + def connect(self, stdio=None, exit=True): if self._is_local: return True - return self._login(stdio=stdio) + return self._login(stdio=stdio, exit=exit) def reconnect(self, stdio=None): self.close(stdio=stdio) @@ -441,12 +492,13 @@ def execute_command(self, command, timeout=None, stdio=None): timeout = self.config.timeout elif timeout <= 0: timeout = None + if self._is_local: return LocalClient.execute_command(command, self.env if self.env else None, timeout, stdio=stdio) verbose_msg = '%s execute: %s ' % (self.config, command) stdio.verbose(verbose_msg, end='') - command = '%s %s;echo -e "\n$?\c"' % (self.env_str, command.strip(';').lstrip('\n')) + command = '(%s %s);echo -e "\n$?\c"' % (self.env_str, command.strip(';').lstrip('\n')) return self._execute_command(command, retry=3, timeout=timeout, stdio=stdio) @property @@ -503,7 +555,7 @@ def _put_file(self): def _client_put_file(self, local_path, remote_path, stdio=None): if self.execute_command('mkdir -p %s && rm -fr %s' % (os.path.dirname(remote_path), remote_path), stdio=stdio): stdio.verbose('send %s to %s' % (local_path, remote_path)) - if self.sftp.put(local_path, remote_path): + if self.sftp.put(local_path.replace('~', os.getenv('HOME')), remote_path.replace('~', os.getenv('HOME'))): return self.execute_command('chmod %s %s' % (oct(os.stat(local_path).st_mode)[-3:], remote_path)) return False diff --git a/tool.py b/tool.py index bc35de2..a02d814 100644 --- a/tool.py +++ b/tool.py @@ -34,14 +34,18 @@ import json import hashlib import socket +import datetime from io import BytesIO +from copy import copy import string from ruamel.yaml import YAML, YAMLContextManager, representer +from _errno import EC_SQL_EXECUTE_FAILED from _stdio import SafeStdio _open = open if sys.version_info.major == 2: + import MySQLdb as mysql from collections import OrderedDict from backports import lzma from io import open as _open @@ -60,13 +64,14 @@ def __init__(self, *args, **kwargs): else: import lzma + import pymysql as mysql encoding_open = open class OrderedDict(dict): pass -__all__ = ("timeout", "DynamicLoading", "ConfigUtil", "DirectoryUtil", "FileUtil", "YamlLoader", "OrderedDict", "COMMAND_ENV") +__all__ = ("timeout", "DynamicLoading", "ConfigUtil", "DirectoryUtil", "FileUtil", "YamlLoader", "OrderedDict", "COMMAND_ENV", "TimeUtils") _WINDOWS = os.name == 'nt' @@ -677,7 +682,8 @@ def get_host_ip(): class TimeUtils(SafeStdio): - def parse_time_sec(time_str, stdio=None): + @staticmethod + def parse_time_sec(time_str): unit = time_str[-1] value = int(time_str[:-1]) if unit == "s": @@ -689,5 +695,140 @@ def parse_time_sec(time_str, stdio=None): elif unit == "d": value *= 3600 * 24 else: - stdio.error('%s parse time to second fialed:' % (time_str)) - return int(value) \ No newline at end of file + raise Exception('%s parse time to second fialed:' % (time_str)) + return value + + @staticmethod + def get_format_time(time_str, stdio=None): + try: + return datetime.datetime.strptime(time_str, "%Y-%m-%d %H:%M:%S") + except Exception as e: + stdio.exception('%s parse time fialed, error:\n%s, time format need to be %s' % (time_str, e, '%Y-%m-%d %H:%M:%S')) + + + @staticmethod + def sub_minutes(t, delta, stdio=None): + try: + return (t - datetime.timedelta(minutes=delta)).strftime('%Y-%m-%d %H:%M:%S') + except Exception as e: + stdio.exception('%s get time fialed, error:\n%s' % (t, e)) + + + @staticmethod + def add_minutes(t, delta, stdio=None): + try: + return (t + datetime.timedelta(minutes=delta)).strftime('%Y-%m-%d %H:%M:%S') + except Exception as e: + stdio.exception('%s get time fialed, error:\n%s' % (t, e)) + + @staticmethod + def parse_time_from_to(from_time=None, to_time=None, stdio=None): + format_from_time = None + format_to_time = None + sucess = False + if from_time: + format_from_time = TimeUtils.get_format_time(from_time, stdio) + format_to_time = TimeUtils.get_format_time(to_time, stdio) if to_time else TimeUtils.add_minutes(format_from_time, 30) + else: + if to_time: + format_to_time = TimeUtils.get_format_time(to_time, stdio) + format_from_time = TimeUtils.sub_minutes(format_to_time, 30) + if format_from_time and format_to_time: + sucess = True + return format_from_time, format_to_time, sucess + + @staticmethod + def parse_time_since(since=None, stdio=None): + now_time = datetime.datetime.now() + format_to_time = (now_time + datetime.timedelta(minutes=1)).strftime('%Y-%m-%d %H:%M:%S') + try: + format_from_time = (now_time - datetime.timedelta(seconds=TimeUtils.parse_time_sec(since))).strftime('%Y-%m-%d %H:%M:%S') + except Exception as e: + stdio.exception('%s parse time fialed, error:\n%s' % (since, e)) + format_from_time = TimeUtils.sub_minutes(format_to_time, 30) + return format_from_time, format_to_time + +class Cursor(SafeStdio): + + def __init__(self, ip, port, user='root', tenant='sys', password='', stdio=None): + self.stdio = stdio + self.ip = ip + self.port = port + self._user = user + self.tenant = tenant + self.password = password + self.cursor = None + self.db = None + self._connect() + self._raise_exception = False + self._raise_cursor = None + + @property + def user(self): + if "@" in self._user: + return self._user + if self.tenant: + return "{}@{}".format(self._user, self.tenant) + else: + return self._user + + @property + def raise_cursor(self): + if self._raise_cursor: + return self._raise_cursor + raise_cursor = copy(self) + raise_cursor._raise_exception = True + self._raise_cursor = raise_cursor + return raise_cursor + + if sys.version_info.major == 2: + def _connect(self): + self.stdio.verbose('connect %s -P%s -u%s -p%s' % (self.ip, self.port, self.user, self.password)) + self.db = mysql.connect(host=self.ip, user=self.user, port=int(self.port), passwd=str(self.password)) + self.cursor = self.db.cursor(cursorclass=mysql.cursors.DictCursor) + else: + def _connect(self): + self.stdio.verbose('connect %s -P%s -u%s -p%s' % (self.ip, self.port, self.user, self.password)) + self.db = mysql.connect(host=self.ip, user=self.user, port=int(self.port), password=str(self.password), + cursorclass=mysql.cursors.DictCursor) + self.cursor = self.db.cursor() + + def new_cursor(self, tenant='sys', user='root', password=''): + try: + self.stdio.verbose('fail to connect %s -P%s -u%s@%s -p%s' % (self.ip, self.port, user, tenant, password)) + return Cursor(ip=self.ip, port=self.port, user=user, tenant=tenant, password=str(password), stdio=self.stdio) + except: + self.stdio.exception('') + self.stdio.verbose('fail to connect %s -P%s -u%s -p%s' % (self.ip, self.port, user, password)) + return None + + def execute(self, sql, args=None, execute_func=None, raise_exception=None, exc_level='error', stdio=None): + + try: + stdio.verbose('execute sql: %s. args: %s' % (sql, args)) + self.cursor.execute(sql, args) + if not execute_func: + return self.cursor + return getattr(self.cursor, execute_func)() + except Exception as e: + getattr(stdio, exc_level)(EC_SQL_EXECUTE_FAILED.format(sql=sql)) + if raise_exception is None: + raise_exception = self._raise_exception + if raise_exception: + stdio.exception('') + raise e + return False + + def fetchone(self, sql, args=None, raise_exception=None, exc_level='error', stdio=None): + return self.execute(sql, args=args, execute_func='fetchone', raise_exception=raise_exception, exc_level=exc_level, stdio=stdio) + + def fetchall(self, sql, args=None, raise_exception=None, exc_level='error', stdio=None): + return self.execute(sql, args=args, execute_func='fetchall', raise_exception=raise_exception, exc_level=exc_level, stdio=stdio) + + def close(self): + if self.cursor: + self.cursor.close() + self.cursor = None + if self.db: + self.db.close() + self.db = None diff --git a/web/.fast-spm-local.json b/web/.fast-spm-local.json new file mode 100644 index 0000000..7edb542 --- /dev/null +++ b/web/.fast-spm-local.json @@ -0,0 +1,102 @@ +{ + "src/component/AobException": [], + "src/component/Banner": [], + "src/component/CheckBadge": [], + "src/component/ConnectConfig": [], + "src/component/ConnectionInfo": [], + "src/component/ContentWithInfo": [], + "src/component/ContentWithIcon": [], + "src/component/ContentWithQuestion": [], + "src/component/DeployConfig": [ + { + "name": "部署配置-上一步", + "spm": "ca54435.da43437" + }, + { + "name": "部署配置-下一步", + "spm": "ca54435.da43438" + } + ], + "src/component/CustomFooter": [], + "src/component/Empty": [], + "src/component/EnvPreCheck": [], + "src/component/FooterToolbar": [], + "src/component/Icon": [], + "src/component/InsstallResult": [], + "src/component/InstallProcess": [], + "src/component/InstallProcessNew": [], + "src/component/InstallResult": [], + "src/component/MetaDBConfig": [], + "src/component/ModifyOCPResourcePoolModal": [], + "src/component/MyCard": [], + "src/component/MyDrawer": [], + "src/component/NoAuth": [], + "src/component/OCPConfig": [ + { + "name": "ocp配置-上一步", + "spm": "ca54436.da43439" + }, + { + "name": "ocp配置-下一步", + "spm": "ca54436.da43440" + } + ], + "src/component/OCPPreCheck": [ + { + "name": "预检查-上一步", + "spm": "ca54437.da43442" + }, + { + "name": "预检查-预检查", + "spm": "ca54437.da43443" + }, + { + "name": "预检查结果-重新检查", + "spm": "ca54438.da43444" + }, + { + "name": "预检查结果-重新检查", + "spm": "ca54438.da43444" + }, + { + "name": "预检查结果-自动修复", + "spm": "ca54438.da43445" + }, + { + "name": "预检查结果-自动修复", + "spm": "ca54438.da43445" + }, + { + "name": "预检查结果-上一步", + "spm": "ca54438.da43446" + }, + { + "name": "预检查失败-部署置灰", + "spm": "ca54439.da43447" + }, + { + "name": "预检查成功-部署", + "spm": "ca54440.da43441" + } + ], + "src/component/OCPConfigNew": [ + { + "name": "ocp配置-上一步", + "spm": "ca54436.da43439" + }, + { + "name": "ocp配置-下一步", + "spm": "ca54436.da43440" + } + ], + "src/component/PageCard": [], + "src/component/PageLoading": [], + "src/component/Result": [], + "src/component/SliderAndInputNumber": [], + "src/component/Steps": [], + "src/pages/Guide": [], + "src/pages/Layout": [], + "src/pages/Obdeploy": [], + "src/pages/OcpInstaller": [], + "src/pages/constants": [] +} \ No newline at end of file diff --git a/web/config/config.ts b/web/config/config.ts index 7980f3a..300bd8c 100644 --- a/web/config/config.ts +++ b/web/config/config.ts @@ -1,13 +1,19 @@ import { defineConfig } from 'umi'; +import routes from './routes'; +import AntdMomentWebpackPlugin from '@ant-design/moment-webpack-plugin'; export default defineConfig({ nodeModulesTransform: { type: 'none', + exclude: [], }, - routes: [{ path: '/', component: 'index' }], + // routes: [{ path: '/', component: 'index' }], + routes, title: 'OceanBase Deployer', fastRefresh: {}, favicon: '/assets/logo.png', + history: { type: 'hash' }, + mfsu: {}, locale: { default: 'zh-CN', antd: false, @@ -31,5 +37,25 @@ export default defineConfig({ `!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 { + 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; + }, }); diff --git a/web/config/routes.ts b/web/config/routes.ts new file mode 100644 index 0000000..734e822 --- /dev/null +++ b/web/config/routes.ts @@ -0,0 +1,61 @@ +export default [ + { + path: '/', + component: 'Layout', + name: '系统布局', + routes: [ + { + path: '/', + component: 'index', + name: '欢迎页', + }, + { + path: 'obdeploy', + component: 'Obdeploy', + name: 'oceanbase部署', + }, + { + path: 'updateWelcome', + component: 'OcpInstaller/Welcome', + name: 'ocp升级欢迎页', + }, + { + path: 'update', + component: 'OcpInstaller/Update', + name: 'ocp升级', + spmb:'b71440' + }, + { + path: 'ocpInstaller/install', + component: 'OcpInstaller/Install', + name: '安装无MetaDB', + spmb:'b71462', + exact: true, + }, + { + path: 'ocpInstaller/configuration', + component: 'OcpInstaller/Configuration', + name: '安装有MetaDB', + spmb:'b71463', + exact: true, + }, + { + path: 'ocpInstaller', + component: 'OcpInstaller/Index/index', + name: 'oceanbase云平台安装', + }, + { + path: 'quit', + component: 'OcpInstaller/Quit', + name: '退出安装程序', + exact: true, + }, + { + path: '/guide', + component: 'Guide', + spmb:'b57206', + name: '部署向导', + }, + ], + }, +]; diff --git a/web/package.json b/web/package.json index bd64410..2d45395 100644 --- a/web/package.json +++ b/web/package.json @@ -20,28 +20,40 @@ ] }, "dependencies": { + "@ant-design/compatible": "^1.0.5", "@ant-design/icons": "4.8.0", "@ant-design/pro-components": "2.3.34", "@ant-design/pro-layout": "6.5.0", - "@types/video.js": "7.3.50", + "@antv/g6": "^4.8.22", + "@oceanbase/design": "^0.2.2", + "@oceanbase/icons": "^0.2.0", + "@oceanbase/ui": "^0.2.2", + "@oceanbase/util": "^0.2.1", "@umijs/plugin-openapi": "1.3.3", "antd": "5.0.7", + "classnames": "^2.3.2", "copy-to-clipboard": "3.3.3", "cross-env": "7.0.3", - "i18next": "^23.2.11", + "i18next": "^23.7.6", + "lodash": "^4.17.21", "lottie-web": "5.10.2", - "moment": "2.29.4", + "moment": "^2.29.4", "number-precision": "1.6.0", "randexp": "0.5.3", "react": "17.0.2", "react-dom": "17.0.2", "react-intl": "6.4.1", "umi": "3.5.35", + "validator": "^12.1.0", "video.js": "7.20.3" }, "devDependencies": { + "@ant-design/moment-webpack-plugin": "^0.0.4", + "@types/lodash": "^4.14.198", "@types/react": "17.0.52", "@types/react-dom": "17.0.2", + "@types/validator": "^12.0.1", + "@types/video.js": "7.3.50", "@umijs/preset-react": "1.8.31", "@umijs/test": "3.5.35", "lint-staged": "10.5.4", diff --git a/web/public/assets/icon/client.svg b/web/public/assets/icon/client.svg new file mode 100644 index 0000000..8da1b09 --- /dev/null +++ b/web/public/assets/icon/client.svg @@ -0,0 +1,13 @@ + + + General/box-icon/24px备份 2 + + + + + + + + + + \ No newline at end of file diff --git a/web/public/assets/icon/close.svg b/web/public/assets/icon/close.svg new file mode 100644 index 0000000..8ddb1c4 --- /dev/null +++ b/web/public/assets/icon/close.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/public/assets/icon/ellipsis.svg b/web/public/assets/icon/ellipsis.svg new file mode 100644 index 0000000..adba3cf --- /dev/null +++ b/web/public/assets/icon/ellipsis.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/public/assets/icon/fit_canvas.svg b/web/public/assets/icon/fit_canvas.svg new file mode 100644 index 0000000..3b72d3b --- /dev/null +++ b/web/public/assets/icon/fit_canvas.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/public/assets/icon/more.svg b/web/public/assets/icon/more.svg new file mode 100644 index 0000000..0c06060 --- /dev/null +++ b/web/public/assets/icon/more.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/public/assets/icon/new.svg b/web/public/assets/icon/new.svg new file mode 100644 index 0000000..7e2d9b2 --- /dev/null +++ b/web/public/assets/icon/new.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/public/assets/icon/obproxy.svg b/web/public/assets/icon/obproxy.svg new file mode 100644 index 0000000..8d7fec4 --- /dev/null +++ b/web/public/assets/icon/obproxy.svg @@ -0,0 +1,14 @@ + + + OBProxy + + + + + + + + + + + \ No newline at end of file diff --git a/web/public/assets/icon/reset.svg b/web/public/assets/icon/reset.svg new file mode 100644 index 0000000..2682c0e --- /dev/null +++ b/web/public/assets/icon/reset.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/public/assets/icon/settings.svg b/web/public/assets/icon/settings.svg new file mode 100644 index 0000000..6981e2c --- /dev/null +++ b/web/public/assets/icon/settings.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/public/assets/icon/success.svg b/web/public/assets/icon/success.svg new file mode 100644 index 0000000..218d9ea --- /dev/null +++ b/web/public/assets/icon/success.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/public/assets/icon/warning.svg b/web/public/assets/icon/warning.svg new file mode 100644 index 0000000..4e42839 --- /dev/null +++ b/web/public/assets/icon/warning.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/public/assets/install/empty.png b/web/public/assets/install/empty.png new file mode 100644 index 0000000000000000000000000000000000000000..b8e666402623bfffefa17c50ff2e068e2f8b941c GIT binary patch literal 14913 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

)SNCXUFU~Q6u(jIY$+Y^r>>N2>ANZ1o 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 literal 0 HcmV?d00001 diff --git a/web/public/assets/install/failed.png b/web/public/assets/install/failed.png new file mode 100644 index 0000000000000000000000000000000000000000..0ba7db0952ec7fa71158ae0a287d5e8f2bd37b89 GIT binary patch literal 55696 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 literal 0 HcmV?d00001 diff --git a/web/public/assets/install/metadbFailed.png b/web/public/assets/install/metadbFailed.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ba45a002bee00f4ef584271f5267e4a8ea8c96 GIT binary patch literal 607171 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

W` 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%0AL?CW8(3Z-U6oaKU!|6xv>n+ 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 J7r*=Y-vCqfyGZ~5 literal 0 HcmV?d00001 diff --git a/web/public/assets/install/metadbSuccessful.png b/web/public/assets/install/metadbSuccessful.png new file mode 100644 index 0000000000000000000000000000000000000000..01bc87968ff2f39614f97c7e0f32dccb24accc48 GIT binary patch literal 698684 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ⅆp6??g2u>mi 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

p#`VGJOrGIE`lJJA&^ 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�L89@aYnyXK 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%0D@2 zDn7aQ>Q51N}V`!mL{ptB0@fwm@=7h!^4x{M0BxY!@)#`)U{6PwSYO* zXFW65f?2c&eJLRhwg=Jx5VkfpL7}1X#-)wcYqWpRbkS$MnQhnk8K%=^%tmtO0U({j zkdMpiUAE6penUi3M76#ZuRt{!rsx&I)iQIoko!#{ zc;QLqL<+T#nL+ic^6Rx?$k)HcM#o-N*L^}}$$Ju(RQ~~56ojbOi{rD^JHFo$^m)DYlY>iMQo0i3g-n zf#~}*#iyV}mm}| zuX~XKZ@KOve#@S>cdjh_a6r8|*=U~?tcc{Y_jSyZDsQm%S!{uRdgi3i>Eoj_45;O< zxRa?fAEy;pgr2FXn8(MAJ`e@`CheiY?n~55vIhKaoSLlzGlfUxk?&{1L&X5P`6!J!dl`f&&10o9B#(^Z=ePabC zO9Ccsr#3Q14MY+CeZg53(bdgE1;1S%U4?IPwF|Rot$4vw?$bVh>`=o<+lW9jX%Z#4 z!sxkPs)GcgEsJ#|lG&UVYwQ`IN}1>$vT&N9Erw~)W5)`NNoz%M#AkqOm=apZf-NrR=aQH|Xlp$z4^5*b zvUT-q;II;LI509TMsn=X4OkJ=SLlB?{OIUzG(PnGtc^tU6S5(=# zYD)~%)Ii1o>{&@!PKMo!lE24losNP~Mm=SWCWkc1%0zjD`qfD6asekZ2UGy3F zFg9$pMe!&STy4NAeRLm$MxH_7J0PhDTfZak7VoMBgrZcN3D`}ln$g)+j@wM;WgR)u zrg)Pwh3V2$Q;k=8@h=>xHdd^)WK*Z&hO=@Qw=O!xXPi(J<{51H_FP+5*&N!LbB?`) z(~eVCriQf2#SyHi|6%)LNyxDDUx|>K4OB$OiNc1}acPv}td3%Y1AIG4%GvuYOkQF$ zd^c8NBUat8Sd>^Z%GAk=IGKl8je#R_{sdK}@mQhfkNfn5I(A;r|I>0RQIl-wxKO)* ztv{)v85S5bLNN$TYJ+QA$1;!8#Em){L8I@Z`2QM#7t#vMnYWl82$!4{`+Q z|J6kK$gPxR&hbn%(P|_Zng9SxvI{l_CzOwhWn)$Y0X=j4R6*Lr!Jh4%c8f6z-^&Ts zN!rF9+ZRG$K^kVl#V}^Fm0?)c*N@+L26p$$(mQ!dq%UGE#qB!!33ehWM3|#qY{j-g zOv~d&c+!=X=OD1>E+U($m|pCOvaTkfZ!ANP#QM3L*yfXnu|wmU5H)PjWL6-dq@fi& z=@?2WEow?S5kX9vQNe{kQ)Ps6K4K=KbT#F?vCR+2{}Or71UANn$b`m=aaww}uy#0dWfKAwRCQc;q=|3&QE~GS244ic}yR4R?F|jv@;gb>{G_8is1S_p!Qa zYa+%&f~sAA=)jJ#pm*Mw7Ecg;y#6aNSL}2$;UEzc>7%{}b|**bb!2KAj%4n|O0!*P zMG~d5HVk}lITB506r#E2Uqp@b3sOUuY&D;0-{&Bo{g<6Kp_onoP`Lfsll_9z z{;l03F-{}!cf!|xyB+H}$9mJ{-ov4|rX0v)N((<{&L9ro3?}>;ol%euBt7T5MAc z6=)dMI?k0$%s@)k*MuJFucTauVm4kGn&`SxYdhgQZ0rLgTF6Oaj2rVFsj{T1&h)&u zGXNUVl(+S7R|M|Yv@dta)l%S!?proshADZ`;i;>4s4h1{-W~% zpRnA=RN7RRAHT$ebzf%;+S-sO=>igIP+k_*oA+!m*6B!~yDHLqLSE6JFU3jPxldo8 zhFVt&!)+Z6kSK&`fL^#hF&h60!2l?Y_sY3Ds>n%_ctl6UEp9@hNp%N98oR9lZ!>TLrDJM`- zau)0ah4&%|mRudTJ(w}}g#2rupu_#Uj2|kR`mdqg8Ywx8c|bTlizMi-q!}a}aMv0~ zj2=cym7JOIyn_X`cC|<@tT!l{sp+@J)scT|@=&3he1`yI|JlOt=?xp$JAU*=z}dDr ze=)_MWqe)`X8nfR!{LlfBN!*MJFCctMxW?$TE7A6-O(~Uy1%(DyH~>cSfO^|bN|6y zwSYk}rFvK$Y>NU8JPYes5>kb4>fh}fH0xNvdYR-M5KL}dHOyl;RozTX!Zj9epg-aE z6287_)Y?P}!-pX!ld8rv#Zm4U(CDnLp_7`(6v$XxJ5}NN_ta4g;F$eC0CbgYNPv9$ zxwPs5ljZySGA&+hudR$Vs_@o>pxzuY?~qG=2Y+7`4vv=$F+pW?>3n*FJeT!G#A0vF zh7%nVH``)o&rG*##NQSU*q-N>MIQ_#*WQ=Os*Qq0?f@q}Hi2)oi4#<3vxLeB z5kk|`OxN$F{LLAq#ZY4d^ggw*10oY6eW8)rp}%5u2>Qw>YVO?1Co$}PTg5N&hO-m+ zDE*wu8*6ekbMr=%0_vHhr=e}JVV}m|8!%U;e^@Uw_8!@Yga| z-ud*@U@sI?n}K&mHO=W!cb2M(VXR zO$Xmj*KnfI?>9&CUt4}y?gT`>TDgA1KU}@>x0!yBsorZ9wcz83Ouxj7L5=WQ0sjHE zpE$gk{p)kn;~3`ugy$*p!-|FHdo8J(Tj44>=8EL%%klKtv;P2$UjjZ&UYJr_&h7^? zcMY^v7*z18WpVY_uT`Zw(f-qceEylH^e-wvXf43es!I!xgpQ1_545d6IYIQd6VqP|M;PF=zR9GojWD-lbN(vtx|%! zz-OgNjLi}eSPi>?`&nmn`E#gNNxap{@-Ei%$*dEDPe}8EG7_gujKI%tB^xep@Tsag z-GxzI(H0vKWx^E`{d{5wzTYKlC`BIQ>$p?+C58HorLC=&`l?llqxNVUpgp&->8Vt3+G^unUc21Eo>0&)ffD*sCP)F$Lu zjFZcXj!6ZW?Iauw!%XQQsCeoiy~)%TR3$Vnyd91Yr7=(hsSVzjt};0{fm9otK^i{e zJC)etP|*+$Mq_e|zZw9AP@V`zt3!aO4aQ=s?nAMcANbHrg`}XGh6?0v5hW^KWz(m} zn1O(b_GUy<&KN$Z;*a}SP45ZCJrR=wGAC`lF|?&IeNp~bvk&OW9jOVH8mgZmH4#8O z8!X(TSKW#NKbw`B)zRENHbQ&jMI_n}=9O?jNm#|5%j41#ZV&b=1A%07+WDuFUc5Xi zFU>$k5_rw}Sa=;Lc?v8A(=HDdI_5V7CM3rwg4aYE`r;e%7<)CSY^JHzyaG%pTx;V< zuuGImCEZp{e9(IRuuOosh*bT(e=&2sGr3WYTakWFc4kD9j@wvwg@Yxd)OQr^k3Y32 zyV!2j9@HJIFEk!o9`=N3WPcw2+YFkj=s1=ouBpGUBwKNovG@-VL^4{k+-KV9TNB(lCV(Cc95~PFdb0m6 z`tKv&=U%Qh%n!GjmHjWCY!W~E71IW}9{(NrCq1a(xc<^I$Lux-YVfiw7UJ-&$j|EQ@LPtiUY&(#E1(pHXPLI z9m4Pzb`(= zC>wAaO<-mzaf=_!i@Owd_@(8z-<=Vq=TUp4YBxe(tOge%_>~*d@^Gnky%4RU0$u2q zO@V%X-VxV5vZoSb61F%Fc&<5u(x#5(T#%$4r8G~=+E&+eYWpo%5(311rG#D86jSp0P?9lpC)6;asxd`WwN_;A2lD!CW!(H+Q4!nG-s*81II)An z#yaURCc|?e4%7A5GB<^Dx1uO?09+e4q_=d}$O%bDS>(SBMI&jrj1g#ZaKrobTUfF! zY>s@Q3llXeZZAqg4_@`aDTeu1k;MH6(8hcw4lRhktr&=0Y?pv$dtK9ft-Z!n_=cea z8R?p{I4kgCmB@p^x?UKyY~QB1_Joa3AUok{PHqdD90l95AORvRZ)=hyZswSj8>_xm zLPY`8PtC$(j=B zCyQEQt+rwn+iAB0vNrXT(Y_;;m*wO?48QVS=kk#Blrs3HRH;|*rsc?y1SYqtHdVBk zpq|*06c-5rUY@%Cn(DXdMW&>eAK@3{%GomB5fv2VF*bI!4T~=J&KrWzMFTNf`@YfP z0-a74aWz5YN#kazE^Rn)9L|j&$XX;K-dZ_BKzBI!<}KO?$2eJ8Lg->s_J2%Om;E;X#EDef-s?iXo>3F+qf>mTbbVW(AL*8@TmE<0bW+(oZnj+S zWr3Wn5@@V|=I7#Hs~HkdkoaNjisjnzI~${C$L0>Fw3ce6hj9{9+44Cmzob93`&}e; zD@5#}d)^ysj%I5ZC<7{7V%OSY7Mhd08w||irGP9?GES;o-}Q#b*fvPiBGc^>O!DV_ zpeXIz0~+qibKg+s?-}8J!52o3BB*Pn$rvMQqsfGflu1yxC|vgVn?wfOj@(oFdcu@H zJmdlVB7L4lt8;S_qdl+SGBFXNejW3|qf3I;lu>Q>t=I2`k587eR(XFT|E~XyxRUo- zSiGM0typ;>gYB<+b@s*McR+Xj%5CgUdD&Zj{cl3vPxnTT@ zh5w)1&|sT4M*&k;l#4-Cmw2H&uhy>C_kR367UQknet9M@JG5+@9>Ra#y?4ti_;oKT z*kx~I*Z|n}<(+zz#cZg2b2qEzQ)t(W$MS`eB;>h45ZA zDl^fH<%M|=_)k|IEG>o>YaM;Nsk+sz3UK%p9iK1sy(Toi80X5$+J01!Fl^wK1I_8+{2- zrr(G+J7^T&B@BO7_7w3Pkx$)V8tetUItMUd*96QYMqrQ5tgY?C`iPq#ea5m3@e~xX z)M)~viZON~HZ&|l_~2J)7f2V&9ci^TfzO4%mR!&PnoX^{Rm|3r*6r;0VGMk9#o;3v z{lRls_hxI0u$7^yN>doj_0B#P%;fjU#~vWUp)fwP;f39#G;8;WBMPG+sULP}6->M~ z#bV54!iIV4U>&Z55f8{8lRj-3VW<`Hp>r~Oy@f4r1z{PQY*t{JKlNMgRkklS)|e*H z$UcUoSPAaa?U&8tf6o)(hP~PBi_QU^;+C<;EN{v$zjk*;@OS)5S*cWTqFNhv%V;3c zhc+Bgk!;EalBMkr?w{xX>tQzhC^=^s&?7MZ+U42G&P}}t#TIJ;Gv+@)iQ|mMNl^7y zv$3nY?Z`u*OQ~kHv}yo!$RS5?T+G&Yf|k^QS{<~}e*H!_Z!Gh>vnf;fqW%4;va)0j zG!nO~ps#F#<7WF0a4q!M$h|g<{H4s-^0!8?V3u)A;P};g?Ik#ID!QL5Z zVm0Utj!acd;aUy*#FO2Hp};NvT72QjKQA))L)4&ZX%=fpr5_LHUh4}(wwGd>jbBJa zVVOt?6~Hg6E$O1>c{TQIb9Fx06^kMoy-I`B&Mj~GFj8!vM>N+QuXpoVVAj;T>l6RA zEAP44kXFB7iHKUu-fkf~(9ly`O*mURipqJ#cMU_R&p2Fc7a3%ZjRg6qT&dyf3UAN* z^mwz!2l%kuxh4fjxSWbs2tWBCg+;dwAi)1Q==7x_i!1|$@4Kr_jaEX6)2rq)iw%zM zAilOYP>0$R$KLl8k$S3aRPiG!7tcDz<;@U7n>Fe$h%7SCM;8%O&6ZmM`of~Kz-&b~ z^gO`DgKrsIv2Uq4`g{rsyDkMgZoKcKOxOkV8k*9GofoTM#0>!Yz8=uSyQ9|o;nGqp z&QZSAh7k=5tT_J2Yn3$OOe(x!R0#oD!E*Owf!UHx2p=glX|;rf_WeO$l{F>i3pu5j zx}1EP2dY?8FSJew(lOEEU~#M#tDW%Lx)0a^fjju#pmYCP2;xC&X^g;J4^W;5g@ zj=yBve3em;Du=r}3-e}*H}Q`{?T~(!D)3HII?YJ8%Kj>A`nH$k&q$Chnb2webFp5O zDvWQ>u@{213-jHh8Te><%>hbY>GVu86VbRaB(e=@Vo%4jhyug4`BNw0y2tGd%;c=| z2`a#s7G8OzXH%M5k96E zD=NH|D#BT@6XIs26Jwj<^z>yT3!^rQDY?2iajs90-bWe`Jbo{ZeoF+Kz4M(d^(3sQ z@w^oo55c+Feyi$a1nO9Y=~Nvv{G2+bC-K&EhovO>47Aw4o`+?`gYcE}DP-Ialr7Ce z<(_slthdwqP9$n1jD587U_1LF7bmFm9(uHkBifxE+Mf{s~q zT`(+Sh?AK5?+J@!P*r)~ERL^H0BS!iNhO_;$w=txSJeM7q%k0IU8P7W5;^eomd3Eau2|^Z~wQui62c=%nJ{FG7k7`)dcLUIoQn`yg&dRH7t{3 z_g5S>{=fuVcyDwR+m0y2^9k+4vKjW4eij^)j*YBBT+^|2W3`G0*V_NL+Ub?#nkE?t=>M( z+>1x8<;seZ7m&F5-l}fEp2BF(h%aoAUV!1>worf>iNZ_!FKeuBlLjr_36Y6-1OKQ& z(sES5i$eBlt~{6uh~hr26^tC0>V|vCTo)L@?eyJ1QVKV?yd=sWs^8n#+9e7vAZQPY z5{gDhdAP3ykpRa>G}qS;R?_b)ZIyWf5G$WCX%A4?CQ%1|#Sm@vF%_JkQxMdFqnBD> z`}H3|{(`3=8TM`m0BTB8z2{tr5-ph~_q~xy(V8|%e4Sb8U0-*3<10+sM4xqR!`C|u`4kyRidc($6 z6@fGs)USvJN>b$r7cw+y#cO9qkKR-byZolW_uoVHd`QYPkW{yU#M!1YXX~(V+XQzO zQj93W`;8U=mf5lC8jYTDN=`OrQ5H3Lh6E+|zbJKmHsjie9?TpKAtiRSm2mY9q{w>} zHAT?t-CSvkqUd0_L+*SFzQH{eI#9dCC0Xm1O?u3v9Slalb!m-!-WX;CprE(s;A!P% z$*<<%k)oX#hxaBbKhDSwKNIPnd<>=J%!GMHwT}dbrhc@$+w=WB!@>WACbA~hh<_MEs-%N+9FuqN?-wHfR*&Oi$+{_;wBcLV8dI!`4Q zpktUPj@W!@pdK5&?i zWZk%sy&JcHF*TZUwsHKShSndbY9ckVQDXAdkZo4U&VwSmRbnIt#5fXHgyTiVjbXFq zc*hfj0gf3>in0{^M2R8Df2&ljPOd;|L3>+EXI16iu)H;}Ss+?hm3 zY38?@6OL|Thg5^X@3TO7@72VzqpcF41}Wn<$c-(^FKHQr;Sd!1Qksd^&8~Cr9#OG1 z5no5T*dS-EM!Yq{sx+M^Lh`iwoB(2r$=X8e(LKBT@c3VA+Xah(?_0ebYLE7_3?;ZD z6To9}eNy?BJvM_dKw5K7_QZMIw!}lUB1n~_Z;&j2q$NipUgB0AA|XU>K~H$u(ka+l zl!)U2?MMM6=QUz2JbM@1`nKG=Tbh09Foa)kgik(5Y{}t{rv|T|JUJ2OUGjZ%cQN|u zhmOObrcy5=Iv2Tt0f>0jC=s4{+gU#^0{Lxo1yodscr5+y44t zD4VllNR>yFj+4owiCREipms*35Wxm#aResuV5-uYG&mikE@DRol%z z09$qpN*z84GMnJL16H^zd|Y@-{wH)rZ@+oz(X+mr+wCH}_d_P}U#o=0{iKS2U^VK8 zq`&#fR@*J{Cr|i{Fv~JcHAfatazc%4kWw9$h&+1o6k4yNwMQA%W=4te=FW>_l!t3( zd7JleiV4%nKaMQf=O1~lnyvaEz!#LF9+vq1MK%O$RYcj-2Bu^y4f%I#mwJ3<{I^`$+PD+>h775?__sBNHZ0@}l+*XKz=JEAa)&&s_87ArKxXp~Vt0T(ac$E8&E6KlDop zOQ!1vqDGaA-A7E~?jrEjqbP$Rbuk;;UOF-Z{k&?=2lF+8cO2W{4~=H(swrv=#Dx%4 z!{vaCTZlJ3d1LullREV^4{#2d+AqGW)qK#UBgrh$AJqCBeC{PET0y;H!k z(vS_BLhZ%cxJX1ME=EtYl&yE%O+rAd2IwDiDVBN#rMwAJ#V?M&vn9q6w^lwT4#oB> z3hP0lM&xX`)a^KX_zYvHIk52BmU5zjOwqNRzIThIJjK+VuBm^xeuS)lW?=u70*(3n-A(5O+m?j z%d&y=R-7NQg+ILUef(v8x-EF)>NK}w$nxa#yF0^!ys_WYjqeWoUewkoBspd^P~5>} z@#b;=kvo}o{~>>PxZG`IoKmz`!2fK2=1xBg{i)Hf*f!zaXI+2SX63F=>M*N;hjCs` z4;?<*R=n5xuE#V8^w0i#VQ7c>QJ8WfMpHvy4wVk5lz_ubeiqft#;+`InZ(41vgmfH zX275N{(GT5mF(y)EY&&72^ih#h<5iD{wo*p@ze9%S6aH1rX;D(cK90qFCio$2FCq6 z0nIT|sXzP;K~nok*0^59P?q~Zs5#q#NxZN=!mdWV#!Px#X6vsA{kWr{0FUC{mXUe5 zwArZlzV*KQZ)anThO|Lxp?(qCxG)r#(X3;HQAPsGg-6{6kx^{Mo3NqHpgSUYbKLLB z<2zrmRfs3)ovafLv;6KDIv`203(QDC%Sg9$RrR85m7+*+Ngy&Uv*!`Qccu@&I~cMZ z*wgya`32#IA*YrCjqh7Z#dbp35Pv=VHqPloZ};KZf?S$u2gpDjFXjZhZh@S+x>~LL zw#bzgSTk?KyRnoRE(NNp)B<>)8^4Ay4T59rEak(HSAUn2_tfQ)gA}Qza|wh7#W3Qo z**97+q)ZmnZf_^j;Im64OiZJJSo>!w-d;d%W3buCFUs_Xq0T^L zbLofbpq-(lwo0N(i95^MC59h(T#PVWz(oHqHo+ z&*tM_a4TLTi3^0D_l%eBP1ZUIo9+&%L`YO5=V$3$#{VHK>ie-$6X$Ykm)>3S7(k_5P1!5``vD1Mfiwj}ix6y1_g3WpJ7P27ZApM4+U3L-2TL zH0#CfR>GH$ie3x7DAJjq1cmZSDx+;tJ>=RrR3%bjd8uZ!;2tu|xNO~*YvQX%*Hqwj zg4XF_$?z}EHrjqBVkKyXW64H~@I^cU6q|GiU@+jyUHKVFVhQFQ>s?9t=qaBPEb?=O z?*Zkt2Y-;HZHqa6X;8#!$#NfO<+!z4g$%oQ)GBnJ+5Y~7{oSp@XWoT?e6K$12l-3a zO@3wYC%(OpR!V-g7po2I5^S)Nt!?fu*!VZ`IH*v|I2x{zF_4QGKK~j$2dd-Hd!5Hz z3Xi3ynZ0Mh6KBLXa@GTa9O}ex2rrv@BP2h7tFvzWnbMQ#i>(HoBO^*YbPC* z{f=$)^jewmemi@_pdgI1qtS@T>#a!0wJjw@xzut}go>q%FzY1L)U}-(|v;#7QN#013!ZIZ{+h801nO`H& z?rw(PR-ey4FYJE);TJMdRP^VkA9({-)();;UjEsWdHB?>=F@Q??ejN( zB2|wbn>Exo%z78vdo3)!5kfG{JweLF1L1%i%$zNW&@{Q6T9iINR6n-4a6w6G{0se$0VciCf>l%%4qD#{ET1OV-S z0NPt`=wm(t)MxILIi&uaBF)X0$W2C^CxBpuU@e`pi|6ItBrhevZY@&Jkl#zz5lXn6 z&FZtD)+~E0EMM1hyrmLog=KFNdU~ssEq4E<2>)rJ2DRg#`YKo{v>Kpi_n;vf7&MsA<)?Hi{t*x(U#g?JD{LrIjY>WfJWs@c$N^1!aQr3szb znoORbmwspMEnT=Lu8>vIp8ydm#Cr6whfJ2NVyuu$j=F5BLgP29L?#>Jnsdo}A}gbE zlWuhbs2Xf;d3groQ|b5k#?iQk?pAgz-SO@%c!VEWz3%-5dz%_sZb7WpK%lK`R;ATP zwRmK*)dDyCPNR2@Y)_so9tzinQvABl;t?zPLD=LDOG)%Uf2Atz1N|m~l;0m^v5(t3 zHU!{eYaqmk7V+aC(*%X(VcTWC6I^k%k_{?;NOLj%3Er}%*tbJ{oPl0FXEW?TEy66> zHOyGWdUHvf1mu~;Mx2ZM%5V3V5%Zp+)yNhIsw*~A282agMbVV0!0uFX9v#vXY8c03 zPuKU zl$V;_2>dLb?04TA6P+ohldbwacUkC@l+XUBNbBluQX0ZYAdS-SZr`(hC)kka+(T=t z`uMErPn6&tn*_lrUdx3400+0ezTu;AoO>Y{q>!B4e%n0hQII7NP{Vo{{$PC_gf5|EWT0r*9^$TIe%_iAp5XuY?Z`~EW zK#2Co(vv@6I~Dg5*{rgj3Tv%d(s50Et!ToO8rndxVm!+tE`~p1?XStgn2A%>k}I=V zE`vQEnLWLkA*j1PTAGh^Qne`nQ#qca8KzB_ndaW``g69KBwoz*vmD$?1rO0$J!ck@ z`?yuBl!VrmFPOaOEC}&hnFgWKGLFN&YMV`lv086VMhY3|#6hT2QO!|Sk{$Yp`J-`Y zFksk0HPSugT6%g2ewJio^^ ze%CfyxOdFw(CN1YF+c{3v&D|3?mocv%2*3X^0cVPe_`V|=!h;wDnCPWvHOgnXGzq8~+x;W;>aytI zF1)F3>~dh&zCIPeS^X{k0R_S080x<1dt14b$)&ck2fLgP7Ia}6@1|L#Fm=B5!M^in za+0RIE$yl6w~e2tU-Q&=0`0x6Tyj66VfGxj#<7GxQ>slFCs)H`hR}LA10bMRo4s<~ zjyK!#5Vo5CD1f2n4?WL5$-e);p1hPVQ#8KMrGX- z{Y|z7uxQjXgR*jD{~@l!fwII5)h{j`%IlVjWUt+ihp>oz;6V!N-(_egFh>Ded(8g) zxzJ^ll?@im_O>^CMNjNN-Na~POBld!(55k=Sc;um2*3BRsC zhQ<3;A|@lRo6c}>HIfDcz+h5m{59c;OhYM?H+8&C@B~ND0fDhx>}DUwm2i)O1ffP; za{bnICOAOTkKD0SP`qpChYB%IS=?|ve`qaINa`aHGgx*(y*lR>&qEK)P&-W@Cvz>L z+HUk?B}2q9CBkqcb@nhn1WSNowhYcW+qNi9o5Gaw>)M@c{E88g9z6XUR|24SH1f1^ zqlNk$%=&V`+1e+$QtXwb9_le9>=P$!*UCO~1hi0dX+NqNQO$Qk9G#52>hS*91#TsrZ(k*%Y#k--BW{%tnZP>VlJ9U-DeK5uc{#5N5nKVpM+$ zaFT+I(rG79V64zPa(*h_Q(LmbuPqe6T2F@b$se2J4`Qrs2NZ7A*+Y}%K zDCw*65h?JYs?Krq)0mp267_6v{7XwT&gWQBC0;q!7T-JD>fCo(#?9-k`o`;Fv{2XS zOX)B*3OCG-kjx$1MM3cM`pDjt$<4IAHc83EN9s#_tHlRZ#I-pf~csp4?i{!s#~fH7S>JxpRxftqey-O)dfZ ziO7${BZBB_L(rpn$@ciUENuuZ_ts(p50=C?Dv2B(LN%_lIsYHPajVUWjThOIf)yW> zaStGgb#`IJi@Xf(b z!9=mME2d;(A$-O#-XvK?0lt@B)f5?1xtuw_Nif(L@1p@A7Azhf0=A$Mqx1aeR}#$u z*EA-n9N({QD~69em0sH$Al;a^c_RjeLJ#s(z%BUEJf6Gzj5Du9kym z>8wXq$oJcEcBHj{Px9Y15p@%^VI-0vt%iM2jZp3{K(m-R%j-l28_E-`>}8?acA;T6(qoNX+kD$3x^1?RM6Tn}74bQ?84ww+jthTUz-|Jtpd1 ze0)XL_3WSTraT)NeTI1ON~7)dXt1@--o0v$~_CS&yUR5Xw0<( zvM)cnEUkv5Ey&bUGLC&n)<{(xSTj*LQyp}?kN%ghSYWb0#`H8Ba@_Y-Mr^cy>VSPR z)cT#Bhn3=^O`Bw?zNTT4$_i&RWV{E zT3tv{6T(G4sO_DYr1cxtN%(A;{q}KE$*N$&`f#h$63$3;d`w~yfF;vPGB?$^lmUG) zT1s`8A3KZAG_w#kPu8ckVXQmn;WjW6`(#XE9F5Db4>W(B~LFW2Ynw~BLdcl>f>&tTn(sS-jm8k^*YT+xu zcrR4e{It7C3M&VO@e`$L00D2I9kP zV<#aBLkMp>WjI9t7D|WkD*W-szQvi7S&l{nV_EHu4df;~kE|Vfn{5ZGNKa{6K%_|l ziR!doMSRfF1D*-mYx(3Ye>(ixx~=j1;x2);&2KD&CDqzZy%AzJ9$gnEOhJd+xcDAN zrHNC4sPd$5(rw?M#IEMsbq2KsHSq%4q0ZjlJY$AcDa0eB!#_6yygo-rD3A%%-~$!z zl&KE-3Cdc6d189-z!eE&;Q*tgL6hxw54TS~g8n|wJh|Logq1Fj<=?Yz4&1tQkxfQ- z@x(>J^mH&~0baG#*w@4YkF9P!pW48@%AS$9YHPf#68c!$>;G4hfgvaXS^ zb4YY6f!Jz8a(9D|cO8os!&1_Hjo}lITCisiO~Mrv>}=qP+}F5Mp?2Du_}?zV%?wSQ(s^Jk}G-zDcxJme##WW4osb!_~T ze}rDG?J?Ab&A6V|RQR4?B2`SXo2RVoSSZQkIBcE5q=KCbMe?yrtJ$mq4Cw5*mCDMm-r-wy(tizY(Wq@-u35abvm%G-+B_~iA^m8_5W7aQZ zF=h}()eMtXOq!TO9hE)TSIA1DleH!l&8QwO#f+Y`m`)@w2m`7aje1LEzOeqr`}k!Y ziwVc^3kvHA?3gFWU6xk2vHb_|aax>5>y>Fat!yjb3 zIx%8qjg>_y_{4J1T4%b00QwB`CSXAY49upO(cHA}0V%vGYf7)-}0z^3Ao{yXD?l6|7D zCv3@8ULfrTUbZjUp_?+4X-X##GR$CbD%73|Sc31#lNbj+b~{ts9txpC^`jH1BYnip zanvbA6?K*k{A8ghCpgDj5EGZ^o+(*yL*<@P%vBns!*%=z`m zUsE#Efz|;f6Ht>UPYAT)>R$S(*DQtVf8P3dz^`0_YR-7*3f{+X%NWJ{<#wCwt)^3N zX7%z-rpJT9Mrzg;QbJ3Q-n!&TZospT%I>~eKa9%xmbWx!q9A=WP#2LK(Uf_5lPSOa zF2SnY6Lq?iUu9$N#V_b%CGO@fCc(fGl61Kug;NL%S0LLCX^uErPqfBX7m$^3T;0nj zZ6f?`0PWa|1>(jLX+eSw(Ar@Gh_R86j(3jR%F}W_I-0#5VEHVFf>c1z+s1`$O1+zz z9k>4W7~nFPGn$6A#$zz91v`oXQ~`bnr@(sp&adu7Tb4Gt*a=QnF~7@?z4 zlX;D}`h7KVrGC-bd6jWG|8+XD{?`rEdNcIGt}R7PN;q=r%OzG0lNU0u@=M80%TLFm zHT@~!ug9WB^F^j4Z(RSKJS+VND|BBPHu*QXlf!^kR#weZ)(tb32G2U0 zH!Db@-Yve!PNaqx94YqyiTon}|DT3sIs1P7E^NJj;(8=<@$0c-@s)qT(l*_4rQOC| zv6hRE7`$=Pot0ESs6cKf=TptUv9lKQ5i8FZtNWRbE$XtadqgTSuQY!(Z)^Ozzarm1 zay@wU{Q1GZxw}ux?fyv`-80H<{&x{?=OMUjAnGDj6UAqlz#~jWQY{_Snw@`0Ufb`O zc-b8F65d1Jdx&`-H~#~5qf22YwIqe!ug_vhBWXgMeSokC%DeG@P^nIFt)NT%j3 z9%W?IK+woZlS}`eToI1*?~K`?WIxMWr>6DzD}t-RO9ojLMR8 zdC1JbI*h z+weuLWi296n8FCi^J7Rrj_)R)FR1lV7$eI1iPB^&O4qS|+7TLi_&#^SyR#>qE{ zo{-ZI2JAG-$+ZtOpffE>FAo3dj`Gz;6$T=Lk50YO_@~|MDoLxjZ4HX0THrcOtL-S4 z>s{x=+iRGUr@l9Z@2j8<5m)Y|Kjnw#GCV)8LWEOL@uIIin4Rf`=xFC|{|AUJw)_vk zEoa6q!ma*&GDQBSvITlnFLON~-cx?>tu8;M&R6PT5hqyQkYpO`t!&MvfdB!ju^65* ztYz%DX*a3R%yc48Qrq@-wU2iXT9P)0hl}|47fWxLp>k-v53nLFCK|FaYWh-;vI2sd z)p*oGJ|b&X9c%+((wOpQoXb3c&k*R4Y#cu=;BUQy zurY31amhE9X*A+_WIoEM_I)*hxQgQ$D{tofcIn#ww`}+o`&Jvvox3aD$HHn&3Y9@| zWZ;ha?u5;E?0(YK`z(@$x6QLz9;?K$RRM`o)cXTQzZBAZ28b79;%3^5mGS!F!rRLv z!!IOx8sq|<+!Fep7M|ypwfu10n_K|ya>xjwcH*?B>3gVWB0d76y&VqnMpQRE#Zw3r zN9Qz)b}sM${oEwajaQmC#?j&n6Z&x;Rv>k=N*h!_a>y&>Xoc9pQwhXC%H-{QFsDp1 z0{lXf+6)viaOg<>XFI_e2dxw%y`0~LMx*U3)NA3HFR##Q#Xg95uCZJ)>QWmA$Bh}m zNTFum@w-{BTvRJD$G0+T;ZN_Z$=9C#c%b`xIxl2tC1n#?AuT#N$+Y66NSp1Got7Id zZE3LjSr+otdofrv{Qa+~j=^<)kGq5++fi?q>fJ!0c8?JI2es*0;&JrTJVWd`P<~c} zfZ^ORyXdg&*v$x+_fohf^A{EYdm zca1p>jJm|UZJb4Ireqx?RY>$rVoF?<7OKi1bl~s^B^;pt(P?Wb;aFU5euY+T!}_if{#mEp7MSado13b$)YSw(&B^a62Pp^ z&rsSL$Dldj(w#)%deg#O9>e6xBSZ-EiepFCNFYk!88qmPm~cIAjO|i`E~o z+0HgtnA|N~VhPDRu@fu(i2G1Ww36|hnikgl)I=B`BNt zhq*zlV{&7EyfU-0rccRAwrE&GbwIR(vPi$;bhPV7X#^HHN~;dv0}hGY!QxRU=hgyb zr|6Ji0q)jIO}o6(3JMqL&M_~c|+W<04wpy=!22*E@eX zOZwd^S(0tzS=w&M;|aoOlUR``C-d|Vf^f?+i9%+E=scVTtPGSDuV7H%MnMZZ5GrFP z&l@D9Zr*UMqH+k|_+_z=5c^x59CBc_5%n7dA!!;X4#kU+CwJS7Sa=`9tZZwUlosf1 zfG{11D|cS9qUNk7ssEo38Fomv&$;>HnPh_o$1Z{-^J^PmNa2LbgxQ|oxg)JQF+a?M z3<`$$U|!R|GedV%+xCFnaEA*>3f`*6F#yw$)*GZP+lI{3x%_eRF5b0c2-C(q6BbG6 z5k)@qDIQJA58jC$&o6MP!9Y;HQV&Msi?`yiI& zwG1a}+vVanWMA)U(X<_ZGhA&6RbNJ(ky+*S=!XwQw5`_dGv!e3i6qA?8B@@54wUm~ z?>A6UqwV=qJ}V=Kdc0_LR@21svcc3;0b?!?7s!26CV#5X4N8?ejHoknEyf%Kxq}UG zL(_-MvI5RD>h&s^(;H>2UFe+e3mx!%>_CG}UaFN2rl%sun}DWjFA}1tAkWela8>4P zC*AVwb_NgFrLtZWcoe2&ktJ`%w9LtXTi)2N|L{go6M}hez%x9%?()TH zlJO3sjfNKkI;DjPm`YiDtf}9u=12gW)6}S!I;&cvg^64u?L~yM@XP68en6sv%12So zWKRMgJ=TjVUX<$8u&kp@bC(PeY0S4Z{2!pf*Jc7N6i20610vhqMi z6R3@WyOO^YPi#Y1aVF2}1ccyOB7DP^_H92Kco36dyXbETw{Ub6lFmO%n|fF`XBfr` z4cWrO+{M|z{Kd3l#Y2K!@p7MWF3Nc2E=QgM&ga5YKf2*P7%K{QO#tvMtY(DRAWfAI z!%4imgse6R780^c(b;bKHy&m8}rz&)+LUl4OD2tG+O@b8Sr1o=&9dz&^CdBH7g^ zjeb!Ppe)VaC+LY6*S1Bszsy$wql|9{q(HM7ScllqrXPixs$wM z|ukQ9{V%`5tUsvn;TUwtUJ_#ifR?`AOWo%2fiw<2-x z141D3;Hb(NI$@6IOr)>7L|(j#{$Bq6+ds9@-x=eX?7Mx|E*p!FKG_`WKO;hX)-r&v{v zgoJceTU95Z$t_E8O>+|PyTL1;pI@`^UGs7SK2*>|V^fC@-rNTLW zRrdEPr_VSg*(wyVqu)Wi_xDLy_~XUS6K2!VEV2aJ4Y$dDebufzeiXv`6rJkD$GV^~ zD?y^2W%jrx{a6zF{^Jvbz5LxBj&c$1uSCYeuG^Qh(UObO^Gsau_dno$=uv!OGi+xR+2%n-zr8gXH`v@vkxjklJs zcNmVkifnCo@zdK4QPiAG!4z328$dSwN5VN*&C8_pi}si*SdQC~lq0hVKBHSqFxbKg zNoDiap%8{11?hdG;PXYuMG~@4m40iUBlLjdK0K7&rjG;d9Cq=aamzW>hRq{=f{=?-yYnYf`T+6ucV0FK7W6` zGK~EgF+A|$LMo*d_T}r7f*_>BtL&jabNY0|+ zmI+*6#)Uszi$s}IqP3;+pQ3*K2ax!EwO+hsUwq$u@t?I6{Mxpff%<+z7ESQ8IQhv3 zvk$udPJ|s?eULbOQWy9v@}RFS^nIA**H@?FH=gmYq3_pxx0ZhOS4lSJ%S3kD6oM!L z-ru?EWM$;$`s&b`ygYG!`$LTJbcu8EKZ%D^;$S znN@3zAO4sT&>awsJrQ13C6aF;9UkEN)uLTO?@B8Nt^&JOc*hDtDy`&Ga3t}g-}v}w zsNF+)y|nG&XpKEKhUmd|tyRI^_+;}xSq4czNk79_B_%9IbVyw&lMKJ4@pc>>Ic|I# z-w^SJLfiY=cAU(QNl~hS@{Ki#KLY6Gnz@@BNMN5!{{tuj#sBIgYZH~)P#Wza@`Cyu zw^l(x9EV+v2_#GrY;uiThFLBQ1^@#tS$yf}Q228hD_d+p|Dc1)JoGn2>(I7?O%z`- zip8amTk!xJtQ6X;=VBW;(?-6jn>)x@2`Pjp6|r$R_d)rDINk2OU=aePCbJDDwnV`= zS)EWa=@}C%+9^}czZ6f8a@*8~3oJ4fT*Yp!b!WaY6x}{0RF?2W0+N5;nzcl0E10_M zJdP_FI8St{t}!HO3GsnV(g@&lWYF7{JO+&1*PNVy*ykM8$Boq zDq1UE)-4e@tHW*XDu}6W>mN4xaQ<6?3|n(1sFI$qJgz^<$i zs=*SpN7=H!?5iD;qg$+O$Yc4VAZ|8K?8QgHxtWXd-H!CeyWdXo9N*=DnRDA3rsWIG zjRwSL&zBwE$j@)aT^{tI+Yn4i2Avdl#s9eFxIphAyAY(%rp9-c;@$bc!kn-!E&!X^ z6ANK(>HTr!xEEW@*!pM~rxLBU)~SOI?@h`Qo~0O_$$8Jt19DqwqZ4>&smDrdCr-K| zjC{jeA0C@6&>(EXI9hhGVU{6!quY*}VLAIP&P#=R0BwTQGhmyJ!Q_HgPeP?b`IjGM znd2jM-rgEZ^Z#LVFg?bcTJ|t3dRK2hwsKI^4jTnGDQl zwUml4YQcyV0F)Gb0uHGMTY0i5xv=qs<0w=#Nat<`W1Nexo64Nm(BR>JfRw3+M>Rfa z{X$*I2moMwQ=#NV8v?hu)XKiW;ZX5ih?P*!D}Jrl+KRr7wG%hc%;^H5x&UkwiMSLN zQmFF7z|PxuVnU;ik1;$+^*e|>BuVW7=UR6Dn7i%RQ=-!scH?YbrxecPK+C7rE^#a_ zU;G5(k>C}JLSAfMY2rB~8a*yf0(dN%1T^-B0p3#AHPljT1Qre*N+-zVR1G*ReD-TS zW&K6%!ep7F-R;wzhawmcvd&Issaq@Q^DMk^d$&l2uZs&XWFG}fbD^5vT47bHx*Cx$ zkxlDswJ#H1m~U63~eK#i(ZW~A(2v8zx?OrV4R z)}5|9WufMU3Q7)eBC&tOPB%IQl^dInF0Y{ZxNv__RkHaMW3ROE#Jb}V&C@&lb@nz* z?x_Y&$V{a=yGQ^!nq28d`M)F_xt`=)ArWeyZ!W zXv0N8#Wsby84iQd2PyHddsFYgr$`G3?gG+~E-@xriq)3b)(r@|LKH{%(^nk)%#VAe zR{jHAOGbRY)VQIX1ibQ6oBznT|HPj-aQIkq*hlnPZSVAz^;X$#DRa#1^6y}bV97%P zAot_HGOq`otGzSGt}@SVKWe^7={|UK|74^&@JE@;MmUzGw(+iuX<24ngXO#`|EE{a z6n+U_75z`{Z?#W9+`Y5%_5R~4oXE{{5}yVA`5M4CD9Sh&=J>VW(%Cufm?f5Hd;G+=$WV*X?r;xA6C&weHVs*H zz8acxDw;iKpoH_I{cfNKx73S6-Z-@S-uI*v3#y?P%JNRC9`vbB)qH~q0PQE$%p10V z+$T3KB)q0fwMoO~nA`%k{jT2Pdx!v_wSlcX^si`q#~J@@v|`@yvu2UK znRPp?D$ddwlza`rMgMSWjM`%A{t(#Bqx0RI-`m%c1QGJRC#Xj;rC<>=hMgYO`mrZT zciR|^`g?zYoT6knRQ5ylD4oS{;80nyLu~k3ePOV;qWms~wnmk(A>2YDmW+W5@rD98 zf~QRQT*%u8sA4S!yF)%a^XlWfc2K6YL9@z)4inStr&Q{lTLIZ1WljW1ucoaFwF#!P zma(wS4wLS-2vcz(skX5(T;3Lq2Ff)S^Fb0Gpa7ZBI>{^lA9@wt@xP3OxIx|b!yMHf zxLx^TJYC+u*A%=pBNbe4(<)ISC&JBnJ|%gxJ9&QX=1|kuanbmR_O3u8ab=>D2 zmWeN?Ip4$Aj<6Jdwakk-7+-?i4t%7|%aAXCh#_4bs(9Z3aF(T=i`_QDYFdm>dgF0EL2!3=J23?ccoU~ zhSKS{cF~;EKNkAg!ME->2t&lZ78<8~x+RV@(tDf1Bm7>k=N2Ti+3#rh1%Qrt;_tWM z5!gG|JA+YdM%3F_!SIYpaNjh-NG&67D2@i}~p=Xx=-&{(h`q>tW3hhO9G}c1p_g!b-bYdwM(h9r5R} zXm@MVwN^U{g`R3t+`pum?>R3VH(FLL(=peTJl#1QIZ*3p4*kB}XyjEn!wwZI2ywP} zXOVYIDqnY0s?Uz2r=nEk%a?5*pk8jEv!Qz=sQh~TFJHH=xLi2iWhPgaCPhYQ)WuO^ zQJGCx$)a^LodU4mrK@>amd5!v#FpBP8X{{(8&*O_jgCJ?H8|gNoK9r~#B=mj+e()m zwo2j;6@ke;jHOJv$-T9_o0@h$zM2Q=AB`e56mhyl-3u=ou3mr=w=hm4bd%T=(p6vjKi-s^*8p#pCi2ESS zrIWwMk(-`C?D_XRmv(&{7diYnQ|a1j!t}?u$$}uq5LXl^RG?!+T>m!ZHci@>p1WRT zXdf%dA+r2}hY)IX45K$p6Jo&64Ao3#37_&v3Xqka7^^xT#WN%3a$OclcTZW7CxWmR zf}-7wzd&r)vLg-VO|_!G@9)QiR$3YyJWObiRn8;*CN??mL)|Syo-Ehh%~lT%carci zF0%d)KodITK8#Q2j|O1Jm6l{Rl~Lo5Lx$gY zFWvlbg*0K=OK~Uxa*EfmYjGrdg5CFJgKk^h`}FT=5<<5G$w$TFc^$@if1@}Y2>8K^<>Zpe@Q%@K`fpAUJb>v20bM}@4yKSA{lek= zO01$~Fy8}!iZ?l5-F=bBq6Zl8WUNKF^?g$xj6%KC0?az#1!9IWptGf!F|}j)5hTI% z-(QN=duWai6%)yaE2tTi;N9l#VE+i)VXuUch6TXzPQd)QX@;!0wa2ufXxdr^AmLF< zzCaS`q?!*8xUL`JM3*sF&N8&9O(yw=Bv)F2w9)dNtBaWJTGBlWX{IS|3Yi%dWQ8Ot z<%c`pI%r?Og)4AoKy4pOaxFdQkp{t#jvvNuGxWf0Drq!474nqG_87+84pNge3h=Ax zqN|V-lNA4h99qOOR7jn1&T3QC>(_7mjGEO=r5twFNf`--W@#}T7dA}KcDeaD4uq{6 zj1B=FQZBSJ{JlT2vHul<6ngQ6Elppc(Ju=6#nyE#$L6z&G27#D7hgS=xrfJ5p7Igu zv~KWnBe8zJ@DjOYLTcBRgCVc@Tl$E# z5=MEA;M@Uy6Mh0cC2=&9!vmQT{r zdh*V%L;aElrbL?Da{*CjEUbYU=^ z_t7%jrbcyQo?EIj+wX~7ElodHOY6^|{Buf*EFWDxG6GqeBG0ZM`H!@mw_=SJfq>CM zii9Gyx}d>)DTSWhNN)epIeYcKz%E2=q*Z370_a^ zkZUfO4f_sXWyAC^=8wkwJ+FT;8f_20oZaxonm58V&K!t!ukL(OyMO1ax6%2@3D!Gk z=bG5L8{hD4s}8d}B&pHRae;Id<8IR6zH)r-dG&-QKx6AqezWDa-8;=0W7a)0Trc!h z^M{SwJ2zN8?g)+h*9+12yH(TWz0VRZg+1OLGy&e~-ungk4={@FS~8JuZtm;MYM!`g znm9gcwS0iXXHfAe?ffp>)m-VrJn6R|$Ngg|zBXD6%bq!UI$tWv_c^|zkH6=%@dxK? z$1OrjM(LijA)7=nEy>R>nwvE*&=fJQSJ+!FhS4UnTw+T!dM^(CQ4xpQ9=wCC#!1UI z-5Qj!aE4SU_}|W(s9-;yayxRjT(e+4!Z)lF98yHwsGk4O5{3(wD#o`ZmAil=jJ9#SDzRb zo-gpoTgV8OS4slCeUwXePljqo1zX*5qAH(bLSqs_4#~wO4VdLD2=$HmJ^vCOwzS`@ zah+QLJdTDhSrL>wFVnr0)}<}k7k?l%z5|lqVHWDM5jXCK-J0Q350X5CG6S*gO5Vv< zIYBp`!sB~(JiS48!pL$cw%q}-?2qeP^?C-a?zz~hjL+vZKCWW0CQB5bw;9(}YQ`*3 z%Cp{?%C?y0VdiMGXA}D*f>;6Dm=*E?TR;ZTi7=8URqeOxsaJJq`1Z~JKc-3P)*Hd%p^ryOmR{*U%zl^9f?7b zjr?3P@zO7KhWsneGD|96s~*=1G{1Xmx&=FJ!{g0a7*7^Z9YYmAMHO#pUzR$qR(7cO zwlC(@Ve#kp&w6XT+K7t(0gTpH)|Da-B4#8F89TpE<#u&^Hl}Tl?8W3;4Lu&85W;&_ zA6ufx#+n=JD(kGmt1aqG1ah1P(E+Cq<}!a}|GIqLuMyn)xzB1pf^I!{YrDU3gP-qh zBxnC>=u`Lk_0QpR{<*{)k}MzjU9jfV--myswy+Tm%~n-2i`QaU+}k=X-RGK zX9-zO2hXJb1IS!mHcxS#E-oE3+^+Z$cZ3;wO#@%=_u)3L<@palBi{?v{2kkW`c+XL zRTzb%`_bLhbAmXb&xMici$Nhn*<9H*ngH7kmKT`6{SXTB-#D8QSb z_Q+ngcre6DPc-#5t1O)KM1gYRb4p#JqVk7TdzE~8wx$o;S1hNEVyyy&DNJ^X0eJpFctfUJuRSBM%IDJW6z9T#mvBZ0(|+UWhj4~ocS}K z^6}G&T!Z17G|}Pw`l^3=ns4eNVpPQE9&*r;sR5oA+o3l%8I*r~Q{&|p1bEMapN6=Z znYGvk+=xvsQ!ujpQS5_@$%wAXk#Et`d;Eoe3SHQp0HZBhyx;Z4P&du2H5s6G06)pV zC`Y@jEoqSw=WEF501>5*4ag`i4GMQV&oaf0vF090D$+D|`BBmS zkx`Tqh8(OSQyP=aTx4_4nO7Mq=s$(XYRkKGCHrUkN4TuXY8~EU`{UE~F=1+!XKBV2 z&Q8bysFiJdV?p2328i=YLsoXSBy5&uxyZrfv3myCA58ypHKTM!pb+La2MYKxIzDIa zq|%_#yHt0O=2lk4EtUxlL37=F?O_7hqlMC;S-{&Ad;(Of7hnF|`3xxaZcKyu#xO?_ zb170<9I~Q}#VKSuDsvlk7y{X^Lfg+`Uo;p6b6REiEjHl z4n?|Z>Dr#yA}Vr3BE3^|n-A1+C8?Sym=8IZmTjGJDXIMoLm}T?mT8(4F&X06WVewv zMrv+yqgqqZw{32~iI3|CM;IwjS(SfF`geq{VeNlj{vU5={nymnfZ;L5sL|b{y9Gf| zMmG{;j2@$u4gnRxjqYv%X$B0~=n$nFRHQ)(0i{I+RK)MgU-ABQ{(|#4&vT#qzAm@= z&+~+27WdS=3E|=;xj{oHR_&{ey*a1mW~y*G$%<5HsD9WR>pmWD~jy3Xo0z?75t*`}_K$I)RG8zj``*B4AH8hnFdRz3Fr-%LabA&4!0uG}RAg z!oy2_JjGkS8@O_7QuC=D-f`}ng~PB(=b!w|O74XcpcIdd6uCS($X`p`bL}vG=Kly& z_j-0kYP4T-vbO0JR)}C@y-6YITvrkv)}izZcgywuW2gJ&-T^;E@_uRzcWkJ$<>vu1 zo*UXOQ=M_hKG+5y3b5HqEe@cvj4|ACr2Xup(*iat8h@5A z3obM++b`ZzBTDkupZkU%9>0kQSE+9g|9k&Gfcrn0ojM6oUbwE{UBeOmhNNilV&4~ z^7htq#M5iNH+2syL=uVw9wh$%9x{!mFO~1M9yLD>&&VS0yly<9Q#K$=;FTP{jQAZ3 z$kQnA_Y3)Oz&*b6n1~-&0XgjANH?r7wwtN&`_P< z|CjXd;g!q8D~v5>VqATpV{-V7hVoUWBKPgTx-}$es?9%~mJ-|XbM`Rt;si>SI1he% z74-^l*JJ?TUJZ&=l)#=axh!L+3vag~r$5_>cMbCq=U_-pWFHEo2hO;43J9K%V5QLd zwPK~zrPvYUQSgV@1FsZqPjAG5K$|^?ODe<$IJUwPKYyQsUay-BItj8{%ZIX9k~8(* zN3}2YLivLbB2q%vP5M zyfR3W6ElA|*wib8_4i@i02Y~Kq!S2pF5jIfYCi2udL0+m_E!6f3}HEw-s7N2j~Cbc z1^g}_5T*$MkKr%tU-S#54*PR~{VxVT_Wo^qhuX#+(`@+Ul-Szbafnl5WOg7?EaE;) z*`!uT_+vIFYKtS$6!_!2a<@?29%C5h+k0AqNqTcaUH^;ECv-E${p>*LD=4;nK)3u|Y~hBA|Jf5ZyU*gPV5`JK30Cu_@$xJ(Yys&@ zacDxxR}t^$od)t@5vBLg(nMe2L@t&nRKCAfM1-3Ub_NTl0|C^+mG2HP4S>BzW36Jh z_|FkySSu+gHOPepJLevc-W-a<^wSj4)!^e9m)4Ow+!ud2B{7#F?N*yo#5B|!AIX`) z?#c6E&Jpxd9S4intb?I|^5-S#Y75EMi4WFxWfsb^DQODd?oREbtD*;_tXN^JW3;om zKN@mdZ&E3_y^r~f+Rgfa{#?(t``pMRmB^@f(k2zZ!A>T4nQ3S9M2#LX`| zOGa%6sGu!5$~XNS_%D| z3ES_m4jFr&aDE7Dm;UB{%6Wy9xdQ7EsAtOR+PoINRmS{{vji8U{OKXt&b*HcSU{WJ zMC$7=!+YCvb(bIGbP0XLj&_KykeG?>(<-?=cWBm*j6*-WJc*fPUc*kMd@(HBJvdQc z@KYTNIlAfuA}g`T6^hBqvb71K=BWXlSQx-qNjZ*xc(TtLX@%wq!#t!rbb9?38<6Ao zH8xTH+%7c2WhfBlq&s@$1!@q3u11g`T5}K%0A>CpNvf?}1I&}h*K)Mq+6m@uvURPh zjAJ8%d_d^opbNu782ZQk3-ie#Y0qw^ZIuL z152UwdCU8`l?{;osOQ{|>NX-?d*8z5bhdxbbMh+n&HY$S%pI-{St))6hIB9gb)!tZ z^vDMd^ zo`mUdRcVZQxg$O09s&H!Dq-3Q2j-#l8TIL%fOFc)qVxVQ9OcwctXid}80&I_a7jrN z`iOm2pP{6c92R*2H*c9;z!n`Zn_}uKP%a{SUQTP9rp}u}nAR^i6l}zI6YgBBPVFU`=I$Fbt4%?U$pvv5T_= zDsu5yftU*b?>!4*msY<#_LhR7U!-|wMvJU0``{q}UHe3^0ibH&Gj7nTy{6dBdYIj1 ziXOwHHu$g%Y-pm(M2@8VZa!IqzUr!!Jqd+F zt;K*)9hMQW#T^Hflr|2WUmBE`jtrx&T(f80!3j~n`=NL@M&8bVAVF-K6!&xGC4kc( zVeQzD3I=|B#Ej@u!xxhnYhq<)Typzaq`oxRN#KdQ5@!7z1kr=l^`c6{(0~IS$Q36)Re;${{v*ilEFP# zZPXnWN6=7hxA44f5`~p36wcgmN$wHhq4qkb592YdT>yKzezZY>E8kxefI&|# z{5@YV@4jO~O39tL=*g!~wn`Gu0rN}tFR1z@r4J|>fM%<}kzG`^<|o=Qo)+*A$r408 z<5L)Ev0HsEHHj`OeQW?^8dUJS-&cOsSaW)p!fa5*$6VQHdB3P7TeyJL238f@mYc)J zIBfJyfzrpQ&fkDHFMeoy%jM0Ea-KJ(gGny!J~V1jN;HoGT3lmTC@SR8&D~4ERl62K zFh__CN>0=}5@@*@QvA;Is19JuiJxwla8J6p#sE05IG;A*=LKsd%ze0{s-h`o50BCy z7HAVJigrhSc>w%cObnL=`XNswq2&eX5)q-mN)Q*#{2JjFa(%GDPa{4xK{Ax3RIQuc?+G18j6So(ev zYIwqTDOA>|wAeNy_j|L8Slo`j@9lu(CFSbWB+p8iAX-FC;XQgqBJ@P8t%ur5a z=!%IgT@U>u25rW-kZQ__on{0gjWKsIzKq7J*#3QS1syiTek8OikUW6Z@KyoSTlKDw= z`XvQXO@7pmgvL=lF6qqVLKuit_(gnHGySMjG+q8QDgLgug$|6NkmLQq1oDo1h7>j6 zu37a_UDfqqm^NLJBGQ(`ZPO6$**FD|2X!Ab%#Xya(JGj&8sLsiX5JT^cxy39G{o~G zz-CGOWEe)$jDwT$iUE~op~BAzteR0HAw?~6J&Xa!-QHP`7k??BEMDT3hfqgPt*Z1zKoP;p#Rs$H>3f^ zo}zOY=c;si8hy^?ovR;LBv*|80RsDeuScw1%6j--q!Ypq^81(E!LOIzUM-PCKo}3w z&v}~LGn#`&0{;UXb{=mQOF2e(p0Tx!Ar3s(pPlo4=dL!bqKJL^4!U=1h+AbwV^Hhb z`5O1{W}w}0{r*3I-Fb;b{Z}4A%j{}X3(oZ$W)Mi=7OB^wM#{d`LDf9l$+1}9OTQU6 z11ontv3os3g@TEXCNiU`vblbKVp;YuUbOta+0KT=o50cvSrytv>hbHP-L<}xwa&VU z#vnvAf&*d%^>lL)5??+-->1J@Tl;+||2+sh93IJfeE!9s3-9&NbZ(`-8J@Jk#v zO*)dC)2ax@S&}NOkZDC3a7R2#gkH#$>q^_LL7IlksHWu}GPaNF^Y<9oR;LddiUg8R zXc?>6Qw>D3_>}J;n+&_uSZ#>&KdZmXcMK)_f*ovm(9#qi-tUlPkeMv5Ml-kBq~CG^5^$cFTLyz#8*Y*WmmhLt#zsxfW4d zi1Kn-jl6kteMiM&$?ZRl2b)b*nXDw~$}*5)V=+J?7PTTVjg+J(x6vV$Gh!SKYrOCd zXuwhm0f8^E3sTfIMrBz(qM2T?HjRrzsWRuSS#+lOHR*CqIr5qoFk_LHhr#X$?yaL2 z@c9hNvOcb5vbg^nWZLXdKvaC8M?y7Xiqd6@^COAnQQPZKGQvvf>|3B?A~Y6l0R7y} z{J3RY;sTXsNIAX_GEh%ysSk8>|4d7_o9w?{pX+U#HR2|3Q)g4iNytjh0tcno2}Ir` zTw)7SO$)R?dMn#1K7C)1j)}p6JUjL*ZrbQygi_#;mgrGR;XxBw>tFf|S$~QD0hVPi zDei5A3%~ww6+X^%>fZ&oUcajNwE8ph%W$}TS6Ab8240Z&CaM>;d*g4@tSbeLTmS3* z{qoiGl^*9SK0#X^{TF2kk*OTk2KF~*sh>pA>iT3Sh>!%6C#FW)y)Vbm zD7>Nl{`66jI9PZ%O)+KU8(D3DB<}L#1nur7VX-O`HSp8?YLy#B;Lzf6$ zWD>X5qWhO85nRy#{!EO5oPwgPI-BK5cnrR-JMVQ%x%jm%yvu8`#bU;2S38M1VBPID zx7w|E$W7q!eoiDyJV;!KaX3!R;8mxKC%nFRay22!+uOF-1|@O)fM{gLVp|W5^(n+U zYk}j;?L_B(vNcZKs+y7Vrw82~v0t_h$xC`stEmF7vUT70*AalWZQkFnqnVtc0+7^- zjJVxY{7)S0&P#d47Cy=ct|h#d4r>kf9;%;rtT*I$fLVPIE|8?HP9YhcsbDwY7Iac{ zHt#w2tDGrH8+XpVY7IH~SS`7FF=Y#jbuRHD=^wE`NWmMO#TbXg1x!jFNyxYgAFQ_1 z*!|ki)|?7+Y}xJ262CTi`dF6f5Rd*&XN}5S4V|v?!En=1b@EPxysctGIvv#tF))X9k%31~T1woVLdgh@>HJ}pt)A)or zQyq%l&=juLew>X9NI^UefihoALdqa}6vRzPd2i%141$&%(l!Pj(xhv>94fQFaA_4B z(t-)L%#R4gb0?eA9^is*Zg2Uf<`wl(YslqkeVG{Vj?P5(HzInr^VxD@qi?e0$5p`WCw8qzrRO@GA)L3SFft%`J-!;O+)Z57S{& zfh49DiZY*l^rpd{qSoBWcLvMQ(?Nkzt?f^`H^@1?VRj&qPBccJWrJc+}kM zD|hi%vKMtT>Zwq~fNyPAReq?OU!h)jk3hTDWS9Vn;5Nll>KK0Ap7 zEEwS9^UO8sOCx?|jp~G!-v0Rmnlw_ej#fHfqiQlAqiX@36WX(>OxVJcLu12WJ_6P8$f zWW{}p8=(`lHIqwcV)^i%7>u`tGpt|F{w1FrVKK`PFG;_aG437WfNY5>qnf+xmLbm= zk~iXJK1>>SruwCIAjoOrGULkoQsemcx=nlCeRRb9Rm4f;$vZ>QkzX%Eew`dnzFS0e zxZDri{xhyAnpu{iuvBnys&-B8yz_g>>(TEd%H>VoFHTp#rW(?)rze?m-om{n_E9w87|D=H+^gX}(v4@*k4bZ_x#na)jj?!wu{(+g$^#4Bn^(VwrKA2$*N;v+f^r^E&m9Wnx+X~AMv7DhvhF=? z>xykmdLLvus8)Q>{+`j!c(D~0=IG;_=q{V-wHw7M&mf?WKYTQ|n^c)F=|;iSmp*v- z&BAh#v1z=FH7hS=ep8Fc!Pe40CjLOkha!Or9T~dXO#*H82<~njyt+h=e6wdk%9%Gv zP_~&#PCd-+-ywyisd>Zh%6NY6?cAxWnzPH4(x{iSf4PnzYa4x&gnJhk4?K zUDD~DJm+VJ7@he4s$Xt*4$*5zy`u$m4pE5RjV=ouMrfjiaFCfv$YAjT9HW}&8WFf? zZ%~}{d5QGG%SU$kVyMsN65>%x*P)MjcK-pv_|g2`{5y=B&}BpF1IlG4&WGQMevT+| zGS^M2H0!_}tfoFB7787`7~)F$K{m`nh3I4z7cIDL5)*68LE{sn-mi8f09f*)ef6#? zxfDvW^DTJ`oK-ly4I=;!-Y!7w2B$1StwUA_PTT;YQiety!9XAdw`nLsnc6K3LhGaW zfXv-d%3e1w3Mua{mhNWwhd8bYG>v+vz{tnYDth#!Cs(C+bfj~o1epG>W>nI`zSskq zLoOag!AV3^uynApnAuflcVm@vSnzcmV&1PG@l(x-(Ca`bxq~LCVB|3m;Vq64UI%yd zWMSaj?oxiQ&+_MZ-`#(Y0AcWxi}x)yPb`5)69;azBr0D%y&+R6o{$ReW+WM$DZxwH}ax|Pzz#JJuC;xm~ zOo84IUKRl&!W-h~OQpFPTN-q3o`hEbwG?Kd%MysAEo)VzH_~A*+~BWesm+)jUFK%7 zZnZ&o32Wa*>7SfwKKLL5mVeVa#;kAhZW3(rdvcNIUmk@s zbbA4wg$%yWu>nW18Zf1p-F6i@x?OT%lqL1V6W?TNHU(Z36(J^Jz1nuj6-B<$R!Ju@ zFp{A3Y@E}~NB5A*EK*uB5t=VF7Byqxd5GYf|30D8d0!HMDJAn#6xCxCj33Wd;w18( zPKu%M3TDCag4w>Vi-P)E}@V!8rm$ zb=#LXxKhl%g~+o~KjSZDDE9bF@X516qQLg7FnO;dA|_h&oLNQZT29y#!*I3$^^v@_ zXgkE|>e;pk;CEW`d1IPe;=PZ9a|mkRMs^w+suAd2V+z|6ML+IWF~tWbUpke0nh|O` zECU+wiPKn;0H@!WzC8-A+T@wbe)53p@46#(sf!Jn z^?R%Y=ND*l@;mKr8wZCb6a0`*j-Io$*7y4+ocv8MHvAUIf>i+H_0`mh*UEMr_cDgx zn3n?$*8|WYib?EoQj5QcNpc_{W6$?SWY0GCDN9W5#O#;{BTT;Ex88OEFf!qz=EBo= zO^{ixukW(f4VWI;DzKIK7HVygcbeb|xm}`V7}Z7vQ%UY+F*%6+t|~}t=dwS`<3r2{ z+9YWWLeXpfqJfYOh zQQLN3HH^}Q#kA@LsV7Qys=&O-kisJl~(Nt!gNjBJ58_QdjX-`TMa|&wL~2 z;6g^qTle;&LtHJAH3ZE>CP7e8XfeppCef&0sXf?4FMB@Xp8Pf^pa(8={94X}Ui4cAFOxu|(6RsX5Y|dPN_k zI>kB=>MOvJFnX@7Xk|=FX>d7Fy}@!@=tI8s5||LxRFz^Itb`eV@2+Qdc5hfzgHA<+zGMGHM4Gj zAcy)w!I2f^jWXdhCG741P(pTH?+Xht}NP)3T<;h(v0#3tI7eBJCq5w7oO0rg?D(;Py59TQFRy=#<4{^r z)cgkw1hWd1YEA>WN1tH4I!2}NExO`1>xpO28ST_Me!0HcvOJ~y+xEge{)L@>^CS?1 zDy7g)nA5@8U6D%FXPyt`tn0IEa3kFq!GC(}Za!h=!XWjy4AAV3UltSN(A?Y1RN_G4 zBB;+@_{Xq7R?5qHP%T(2EKv{J1tGXa8Fo*&0S)R2TtkH4tW-VkS6{_?)z8v`I|Nzy zfpGx|{aqaX*<*aTL%II|vHliA!%7`T?Duw~3SLm5n^-8Q6A6NXOXn1!C~lmf58Uj} zW2r8vdb<0fE5`t7D`|9H6IV_5ZpuLD3;ybjB;`>k5b8xC@vyou5tpB%kdwML*kF?nu&;HE|k5ls+$SE846mn22V6{|2r+2(PWp)*-F!U79Wq*=($umBS( zYitv&EvISMHRol64iOZAj5lBYlI`z0cE+JiL9A1ny0RaLO%rFt3}lJGz#mO-IY?Ho zP9eMSUY8^|$*D-6d6z;>=hG3-o=w07UCXn}k9^Orf|u_t;cvgV6b*Myt6yYo=SlZ^ z)3EcZImp5-G*Wbo{KU|b+^h_gRUcl$SM?)u>tOXRS0-I^qrI9+P2qy0t(9>$F~;`E zbMJ8HhVZrZ;@b8<(%cco#Y@aqA-6to*3aWHpYNMxTHD1YZn3}!&L8ww{X2O-T{#}5 z`(E*_@enEpuUyBhmoKI#EB;;ee){wuU@9!7jJo$!@Z;*G-M@}y6a^r1cK=#2=j&Zr z{mLNH`24vt$gC3UwKe?Qy3l#ud6ai_-)Z9Ft?0Wu)*9cr^D?U7FmfCCn3dBjucivG z+dw2h91vW3^27Rqr=&f>8yKBZMMT4_^*#>Yr%-_U>0FT;?b6niEi@dr<83-aB7NT; zSxK0L{>{&_^-VEe9vs~4*zG^`V2)QY^9b{S9k|oYqYlXqC`@544--Ha}fzK?d3;^bl9hS)MX2?_BWQjXqTzi+R zLJfiv#LbatKcKw2I7urb!LisOR$h;4vNJ#uDXBP)Er<2L2dMf?*=>j>wK6>%iIc!V z(H%-&*2$a=kr~pi8SHXUngXC!PW3I%;>=v{Mwp9jj4o^j-GEjQdMk&XY%w6GSNs8-E(%5CoY|fcQ;P_ULNyCPoMv*wF+8)U5KN& z8xmP0{-mhhOV7jjcfeKcCEvR9qrT%4zGvb2uMU692441!1=^|E`|{NKP0uWcGUtc6 zuKoJATy2dh&mo>!0@!o+qr*nhadfMSG~=_ z_qGn!t%INbc@^R$Rs$>&j}fnkt0K+L4?9a2{Fv{Bul9j^J0exwaf3KLtB5>urG_ol z=eH6+H__aoz?L*_cR%qJgxx}D7wIj^3us~mNSYq#hD4tBz%JGtUA!oC3#f-Oy{hqe z`Z}!qlxqK8LldB+}%VIIOuXPhCDj0k{Mo(R4_E zVew6SQ=1I!|2{?g!0V7d8ITlQ_){YxZZ^OnjMHTGp7QHUG{Hm+g5PQdv~6J<^K|_) zt>!hQLireQyt~<)i4bKofBE)*VsZ#{63_P;(}dlOI~gESI~j=R-0dyGhXLfv9_I0> z$u)EZGoVZ>)^b=OzVT%#fn)RT;9Pas8*2b_Hjv+W*~#?kb^)%X26YqxBgR1oksMG&ewuk}BGSiYMHJVDOQ ztC7F}lum!ZLp+__wp+Ma|KS+Ws#KuYdi`u{01*W{1YH?t{$4paOQmp+Q`CcA!G}ex zpk7GTp3I>8M?*s*EfR(@!q79Nm#Z0%c-0pdl}XS#Sw@FCg@fQjsjd5FYU1Hq zNVq*i)(`Pz2`qis`*JdgDz%Yf63VIVwQyDi_PRKJWujKM58VNyFFJR5u%p;R)jo&j zoYsga0FsxJD=uuJ6>X6)+PB()8`roS0-|v8|Ll&Wr>JOm(*~6plBKW~H9^Y5zMdR~ zWfZ%TZh1i#Uehb=dDpsAbp`{5d{!U}CP0ayu3gEmA*#Spt8CTQ#y>(3@s`m;bpbJR zMWQ540xQ4Egb>&vVe7!&hBC#QWdEh#g?#@I*x?vGc07^SShe)CK90WH(pv(nVa%VI zt}PfiP|tQB4zR_>ez}|ZB2;&QcZ1mQBP=vZ^bOB~TTF842+Qhp6V2`-wK%5uQw{Us z{GXG2KIvf@=x>^RZPuJUspFer*}3lSPuUPx8o9-vu4j2u*ol*yeHImZ@?F7xk8H^Mg7#+blV@2 zwtH>j`l7t(`Y@28h7EaArui$`n(sSH<;FUMUh#{Kl!~qx-`2MoNV`Fgk=Cm53&HK_ z^x?Cph)}gONH;~W*oE2I7oIG0vO*sSJ0mPn6pG63Dv+x|KdCwbx%D@KL7Zl@pQfEh zQ10XJs!aslR@kBJ_P{MOA5dVrfzY9((k*Ptx0B?JFJy~-ODm<9gTEzoAic(Cdvf

    ii!H?-ZJ&vCrQ(rx~9C;ahZ}2+r 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

    C43 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

    d$akQo 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%0AX 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 Z3h4<8CUp3Nx-kB&W&4jiJofod{|Sgs<< + + 编组 9 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/public/assets/install/successful.png b/web/public/assets/install/successful.png new file mode 100644 index 0000000000000000000000000000000000000000..0a94b90d6d9b410c03907725ea428cc31ecb9fd8 GIT binary patch literal 56334 zcmV)rK$*XZP)bVG7wVRUbD000P?b4y-7D@iRx07*naRCt{1y?MB8SydnUn``an^zFTMtEE6F3#y<1K@lXSh|-7{6=NHX zO;jQ_iO<-*=cndV^Im+>_+pbp4dgRwu!BGZLIeZ_je?4nQ~}lZb?-Un-gD2rr`db2 zHQpaKyVsg)He=2;=WqVT?3UZ!qYf-_fTQA))IA)?46|Qx zpfW}`PTa24%@wygoNIVCj$SU%(N$@iiI$F}`~e^WoYKc}8cJ6O8MRDIM2MQl&`o)j zLc*(+4NI(~#+FW6Y1PXJoz$V1QSCWDJE-&rgm&xT@f=6G$ECX^lgbZ(AfBVlql}24J_nM;#YZlfbMZ7{E7H3MH!>(Nt{$55e3l zCU;P&vRpOwkBToh0+|Ntv7^ z0Jw!vNjD0!tzQre6iS7i9ZW=@lc|4DXtvPGJ))j+&sLN{_luxh+F*920KY}}(X zOaU?!0g{7>tH8*#Jt<5`qP8qMS9c3zav&F)$Tl{*;72MC|zr6U<`ERl$49jqXcC}KdS$LS{4+Qyx57`Gy8{|6mc8y1$I z9~N6XP8Rs-IwqMwny;gXQ-15=h61L+-uT`(Kw&)|?5#LNXMJ_d8rYhE&Y>L7l!mEh zw+%DcZpig8H$x>$<(T_{Mb4;NV{>{&Hg>&VIqt@~pY)GgXO@$q$6<=aniGsS&|i;% z6j&-Slw)o>5`$Ve_UrsaaHF+5ioPC@+&(hOrnDOHl9M?VIFA9%(yN6;Lui*Ci_^cc z;M%VxW4DB+^>db=lQi@Cqg-8)1&rSu}M>vjkIuKu=HyL4;vbdHxbgLldHM0 zKCW&hH;ox;Tdzg{BQ|Yxglr7afHwl08#es8@3M`tw%9HQYZ=K&Tw3y^eCo+4rg<_# zJk?-6i?l!Miz&>xKH=m@{5e62%HRF9ii%l=VB|R3P^>XS>F&oeg>xfnIH99Gm4as}m;Wel(=e^bU4Rc$=EzjUXk7>ygsLNVuqjs8oY{d;IhOqGwcNv#g(r z($s*O8tYMjDJdqp=dPnNd$2?gFqILrDvP zq;5B#v?TDUP7>-yguP*&_A#p(dl!dNm*1k%4cVNq{FO3_d;Nq?x+o)VqS&jn=q*BP%cb$>Va&E)uqqa8R#WG@^Yt^*drC z*JfzRjrp8pnPgdw64y|$6DDimrdzLUu{DZf z8I6_aeK&F^W`h6fp25}InS1H(Ael;1xK8T!W;?XC(|4bkX`z2=9-G%JV6)YZPMp+c zP-Fhk;CF;qXBE|vbnTxGKz9<&>Ei~#<4FG`z6T5Jd?S=#qMid7sbRCn*xuCxF`7ru zBYj{kf6eXyZ|LQ?ot*2)wJCu~>2QgFt#%5^a{RpmU23Q9axcSO-IV&R6psuB?&0Mb zWV2KF_~kuZT%1CF^)d#X)CRQ(T^q&|4+Yp_Opc!oljGRKdfXszRC3(;ypq4LHc4?i zeQH^t#$$Blp#FFbv>6!=+}I!9#p%r9pAq3(lLR-kQ^4gwmH~qd7z}`ZR{Zq_ga$T z;|E=Wg`7e}<_`xYu9$gA0Hm%uw9kJBmw-G2204%kVC)ZoUimvHfiuf0a3qMqN|B@T z=%`%)m)Z#^Cw!cM%}$E#eug_+33}ZY*7o|icWD}Vw}X2w?P6_p2HCZX*qxr*fBEPW zg7q=!*8OpV-BC1L-FQCL!Qx37E*|U{>TTtY#5oqfYga`)GrXn9G5j-9cx| z;f=11ueHX@hK{qzL|pjmfe|540tGaBsJToPbZ}gpIil_IepUHrvMT>O3}2&EWB=Ddf|}_Z;*$9*%Q-?nz+T zpB!hoeLB1|x6`K-2CxmCpsXHN+qihbVT|o&92GSj3Bh*lDMr zobX8yHrgrr{Tz3+9QHbGtnc=5&tex@r;U5IcCdD89@*(dTwb0+-hFZ`E-J?{n0{33 z_N2Xs{pvJ{ytth{rHmh_@FEUW7KPf!p4w)uAWs*jyD#GNX$tRwLlT?Htl8ay#Ywfb zUwLg!k2;x{!CtM|8?U5;KeR6a&_W4}0yII@_+egxV8-K((zMPhW|?OK96642Ig4qFRST+)~7elmZvLc5Apv9!haG%)5+mkk4!(hc}{@q9K#qYfFcX9XK52D-c zVr6v^iz`c5U0uS;sbws$u3%+#5i6%pVPRnwGqW9Zr#fi2lj<9i%n$`z)LDl}SF=Se z!L{T&`6G6r7 zLYk(SnwrA&>>L&s=diTAf~A#3tgJ3#d36P=tBY7ZwSwhSD_B`s#M0^#=H_QH)p1Bt zVK$e!9QI0MWjd^Yg69@+3J=azGsh{ESxV{ z^PKQ->d;FPZ1yvJqMag393IRvJT}wCpf|uBofJD~=CHZCg!|?@Cj%G{V}eDR!v~F@ z<2gxk()1d)j4Nixrk@2}5{!&EM2LNfE00#<*rXYK?-p+FckstfoV<7b!X94x(yzqk zr5#k$u>71t#HeX!sL2C=RJ3qcp7Ydhw=pxffW_rytSm2LWpxS5tIGvIo?6Dr>au5$ zi;J_EneAd~s*6_Jd6ne3^P0^C>6bcFRR-ZRkv(RBe#{}S!su~GzF?qATxdqOP_f6f z9CPHNU{=WEi_9GRB{&Y0S)KEkqoTp(E6D+5ts>!qIkwOrWcXN;V7rrIYj1$NX4=TQ z9XxP(2albaL%uqX^{eL4A9cdzq_c}FS(?D^Fo1BEIoXTQ`7rzUw3S!EgUQpw$h5E>M_IL4s7%vRf5I1b|6laK7;D zv0#p^RvX=J7t=E{SXi9L(#kTHSC+7{x`5@?)sQ)^E@F9g74!2`=(HV@1mT2Bz1TwS zWdSLssm<}>GffR5%x4DyisdykM@}~vlP-gjIrauXFE^I+7{KU@yUb7GkmothCJB12 z1Q+@lKG{hza1M_Say&HCM%K@9XD7whRdcv}Y94nkOkr@;Gto~1?8#$&mc+J-IdNr= z))hX+W^;nUkwbY{rt?c#>ceD43hU=C0In5y8xC~rhc7iqinth2YE;Yu$YPLd;DEti z5103PSUZ0Kxc|W-Y{?cm^M0xpgm$}wxrJpcE-hhYWdSRvma(+5Q~=}ZDwbCkuzJ-B zmR44&T>4` zPO+2axF>Pg>a=iqZ-6^z+8A`(IJ?uweXBFbR_1W-%p7*xB|z>6xK45d-;eAExUPgU zC=f%NtLzqvrbwfUidR~8F7}b_>V|@8RF5~(u_-|vwFWB*icb9+(ONgGj|Narvs{G^ zuH{jpPlWTE7jS;_0`7l6+Od^MjXZ~Q4r$s#x7)$=%rq7j7qPgqjOFD8te#rI^2#z+ zPAy=0wP22`r}Pt4CiK2PAFy37IJe z%(`%5#>pZn#~kxKT;JFeGuMM0$TM8;a$MgpUiTMd0Q&tRp3NSBy&|vMJfc;s5A~p7bE=xe_N3Qy8Ios_?3WCD`z+kUmGRMt=IqKO1|Ca&I zq1)|Zc772Hi;GxUSt!itHMS68vLx`f5WS{dXm2JF`;l_}z-0}$10?-Z?-uZO$-q9sylUEwnCXM>*Z%~fa0|}>}7<#3m33) z{ygr#UxF%CX;TIVhqTo~r_(OS9G9@PQkd4ut1DPuT`DGHPOlW>kf&C#w7i7b*)}?z z7Fw;OBCw*UB;y;}bYv06{FJI^rKdq2@h6KY0g|*}iERK=sKy;#SyH~ci!Po#NBr(c3 zO{MACgvlDH_$T(_G<~s{pdqybuQVX4_?&Rlpyz>*gy{=ZYfu>2B&%}*aHTozLSXgr zNxIYmfePl>8(_P)iS_drf%_i_^C6b;fHFAe(4CsW?A$ySmlm=kDB0%0f^-7xWQ86(J3uSJx%b{fzdzH# zFMRF|?k=tFVahNtyAptI*f)OLEoV+p4COvG-$ppmQAZ_aFUtt6aik<+;2^<%>eMv6 zx3ZNR&tu@})V1YDYp->P0krn2Te6PJvKIvt4Qx+Iml#krb5&)RIN?W9HfE2-p@6%C z47(RDVEz0B;C_URk#!;-b4<~0w=g|Djm70vEG;i#d36CRt1DPuSu7@JR#&jPx`gFZ zD_C4w#O!Pb-EIr5R$71%M=eRJel3Fh`qJWlMHaOv!k|RUJ69GjZ&=tU#w2RW2 zcECKsS!=J0SkALM05*4uzbprG;PhUO*Z21DZST96{{87${P?raxJyQ=6PGIi%qAg{ z#k163Yg0StFvU_7u3OGw_*cY+J!euv9BJv6)V4nW!5RoFV!eN?26AP0ZE7fsM6*iC zo-{BT%rbZ`sSAuZ!8!}@<8&l2YJGiNlKn~lx(raTMcGx!vhZoDd<9HVpb6Ww$Wbsy zU;x6PPuS^S#>U0VC3BQ{m8T~RkR&a1yHl8%n=6*`EH7bcbs4KGi=}D3T#P-IQQP(<#b~Qg!J~zg&PDrwI{WT$6srB_ef@6hksGS$aYb zPEY%_`Yg`3?|w=h0(K|-_@Fvniv>!5kvHrT5wG+kX_f#^=0Vg#?i_Xo1MHl?fb|QT z!2J)0=?eDfT(K0V)ox>Ub`A?mOU3S(l_fvsxVpN8rBelSTv}bl;?f*uXSi987 z*^kJ+At+g@im{e8gFylaMj*K3-bL}}956c%+&BX~vJUL*7GC=qKJV;h{NbNHNUwPD zQ`|+4>q-H-gM#v5fO-tU$XZZT{F!m7cGWqRBJAF{|`2 zvABrlS4J}^o+Zo}xGR>RgsKLzR&uGo`~W1+ZZcRn5l-fu6|xAR_b0;FN{jWB4cI6y zd483gn)INgO1{RhfPkU-i3zE8K!e)E{uq#Tm@vt} zzf8>Mhxbi$RWIgYGvwGVCuG*nZvqcIgn+@83%`+*C(^A}irM)EEG#W!X=$-o&$zl= zj5Dq-ms<#z%I$-5n4O)%)N~iEwAdx%Rpul_kz}R&=~dv-KCru2++XhFAOGot_*DQO zzyV|uOz9*5?m?u!^hDkR{O)CEB%2GvMy<*X6UBi7k=3>qAEEj-qORn%QD@%Gu9<^o zU#R>AtU)t5Zfp{0BN;Gv&{Oae`Y+js&WG2-RnItnCnE?VgD*W&`H{>_mm#S*Ja{R6 zNQMui58NzJZPHhFQc|DVEQ1B4sz&(^hwmw(I|H*w)Rm_{B-NVs9uayMFX8;fEj;j` zLMv}p=Ky6$(+;{*UChjs%yDH2OUuRXm}_ph7BBt6&%-mHbwe|^_L>5TY$!+Z^b%EOASDGWLM<(u#jmA||QZa*|Y_;a)*p9EvMx*5=6+vXIXD&R; z($(xr=FcgRFv=ldJF$|M&q+O3aXKI#kCqs433TwRNKzt^X3gBxEYeDw%S?tZo%!9% zu3L6S0cLXfiq6MOTd~ej^z=ng0N|f}-~)Ka+y11MLZ=PPbbSEc*@PTB% zpw(`Pa>MZMHrnOH(^IkNP_g@D6YZ-t|A;Q{UzcV15QzoCRj4f$0wB zhA1<(TuFd62__lrJF@tXd^SpiF<@hfz(B+a1fZuMB#9c23xcwymb$TAS&fi?RD)>D zk-pXqwEPVK*J585a9DZJ*Gb(k&njw$Si7bW;DYhK*sm0;;q$Mdf9>_~Sej&hG7OiK ze)lS}V2rbT7L1jWsF zCZIUzTDYTZ~ zOs)oG@?Haq?(K&#t6D?SEXI-?VaX2zY8gLJoxRrtT>NWQbPE*qE7fk6-(2XT%e3h| zS`q1x-~tEu{wulvz7hm^0Povzi$RB89V~Ea*!r4eML9#RX5VBvBy!$EK(1N zjLy66JFgeqSaKBOY)8fP_M1-gqT-0izBSgIEMCHwMv+@o3;;05v8ShllVBYdsTegw z(i$6DnIcpPdi9ujrNTrRh}JJwf&_CPt`1KGTsIB(x@W=NdM%LWpgSK0z2)P;Lpye9 z*UCogE%P2LUn|TovBJjmvck#xNcjctO1}f$L9(-C>p-v}yXLnn4>Fdp)b!K!!YDIW z4$Bb26TM0`P^q$SGxn(Dq%*yJft{}UR#lg7+L#hvbdZ|lK<HA@gnAEif5jmbE0XPS~;aNz2;*#@9EA$W0nONPi{KH*?Yiem0~ZmsqqbaUy%;W+V2~%I;Zq= z%CCq!Sfa#9Xl5r*z!vF&;L3HQ0l=}hV_F%Uwt-6j3#xtc<&BO%a3z#+VN@u~I0@mtKoF-Cs@VBlaz3EKJ zXI$x3H4U4`;|fbQkjPe+TfuP6dumk4uWOW{{U|x{3|$@RV>F%5wEdTZ~fQI|RV)(FjIf z6x;K8CJ%J7FVQ;&Iav9U_eHmcnU9D43B*a5uai2&z@Pcc;=~`6ySTPmuN1CHmS|4X zEW!iNMTWHBV)te8W_=~09o3(4C9Nr@OVDI5=GXfdwu@{iPK1%B<4wz;nrUZ! zs?EW@?cWF7{tn1 zc`>eusXsz<)Druk_Bgss3W(Vt1Tb0$Df)PMFE8b5(@h@w-a<+1xr{WeeV9VB5WpNn zj&-;)3g762XARrZ&XA0eFLlM%Y0Jg|_1wv43@Wmbi-y-qMKh)_diX=5i|ge%V7{#~ zpfe_bhyB%9lYXs=fxh4>xNm-GnSMQM1R%NL43dBM8Xyr?ncrv1joumErK`%l_MVt2 z>vAQ8`PIVDIh+~`j)7>f$2n3ao)L40LSdAG-N(KsTHDZpgEf3B>|riRiGkWd(mV)Y zCsFbNyQ7h$zx1Qud_yg1mQGqVl1?frfb1NBa9t8N0O?6C_$B2h@P`UetXalj509%F znao+N4aqdPAw%k?GDa#~5SV{h|H2=eua)syxsYtINdmMb6V;5yg{)3`(fgQcGp$u2 zxYs=!E=_%4hw2+nglZv8@}g$~w_g*!FQ0d-`iNh@so$Y?ys(dp%T)uC77c{Ca+hg~ zIAq22X_M_oGId=K*^53ukq}H+4?TGU$HUr&$zcHLLE`gftV3;6jU`r1XZNNqbR_9z zMbJ*_(96muoErxfS@|WP-iYO|RMR4y5S3B-mz7iX-g0rN49g8NdP;|AoPKOfS9qnT z%wO4nlJXfrmyqTg5^^jM;2jH+Rq}IHR(|iX0zm+{h11x5E<@Buc`CRbp74Mj4m;RF+XpW7(ZM z{~v0{IsrD2={LD=>69N4?x>Fmw-N+aDF{gP+OL|5vT?I$Hw*BrdxHh(#;N0#Tg)WG z)N%Wd+(;%OSw=*^a?Gp=R7i($y7fq3d}LM=vys4FXD2`oH`gvh6ZkMh23uKbIRHHU zG%B;%>VVj1L$}NRxMPuMVO0UW3`T=?O`7T$D>B6~(BM9nXke4~oz$Vj$61T|44^z6C#^IkAY8vB*pp`g zgu02yqPtMtkgbNO!&&iKpdcS>(A4ocYf4!D!Rg6bUx6qKnK0aVh|Gnt2sEB_2{LaN`t; zzY6kdfLF7TA}l6os8UbPNA7KcyiBvHE2y;6fTLMYtTU3%5tB98cO^SM20R9CnUpB! zK#v@CeVTKql#J)4yi5YqrJ6OABOFcr&{3?5oAmhGe&ZT9oCMYS+J*4Rm!`UyDQ2b_#!!#n1rr~DeLz5@6AHYEcOb*nIwa*^KPCZe zja|F!c875QSr25X$hwllB~>RC%z?@N;DB^v((Lafn6kidJtR2l!7qziOgvW-#F)u3 zo73WPNl2RTKwgB6$O;y0>Za;(P?JR1U?5yKB-C-jyE_#xP&T9m1GmRk8$L zPlK9{?vh%nENL(gJg|(j(^40tl^qAI_B2w>hz-*ZCX^&P7 z8VYj5#@zHTUrRHU-E~}ELEXjxPqr+kQ~Z>@XTVck*vU%MK~{2^m{Vb7TMO30Xx&AP zl}jOfI_15SHJdZV@$zm7s(wMrJgY=Djv_QcP7L_CSr32D5immwnwbD`S-v8Vm4o8Q z^~PPnqN@|H+N6g7L~ZKUfS4sm_(30~l}}XFo7&bc@&2Wo&$mw3YAUhkI?kdVXyc(4 z)joE{9wxvY6?n!LCGSV}br1lHW@Gx^GDju2#Q;vmr_bI6^hw1)z&?VlRzP3_)at2z zrfQVA+(D!z-2+fmKq$wS97<4OrluH16!EY4_gKSwAgb;ih>$Ow*0pSh{*--%DN7B`>Lr@;9kLslK zY-=!a6jM}pLv=_?5<9f7z7F-_#AA@7GF^uO=|N6CIg}j8f@v~So1~*YF3jTK%7vJ! z$A@qV07Nnb64#<()K>FZl~^%?+IlmfTK3LhB^o48mhkB!1XSOOWj#?fGEQHzIp0NDL>s`R2i-gsY;Fd1QS8P!aj?Nm1Cy9Vy_HCM<_2wy)_DvO!BS zJ(*`!2D1Eg$HhM~4{~j0Q0%&^(Dg@n);lu-uLAr7OcOU2!2@bXJO$BtKL=Z`ahU7l zj&nRv;>a**1Ut*jjLn={(v&YDhBzGR<76^Lqj7sLqM~}X6Lix? zoH{<$2(%v!6cY6OBc-1cVS)yx^(hV2OM@V(>bDA?1dUhxMo)Iu4c#&)85lKCN&}S_ zyT~aNxlBfalmaTxC?oGfvQ9$C+;pAr&m=$@3OOVj4C1?OTZYib7_whBjK_6(f1E32v zE*77-K_A%3xTmN!wlGgJZ`zM$L5b)*DpQmJ*MV2vG05q-4bfnv*=@k$WM0&@Q+{=l z9)O%khu^t6d(P)q=s=<&S+?6sf4jRq;rTBJDf$M^E|3&|EW6M=eeDP^`YBi<%I zM!FAfA^+?9%NR)fve8(@oPn1(|Hl9$+$CDUt9JVa8h+Sy^jqt~79no_s8T((W-J zDWB<6Oak_3>1X-jXQgTMr;j54nRk?c7fu5dsXEYKeG>G`e+9S{Ay`=qPnVA_lSn5( z<@5X2g_iZ*vDI!~0R8fnMrJ5$Ot$t+f8$o>L+BesqZycypJ2lAPKxyvA+t-8;#eH7mL7-~ zmAZBkh0&8kc&RmNeQ&WHhdL_~fXockn=Y1c95PPURj19Y)`5QU!^pn#H$e}b6S;J7 z`2hJ_J_!1{-vstj1nbRA(Ll{ikjEZH+IrlqY_0U}Pk2z1%S>DVPNm#;PUI!Xq`22Q zS!~My7XQnDC%?|70KImGq5KtSqb&vk1<6SQ>(>(2Rq89^F=qz2 z+$CrstaIFP`DHm)`9i$I%Bi|`fXmB|zQ;Lg`S5Z>CJ$XE^(n+jeo}ENv?y&Ogk8gTiEB)*N^gVAy^84QkTATwQ z%xRR269D~>{|$WT2>@+`9fBx7r$0iiI~`e;7PI2=%Z+f>i{MA9d}P>w^=Tcr)5}qt zaj31g45M{=<$S3E)m)EHj{BRhqe{~Ugpyu1`eMVQ1UlAfu9%hgHI^HXtG#<&HAKY@ zDkoJxvd-)EcfoonhiWU6N;3dfnZExIpezjIe+-5hGz7&CJmW}2+NuTdX5yH61|XQw zVK(A~Cm)?;mMYJ_(~#hj1An`Y>~+5meB$9SDgcgh&|Ciuc*7q8)C$?0&z~#uM`9LJ z_ei?B>UZKrGeP~03Hhwl)bB@DFIAp^W2NOU<#HV5H^5ph85efm1}Ox9oQk!kCs9Vl zkE2+-*K`zBYa9SON(##9=z0L4I1-1?X7{}+vo~GQ#4`pl85uJJ4O-@@DpdK^kpyNe z6gyyWD#OcV4jfNy{aCKjVm2q@A(6IJN4ohmrA`7MEl~7&Yn^InFT99=f4hPFi+&Aw z<;QfI%%3%%=vf@?L|aafC&nzGzs!?I}PA8eJ^!N;e1i z@9YL3AVGn2BQx?O{pobe#=T3xTki$E<(@JtRDhN1gn;Y6h3gQGk;!+)<-ve&bTWa$ z+*#`Q>h0Dz7j))X^h%rwt zBdgO0%wXwebWBkGgZqHK8{tHF@9a=dtBOm0H&&le#jiP6D-sS%4r>qXL4a&h`j}uh zsmLc0kJZ;Ei7QN5&2IEUPm_7X*iZ}rNmW<_M1t^6U5jvj`G-~UEfu)t8;vpmL;*g* zdafn_W9DJBET0TNlOM+6^kYhM2ca3V)tT@mnU74MlXcFe*V)vO_(#TFZykSy*|mED~q!pkP%>HS!V6*h!F! zlk%;J!$^B%GxoSoK?tD6A^dnOSHytb=uj-$WQtUL-#D!B1bb_hwW{9&HH)DD_V z;OIp!t+2p7B0*#1d^MDnnT`${iK7M*gu1?oa&OW{vNOc})Q)$T>7#ldfqp^{xtqe8 zu!@?&Rvl2`OEsMO5OOWoM`*@=D$B@VcU%bFj?ESay`ku}Yuk9(#1&3*d`d?jv{$PK z=X+hzEq9}#dba5h9Jd~TWsC(`%39`~HhX0wwnP97S&er{hv40;bERXQg*7ao^RNBr zxGccbI>o{OwqBg9G}+5EygFLv5jvKdRAucylC89q*EtObyQA8?FVB!WZW1((9NPrN zSOujBRhKjsMN0Ze^e==Rs`IvxJnQ*l+MN>afMpSkZX58AXseZ*6 zGliX@_nU|AvP1N*JJQJooiKZ;KvFL~sYOA48fM?}sbZQQM8;ZrGHDs7&~&qQvgfr{ z{s%&$!cpMtdu&eRCNDwMB-{;P@Vc>H zq76nT?we2AY8)>0jhqzpnT6FP_T2J5UxLzJs#hi z39`cCo=`vbOLT(1Ygi3dQjXddF^aus{QYe4j(8 zQ{Eq}0UeTz(zXxU_9q3VQLvljz@v5c{kRf9hJ#pVhq3~ThFKkrf~o;Ig!>j5L^SK; zBGJrCHq>ESifg$?SDsp1YcR#H`-0nmZ+|YT7O%mQuNgG8S%xsIXjIj;(IHqMsR2T_ zMvgbYgj%x|BHxFMho4dP>p>zm+pKlrw4Jf{-|D=iPC%`ggYj8i_SQs_5s7?1T=u>K zvm*uL&p8l&gpN}ZYptyIb6gVzqX5xyuu+SgMZsW9YHW8AfE|^{3H?y=1Tx^2WcHDV6Dd#_0qX&UPDw(Uj(HJsc5O=g3C!>B63)) zukobf!%SoXvZhytBx$1RJU1j}C9-mt&uYs{xWbBweJA1zdUXLRvJnRx^o2V&J}1)9 zV}7;qHmaUpdj{@5|07_zCD$HE) z9_L>^66q2|*>d!<<5A2_UdzcEC(A@6CP(^%xVR4RBWCZypAVxxtYa;UshR$AAF^Ci zDax2iGgcT5H8KkzKLA$A?@m~=nui5A#|f~FAKW=kC5B0DK_xM>v&)AQ-%i|nK$OP{8I6U2;-Jg&{nbkY>Mn zSxb$j)-n}#2C{RIS}!AJ8a0TD`Dv4@80nP&=NTYhG|R95)E|AQ+akOM-Yv)N1LMcs+14HMo z1AgtxfYnq4(uK;*DnQ>#FPT;0-E?FCmODu-fc1DMk8on$#Y9+*5!=kuPd<~{1zcw3 zAm`?ebBxlY!Rgp`ULA!QJC2N65IJF2TWEqYh9$Jy)hv#^u?c1bYT+nI8(Xz~Q52 zFS{|*6Zs52a-+&5#vo-L9DpPTe&*%Ci$61@J+&~RQp?{|rath z)mQw63hu$kS_;DM$}MQn-S{{jb`yYir-JuD9^WpWDt|mQWqQf;b{+dprJ_O@};+^>64*||eB5Q{CDoZ69KO=`G5{ypT zL7z=>Wq@7D?4;$CxYDEx>ObEorbQ5drcJVvfdmbve4aC)7_*<=okbtaDOg=?VnUl^ z>=bt2)wfrRFa!r&a|Z6s-wJ&5t$-VNpLHPck;1bGZb=gK$O5(Ox8Y z=`ai!f)SaFLYlNHE-FFgZ=V3RcY^Tp`>Q_X=^5Z>zXtA2Uk+T;RXSOXSm{(_gRGy< z8^;3xDZ=%OI$x-sk$z@$Ff~?3z?1`i>Sb_0_L_16%5fiHyf>+HKwCpSf{7woS161l z$bvEKP}@Q#(yW=zR$Y z!HaBy0denV9yvOzvT~eIU}$Je8U!Tkkk@=kz~8SU|9{?HQ&89QqVgwjuX!Qxp4S6k z^>h^9S+zix6R=F}AVw<_BD`2GLGqa;vSBNbw`RtPfNQ6L-}ySY*MEVh@YM&lrGHnw zFFAwjCs*Xb2Rd&O#Q0a20}vd95D-LCY3JgZikI_hmQ|<^AMsSfTUkWq-AS2Li0N@s z^t0s306Q|OOCoDS=}GpSzCt4GCbg_ZG{z z89bCOj)2!Z4eoz^2i!|;0*U;RxT~kjaau^@!fRqZsRAwOU*7sPg;HlATolaybq68F z;n+gZpHK`sj1trZZ40^xf#K;1YpI9H?v8YVLJvS5H(DE5hcrpWodtZ-Nm07s>>P+T z>8jNHat$EZ1^|UXdcVfokbHX*4L~ofH7*0N^g&sd1jwPX$x8qLAOJ~3K~x;*``!wA zVgst`m!WylvEX|yg?r^^!Trzg0)GA#!1Xhz8l6;t!CjY?RdG4LMh77CF2N@FbYKi{ z%P^D!PniYY^c8S#`X)JIGFCxo1ymq2sY!ySu=|PkB$&7{Nq~B$^r3u*xe|Jm<6$(B z0s!+^_F(6P=uu^p30Bxc)N@(c%U^lWrv5f;um~0gh@f&0x@i~o`phUv#PQH2;Gg_g z(B)mBqVu_^G$a9h4(N8_zVUXrKlyIpr*8*tS}4t1sk2fu&|3n4(2@N`0gRvLVOa*| zr6}K1ZQuuA47~phaIbkTDB)wtrTNNvi=?f`?#%M1@Ymml9Y~1avXjyi4L~sIQZs?M zPM|KevBD~h{|1E%V(~@iP<)Y6%0Uj+h{ZF`vnCn!RF+uVKh)XSSmcu^&{006Hqvux zDFH|mIZG(lSZUL16p=l#0tb%+R>e2Mv&fTuz4<28tDVp*{2~GV@(JLdzZvKcN+_#L zIudC~qmMz4<`>|;^NWG^e-H2*Uk<$V4A4fEK50EswJyud^Bsv`M?s?|fx@l=alU63 zbj>vI<1YpN{CnYk=+$uZGpaPJJ16ezOUx{gQThhlP>T!`PQ|;0 z#^uD}ok1+*Lk|ci?^BB7fYl@cY`?_o(2r%GSSHK*>sd|eQG;Djft+-Y6^w2Ois5+Y zI-jci@H6Af^Bhi}m#3F{Fd#@q1Qc<;US)d7<~yc4Ki z32z@mk=kzRuoqEkB#9lJevl*858AemI^ARa2F1uC>MT!!I=#)yd*okz1eA_Yf*W8r z8kRirTmWovKAub`fq4LBjZ7GgkP_fmJ`Cz-z)yVzTq}h%^%&mdjte$wgPgk*?xyR3 zo2~=C`-?&MJqEn@6TqK80DR2et*{c%n_!Mp{f&_`O7#h@X~2%(9~PwV)aD} zGrP*Kt`?>Bn;X5uMC33}JUL0@cl`lfAz}w!0V9&La-#8=TeS>5$N|6h*T5hL{_n4ZYgP6r!ySomVJ@XHSl%ZI@bnvir(X~E z?K#lzfgU&q{Ou#aC)a>`&jSx`0QYSI+kK#y1DRxQDE2qC0Zg}n>*s){t^m(i0iJOh zc)<<8Q_leHHZ;2mHME&@RT3qDzwv#*fBAb9{c=<1)Wpm*qq3gMcdOsWu)3n}bvO-% z@{+>g;PN^TlO1#q_}$o}2A-1ybU>lcM8Hm-s&MF1)`|k`G^>lTuVJQ-adL`}Q^e~~ zXFIjZ4_}D`f3?N17CR~9lV2L+M{oKY(4{@NfBU-96ckB;L@ZAHAIp7_HX(s)PXW)k z0eHssqWuwE-UkL5Xm$#D*yCXJ_ox9#cUtn@#lX`FuieX>)xgc_Y|DJ} zIy(kBl?v6*g}7qD?Kt&5QA-t@wt)DF(Xt*U>9EQypSgzT%+8E)wV?9LMvl5!T9X)a zv1WA%wTX)uAb06-B?^D-Nea#j_F&i74 zBp?3DM*t4~O&Bdl`7Ma!TDNB%vIEZ_v!a%qKLHxBH z5E8@`csd1GK0aOiRwdAE0KnNj&{zK!@KbLC?e3vkXe=c(Ep_Z9Tq}kp`C)NajSNaZ zRSYih4If%+RDmt~wTx=OBs{?C9{{u10r?hz(xQu@*cVi8Zs-82`gcLIh5W!y_nS^Y__sn2tf z*A4_++ycG+O~8-57ub_yblS9(@5tK5CjG`l=CjE{Xkv%MBvxkfJ(it^_-?H35=w_$ zGP}dr)nt96;!{no2(Z&e34n6dd8`sfKq=@ir9Td@nVoD58u)}*$0T`mWH=2pmaZBA zb^c^r32?^-=*!*+`msL%)-C|Z5E_UQ0_7NAbyrEX6|G964!#ulhfk^ctr%YY%~fI9 zCw=5@;5EMj{QljjzY`fwuWz%=+`5)_`ZZWl_pwPU9X1A#8mz523V(8MEI*O8fB@=< zNX9+!qY1?H2Y5z}_euoC6AO0o1^FJ1am4AvJ9RG|tLVCc=oh9JBumkzRGkHdqQO>! zrA}YORr?gA3}fiC3*eVO0=(oGfM5J0V0*`NE19z@)heupr{Uml0k#e;8+=3K+1LX9 z<$nXd@(9amMar;L_CT=;y=C;uv@;6Qt&DFiN&ks0`r{e%r~W*CWee zYzdQFN>2*#4b$Vqf}IqnUo@fox>)(t|Hdkyl>H2S#8{nf95E1O{q)Ly9S2{=8l}ZR zMB`cC1AhE{z(4o}(67D^bYV-Gr!f<`Ug1M%*G$D07hKiH*}So~vjhB>_XGdn-vR&m z4q#w?fsD)C>SU~xo0wb7zxES5Dju-kt1gpa`dMiboJ)|CcuK`OJ2hr^G7v?{NtzKJ zrpt+4R4f(G9nPr_rx)Li1rRq!SVrlgW8*`*SN0ki?p8yP6};Z~>t>k66gA7xap?uI z0Pf!ce)x}ofAay**F6XLmX`oeyIRE)>R#(jYIj!HSSXwI(xq+SH$DXX$3F)i+CkL; z$c{v_IUT1=sR;li5Nj%OH)x6-oSaTDMQ|K+M;zqZbmnl!zXG378pY0~>%4@=k9 zBojC+MTx||z_L;#0kew%T^S&_)|J<4#JZyD${cGn+;9cZIkrjkcoU0egrwX#tei!b z`bs}aHhRD>eHi%Fj{u)@E%24M0bhIzaLr1iby;w*CQ#6MsE7B@`+eYV?gxJFuYkAS z1+48Uy=6XN8rz9040BcYC)$3Xv%L?SIq)r zi_J^_>O4CSa#VrdVT;xNn%cAWe-bccSiFa7#*TybP5yE!zz#sg?98KEtsXSSNF?G$qc9;Ad0IRSfpVDmC?|2g2^HQ?@Z!2f;__~_%nj?8~5vS68ln!V}r zu*yxBlMd5#c!M>o%a4sRYt$*m%B}YhiK85|lSPu{@GFV)BUoWKE`!q_yB`;%j)MvA z3+#?uQ3-a%eQCyOV3CbSS60jXi2Yh%5^Drari??hQF%6Lh2gkjtWBq@pXog4c*}bt zU@Hgy9o1nD+PJWWiwyrbwT-=` zfBI$g_W!nx0s6?1BY)^3_8z?%tNn+u`FCG}n;!Y8{Il+E8>a4&?pq&2jzgb)ft@}Y zdX&RI#}x^vRG#<{G==EWlNcCjU5t|`q9$BZ8dgIY#z?HN?B)t~A&*0^u_Bp{WLy$7 z^mR;sz1+qX;B~$aoVU)4)NHK$q-8D7S}&_Ctn!iot<%)k+ARiVR@zcxou-aoxcj8Y zh?c>yECVOg7I}9LINikqS6{~O&U_Sib{@t3=^8Q&!0RE4|7iwrU!yhtOFRYw;n(pu z`2FOri#OA6eRvA3kIbX;@%&eM-u2Qv=X(S@FhZ_lz-|AX$}`K7b&~{)Pd*^kZF1H;y}&M?H&bfiH`7 z+?KrNxGX)bve#@*1Ekd53e(hyX?Kx!@WCJ#!SFJS{IC!Km3f>4Qz?>HUWeA#KMPZz zcOyPDeGv)%s*IvIq0oUu4ytW?IY^aAF`0B8y9)$-A%HJ*z`uMDe|hm{`mJ}Zp!=3D z$Ib8fA@}Ty_%xRTfn5x+n#|mN_5xW@-HEr0H8p0VHwI9z#Ik|Lbc>Dg=rA#+!q23C zrF(70R)@C^Dv0^BSeylHO(3qBh}Lb`ZUzmMO=-&ADw>@&ooZsee-=42F2(BLw0?Xq z%8+#aL_AK0H-x=DWg4x2`Yd$5>Y122vyA$QHG<2*K`sg>@2aCN{OHRHhu-{KpMk~y@4vfO{e4`~$;e5YnPq}?D9mnHMy0TjpEmlf0rJx_Je`tDmX^UcpkyZr7( z6}+lXRKi~l0#P4Xe-Bx22h`sKQ3eo!vK&YgB<&88b{DSIL95k8;@XfRYw!*RbKBVZ zj>mE7TW+S`eBTXN_}S;-+V}jw?gb49y?=>KUg$P{RG`Rd9Lu8Oec1i-kd6Wtk{H-E zfel|<&$Ow?Vlj@ zyw|%Wq&pC%6$5tb9cw*AekD+uzd9P>?k6G`qx}w~*~_gL=g=@-9z{)1{LHek_*;pg|w#^?u*M)8k+n$KYG6%qSPO?^K*4|~oyrC^lvPQIv6a};3tcuAaOg2b>#$A@ znhtdn+Db>d$+%)>uS_d;FXJCp*47bUIvx?ui7@)RC&4T$Ge`p3DRBELxTn(~5_AacWw|O442e_n*q&tIjc^PT9g`}MVt)%#qW#a%x1fm>+d;seAK|4Fh zE?&am{)e&G`#9WO2kon_MrZjNwA=G=a6a7(z#6t+egS(Qc`p6-Z{9*@e)PAKFMP}> zjGCM@6LlPkf?ZRljyl7Ms}A6&^1noXNE1Mu5yZex`qj^4Ov+*k$l%Jn0wuG(VCj}aY`oF-@T0O^>fHB?;*i7(wS3et#;sM+DKX{ z;1bC5X!yD)DJp7CnPe;JAa4;cJ&%0lH1en3fGpcXzIg$?$Iqd6_q|9~=Fz$SGtim4 z3TZieP5=fNv>(F7Z$9U?zw~AF-~ajh+&}zH43UGZr#tRtFg36nMWMs|B9Rq;%i+OH z)y-?JzplI@ROX3V7qQ2*bQo-;V>*@)>_=mcTm$ zsH`O^+G!j4$}F;#GZ^GM$j&{1-A~+sy);4l#?Qd?;tfb#%WJoT!KshpiQl*_|E*WQ z7}tOAe@t%QunY5GGRe<3>?f{Th~q|IOFp_rS8Zi@7(kor-Te=p$LqiP8?beL4fV!g zF*q%;{EccpIdyLVN>iM}8f_ChvcgyZuN$+Ku63-{Fg^AwO>DWTocEKqW~Q46ui6^DO9*2jKv8o_Z^$X0GxO%ekLN=l)yis(MS2d+^IY^W(?{J>|QpaluoRnYR1(xre^8hWF}hDl%HY#jJQX6jplnK6f>x$doY_i3W#dvE#pPO z^c(@V%mQC@26*l=ra%8PF|)J`hAnTh?p?;EC)SYcwa}WKLb^JIq}zr=0&T3uw6l&b zU^tVkuT}=&56%|9IWqLIgTdD0zytRqnO(s2_0K`4Jul)Wq)4`3NLPRN+v&^RXzj|F zgd7JLUO8a*7`;4m_#^q9<}4$;?GN6MU;Blh!{*xKk&sr4X#%X6>D090UdLx0EFj%A zJB%&PwcM?I$TTS8CfQpIQ1z}7{fi-SX|YUKnU`T8uk$_v%kv9=o6>7w??iz7zDW>Y z8FnTCzUUP2xu<}q&tdv=Z^F#nqUU0~Ab5Lo1HJVvv}g+LQ`1NmrphH#Nl?m(0J`!6 zmt`#cr8uoM3C%* zv7gDm;9tM8b2y?*3#xDNigCE9yci)4xvujvi zJB#yc>)1Sh9^03;u(x{|S(YLA(DO*9QmkR~wSKO{$-dbd$Fux59YGXhqB>s7zs2mD z@^6`eO<-dIt2VD<)y)Dvoktm;wVQ+tH%l)o??5*DIw{#VP2?ffrb@nW1 zGe>uB8t&>DBuQ!lU8qexPnAmrR-unN&{exELZGA|bOC@Fa^&ctPZyD|-wn69i|HFb z2i?{jNOaKG(9-;_=;wDR}|O*z#l(A*9{!r+3Dap4)FDn0KZHvXg=kQ z*_=!N*#Owx8{p#RWt`tQkM*^6tUs}awY4>@pIyiLxiy?$U&s0NHC*1>#P0TG3PD&sSeT`RxrPEy*EMG@75Df0GmK(sbF-@rKr}p@m0Mv>^DgM zSy(E;8v9xp34!%4qzYMlnkfSzLl2iRxO^Y*#5r`Y{VYsPoepAoMz-?CukSzSJAPpL zwnJffM%#fMd>&-wRv+DvM8ovGev|p8-G@n&KMQPQ zY{~i_ZxdVNyja`Unt)L1A>&ecudQ!W;8fF*P>sXM^jraC&dQ5OlL)wR8u&k+0X%gU zSnj}`p2qy?r=nE?8AH3<+38TBzSdRf zA~|3eujl1w-uSQRW#9Jst<%TK@bsULxhK;jpICpLh8*6L0u)dCqo9D5+eF^>Eo`^hFmxi&hgSZcS)+EDB zP|en4xN&rnaZ1pVFH673ys8iZ^K+<)L_Yp4kpSo~9B@cA% z#bwNQPN4!WVE6JR^d7#5&de0j>t^ASg3%SFVSyc|M3J0_9fXE>340-EhCo=sDziZ< z`MeCz*Lk@-g)qP_`h$moNA5@a^lg})xz;nhHl@9r`=?(0!S2_-SC-l^usaEI@-%9Y z{TAX{PVU}Ean1c3Se)+QnqGz*kzlr+;#P8)>ZG_eBTRQ%cuG!Ka0$?ERe%`m{Wch* zCkIU=M#-ogiU8yp(Cg>8d}#-p7q)PIZ3AoPHVV^uZQcKFtgYkX`3-De+C;CnTb}3L zWERFWW6?`!Mlnr=DN7lGWgJ2Lq=F35&BD9r15)q6h+BeP5Jh>B5b%9Z1HSZHV4(#p zwBhDESm<6~Zn-KX&j#3f;4C_M7p9iz@&|E3MSuJoP_@MJ zaL@!#Qanwvu|v3f4c+@T(7I+BPdU4VYtj^_iSTrnV6M}`Ed!w2NpVXK%%lnC(*)fl z0n(B!dLVR>wySEX*?z~dKAFsvw|PeB_j7FT^s%*hsT@;0=O9QjSe-cF2PRZ;pMBq|8+C4*aqfX zz)Xti?kUW;1s^RD;nL&hkX~?T-8hS6rc;8P^USX3Zi;m3{UC||>-n+XhW^lGQSHJ5 z1{nInQek+Lv$bs0OHeF)WxN2ne;@GZA4r}OnTSV zByj_XfSu*xpoyKNcqSF+qub=}-@uvs)-X3ejq7&@xIRg-?0}oo7N*+?o}B^Rc8Z$` z|37Z%!RNeQSlS^b|EWh|YOFY5E8n8tOUePi|2%wlGF9t(A9&dj?k8+(xD3eO7 z1I6(E$Hz1F_m0@z-ibiiS)aEyHrd|TWOrwaqy6NTvj`BM^T{j*uje{<17ORYeorV? zW4;R>C6_6IS2TohmqYm%eQ?#){NTg z9-LqN>+hL-!?*Kkl0L1(*qfPNZnpTuzH)VoVt0nQxWWUU*ya3E$sM(FM`^i$@IX

    +
    +
    +
    +
    +

    {title}

    +
    {desc}
    +
    + {actions || + (onBack ? ( + + ) : ( + createElement( + linkElement, + { + to: redirect, + href: redirect, + }, + , + ) + ))} +
    +
    +
    + ); + } +} + +export default AobException; diff --git a/web/src/component/Banner/index.less b/web/src/component/Banner/index.less new file mode 100644 index 0000000..43a2c59 --- /dev/null +++ b/web/src/component/Banner/index.less @@ -0,0 +1,19 @@ +.directions { + position: relative; + padding-top: 48px; + .banner { + width: 100%; + height: 123px; + } + .title { + position: absolute; + top: 98px; + left: 144px; + height: 48px; + color: #fff; + font-weight: 500; + font-size: 28px; + line-height: 24px; + letter-spacing: 0; + } + } \ No newline at end of file diff --git a/web/src/component/Banner/index.tsx b/web/src/component/Banner/index.tsx new file mode 100644 index 0000000..e697a28 --- /dev/null +++ b/web/src/component/Banner/index.tsx @@ -0,0 +1,42 @@ +import { useRef, useEffect } from 'react'; + +import styles from './index.less'; +import bannerImg from '../../../public/assets/welcome/banner.png'; + +export default function Banner({title}:{title:string}) { + const bannerRef = useRef(null); + const welcomeTextRef = useRef(null); + const windowResize = () => { + welcomeTextRef.current!.style.top = + bannerRef.current?.clientHeight! / 2 + 36 + 'px'; + }; + + useEffect(() => { + window.addEventListener('resize', windowResize); + + //待图片加载完成获取高度 + if (bannerRef.current && welcomeTextRef.current) { + bannerRef.current.onload = function () { + welcomeTextRef.current!.style.top = + bannerRef.current?.clientHeight! / 2 + 36 + 'px'; + }; + } + + return () => { + window.removeEventListener('resize', windowResize); + }; + }, [bannerRef]); + return ( +
    + banner +
    + {title} +
    +
    + ); +} diff --git a/web/src/component/CheckBadge/index.less b/web/src/component/CheckBadge/index.less new file mode 100644 index 0000000..5ca8161 --- /dev/null +++ b/web/src/component/CheckBadge/index.less @@ -0,0 +1,63 @@ +@import '~@oceanbase/design/es/theme/index.less'; + +.processing { + color: @colorPrimary; +} +.success { + color: @colorSuccessTextHover; +} +.error { + color: @colorErrorText; +} +.ignored { + color: @colorTextTertiary; +} + +.rotate { + -webkit-animation: rotate 1s linear infinite; + animation: rotate 1s linear infinite; +} + +@keyframes rotate { + 0% { + transform: rotate(0); + } + + 25% { + transform: rotate(90deg); + } + + 50% { + transform: rotate(180deg); + } + + 75% { + transform: rotate(270deg); + } + + 100% { + transform: rotate(360deg); + } +} + +@-webkit-keyframes rotate { + 0% { + transform: rotate(0); + } + + 25% { + transform: rotate(90deg); + } + + 50% { + transform: rotate(180deg); + } + + 75% { + transform: rotate(270deg); + } + + 100% { + transform: rotate(360deg); + } +} diff --git a/web/src/component/CheckBadge/index.tsx b/web/src/component/CheckBadge/index.tsx new file mode 100644 index 0000000..b666218 --- /dev/null +++ b/web/src/component/CheckBadge/index.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import { Space } from '@oceanbase/design'; +import { + CloseCircleFilled, + CheckCircleFilled, + Loading3QuartersOutlined, + MinusCircleFilled, +} from '@ant-design/icons'; +import styles from './index.less'; + +export interface CheckBadgeProps { + className?: string; + status?: string; // 设置 Badge 为状态点 + text?: React.ReactNode; +} + +const CheckBadge = ({ status, text, className, ...restProps }: CheckBadgeProps) => { + const statusTextNode = !text ? <> : {text}; + let statusIcon: React.ReactNode | undefined = undefined; + if (status === 'processing') { + statusIcon = ; + } else if (status === 'success') { + statusIcon = ; + } else if (status === 'error') { + statusIcon = ; + } else if (status === 'ignored') { + statusIcon = ; + } + return ( + + {statusIcon} + {statusTextNode} + + ); +}; + +export default CheckBadge; diff --git a/web/src/component/ConnectConfig/index.less b/web/src/component/ConnectConfig/index.less new file mode 100644 index 0000000..fc76df0 --- /dev/null +++ b/web/src/component/ConnectConfig/index.less @@ -0,0 +1,5 @@ +.titleText{ + font-weight: 500; + font-size: 16px; + line-height: 24px; +} \ No newline at end of file diff --git a/web/src/component/ConnectConfig/index.tsx b/web/src/component/ConnectConfig/index.tsx new file mode 100644 index 0000000..00cfbe4 --- /dev/null +++ b/web/src/component/ConnectConfig/index.tsx @@ -0,0 +1,250 @@ +import { intl } from '@/utils/intl'; +import { ProForm, ProCard } from '@ant-design/pro-components'; +import { + Input, + Space, + Tooltip, + Button, + InputNumber, + message, + Modal, +} from 'antd'; +import { QuestionCircleOutlined, CloseCircleOutlined } from '@ant-design/icons'; +import { useRequest } from 'ahooks'; +import { useModel } from 'umi'; + +import * as Metadb from '@/services/ocp_installer_backend/Metadb'; +import CustomFooter from '../CustomFooter'; +import InputPort from '../InputPort'; +import ExitBtn from '../ExitBtn'; +import styles from './index.less'; +const InputWidthStyle = { width: 328 }; + +type FormValues = { + metadb: { + host: string; + port: number; + user: string; + password: string; + }; +}; + +export default function ConnectConfig({ setCurrent, current }: API.StepProp) { + const { ocpConfigData, setOcpConfigData, setErrorVisible, setErrorsList } = + useModel('global'); + const { components = {} } = ocpConfigData; + const { ocpserver = {}, oceanbase = {} } = components; + const { metadb = {} } = ocpserver; + const cluster_name = oceanbase?.appname; + const { host, port, user, password } = metadb; + const [form] = ProForm.useForm(); + const setData = (dataSource: FormValues) => { + let newOcpserver = { + ...ocpserver, + ...dataSource, + }; + setOcpConfigData({ + ...ocpConfigData, + components: { + ...components, + ocpserver: newOcpserver, + }, + }); + }; + // 通过 connection 方式创建一个 metadb 连接 + const { run: createMetadbConnection, loading } = useRequest( + Metadb.createMetadbConnection, + { + manual: true, + onError: ({ data }: any) => { + const errorInfo = + data?.detail?.msg || (data?.detail[0] && data?.detail[0]?.msg); + Modal.error({ + title: intl.formatMessage({ + id: 'OBD.component.ConnectConfig.MetadbConnectionFailedPleaseCheck', + defaultMessage: 'MetaDB 连接失败,请检查连接配置', + }), + icon: , + content: errorInfo, + okText: intl.formatMessage({ + id: 'OBD.component.ConnectConfig.IKnow', + defaultMessage: '我知道了', + }), + }); + }, + }, + ); + + const nextStep = () => { + form + .validateFields() + .then((values) => { + const { host, port, user, password } = values.metadb; + createMetadbConnection( + { sys: true }, + { + host, + port, + user, + password, + cluster_name, + }, + ).then(() => { + setData(values); + setCurrent(current + 1); + setErrorVisible(false); + setErrorsList([]); + window.scrollTo(0, 0); + }); + }) + .catch(({ errorFields }) => { + const errorName = errorFields?.[0].name; + form.scrollToField(errorName); + message.destroy(); + }); + }; + const prevStep = () => { + setCurrent(current - 1); + }; + const initialValues: FormValues = { + metadb: { + host: host || undefined, + port: port || undefined, + user: user || 'root@sys', + password: password || undefined, + }, + }; + return ( + + +

    + {intl.formatMessage({ + id: 'OBD.component.ConnectConfig.ConnectionInformation', + defaultMessage: '连接信息', + })} +

    + + + + + + + + + + {intl.formatMessage({ + id: 'OBD.component.ConnectConfig.AccessPassword', + defaultMessage: '访问密码', + })} + + + + + + } + name={['metadb', 'password']} + rules={[ + { + required: true, + message: intl.formatMessage({ + id: 'OBD.component.ConnectConfig.EnterAnAccessPassword', + defaultMessage: '请输入访问密码', + }), + }, + ]} + style={InputWidthStyle} + > + + + +
    + + + + + +
    + ); +} diff --git a/web/src/component/ContentWithIcon/index.less b/web/src/component/ContentWithIcon/index.less new file mode 100644 index 0000000..f7bbf0b --- /dev/null +++ b/web/src/component/ContentWithIcon/index.less @@ -0,0 +1,26 @@ +.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/web/src/component/ContentWithIcon/index.tsx b/web/src/component/ContentWithIcon/index.tsx new file mode 100644 index 0000000..fa9551c --- /dev/null +++ b/web/src/component/ContentWithIcon/index.tsx @@ -0,0 +1,81 @@ +import { Badge, Tooltip } from '@oceanbase/design'; +import React, { isValidElement } from 'react'; +import classNames from 'classnames'; +import Icon from '@ant-design/icons'; +import type { IconComponentProps } from '@ant-design/icons/lib/components/Icon'; +import type { BadgeProps } from 'antd/es/badge'; +import type { TooltipProps } from 'antd/es/tooltip'; +import styles from './index.less'; + +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 +}) => { + 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; + return ( + config && ( + + {badge ? ( + + + + ) : ( + + + + )} + + ) + ); +} + +export default ContentWithIcon; diff --git a/web/src/component/ContentWithInfo/index.less b/web/src/component/ContentWithInfo/index.less new file mode 100644 index 0000000..590803b --- /dev/null +++ b/web/src/component/ContentWithInfo/index.less @@ -0,0 +1,16 @@ +@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/web/src/component/ContentWithInfo/index.tsx b/web/src/component/ContentWithInfo/index.tsx new file mode 100644 index 0000000..0702608 --- /dev/null +++ b/web/src/component/ContentWithInfo/index.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import type { SpaceProps } from '@oceanbase/design'; +import { Space } from '@oceanbase/design'; +import { InfoCircleFilled } from '@ant-design/icons'; +import styles from './index.less'; + +export interface ContentWithInfoProps extends SpaceProps { + content: React.ReactNode; + className?: string; + style?: React.CSSProperties; +} + +const ContentWithInfo: React.FC = ({ content, className, ...restProps }) => ( + + + {content} + +); + +export default ContentWithInfo; diff --git a/web/src/component/ContentWithQuestion/index.tsx b/web/src/component/ContentWithQuestion/index.tsx new file mode 100644 index 0000000..d441411 --- /dev/null +++ b/web/src/component/ContentWithQuestion/index.tsx @@ -0,0 +1,45 @@ +import React from 'react'; +import { useToken } from '@oceanbase/design'; +import type { TooltipProps } from 'antd/es/tooltip'; +import { QuestionCircleOutlined } from '@ant-design/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 } = useToken(); + return ( + + ); +}; + +export default ContentWithQuestion; diff --git a/web/src/component/CustomFooter/index.less b/web/src/component/CustomFooter/index.less new file mode 100644 index 0000000..3ba2e8b --- /dev/null +++ b/web/src/component/CustomFooter/index.less @@ -0,0 +1,18 @@ +.pageFooterContainer { + position: fixed; + right: 0; + bottom: 0; + left: 0; + z-index: 99; + padding: 16px; + background-color: #f5f8ff; + border-top: 1px solid #dde4ed; + .pageFooter { + width: 1040px; + margin: 0 auto; + overflow: hidden; + .foolterAction { + float: right; + } + } +} diff --git a/web/src/component/CustomFooter/index.tsx b/web/src/component/CustomFooter/index.tsx new file mode 100644 index 0000000..af234ba --- /dev/null +++ b/web/src/component/CustomFooter/index.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { Space } from 'antd'; +import styles from './index.less'; + +export default function CustomFooter( + props: React.PropsWithChildren, +) { + return ( +
    +
    + {props.children} +
    +
    + ); +} diff --git a/web/src/component/CustomPasswordInput/index.tsx b/web/src/component/CustomPasswordInput/index.tsx new file mode 100644 index 0000000..aa2881a --- /dev/null +++ b/web/src/component/CustomPasswordInput/index.tsx @@ -0,0 +1,177 @@ +import { intl } from '@/utils/intl'; +import { ProForm } from '@ant-design/pro-components'; +import { Input, Button, message } from 'antd'; +import { FormInstance } from 'antd/lib/form'; +import { NamePath } from 'rc-field-form/lib/interface'; +import { generateRandomPassword } from '@/utils'; +import { copyText } from '@/utils/helper'; + +interface CustomPasswordInputProps { + onChange: (value: string) => void; + value: string; + label: React.ReactNode; + name: NamePath | undefined; + showCopyBtn?: boolean; + form: FormInstance; + msgInfo: MsgInfoType; + setMsgInfo: React.Dispatch>; +} + +type MsgInfoType = { + validateStatus: 'success' | 'error'; + errorMsg: string | null; +}; +const passwordReg = + /^(?=.*[A-Z].*[A-Z])(?=.*[a-z].*[a-z])(?=.*\d.*\d)(?=.*[~!@#%^&*_\-+=`|(){}[\]:;',.?/].*[~!@#%^&*_\-+=`|(){}[\]:;',.?/])[A-Za-z\d~!@#%^&*_\-+=`|(){}[\]:;',.?/]{8,32}$/; +export default function CustomPasswordInput({ + onChange, + value, + showCopyBtn = false, + form, + name, + msgInfo, + setMsgInfo, + ...props +}: CustomPasswordInputProps) { + const textStyle = { marginTop: '8px' }; + const validateInput = (value: string): MsgInfoType => { + const regex = /^[A-Za-z\d~!@#%^&*_\-+=`|(){}[\]:;',.?/]*$/; + if (value.length < 8 || value.length > 32) { + return { + validateStatus: 'error', + errorMsg: intl.formatMessage({ + id: 'OBD.component.CustomPasswordInput.TheLengthShouldBeTo', + defaultMessage: '长度应为 8~32 个字符', + }), + }; + } else if (!regex.test(value)) { + return { + validateStatus: 'error', + errorMsg: intl.formatMessage({ + id: 'OBD.component.CustomPasswordInput.CanOnlyContainLettersNumbers', + defaultMessage: + "只能包含字母、数字和特殊字符~!@#%^&*_-+=`|(){}[]:;',.?/", + }), + }; + } else if (!passwordReg.test(value)) { + return { + validateStatus: 'error', + errorMsg: intl.formatMessage({ + id: 'OBD.component.CustomPasswordInput.AtLeastUppercaseAndLowercase', + defaultMessage: '大小写字母、数字和特殊字符都至少包含 2 个', + }), + }; + } + return { + validateStatus: 'success', + errorMsg: null, + }; + }; + const handleChange = (value: string) => { + setMsgInfo(validateInput(value)); + onChange(value); + }; + + const handleRandomGenerate = () => { + const password = generateRandomPassword(); + setMsgInfo(validateInput(password)); + onChange(password); + }; + const passwordCopy = () => { + if (value) { + if (copyText(value)) { + message.success( + intl.formatMessage({ + id: 'OBD.component.CustomPasswordInput.CopiedSuccessfully', + defaultMessage: '复制成功', + }), + ); + } else { + message.warning( + intl.formatMessage({ + id: 'OBD.component.CustomPasswordInput.TheCurrentBrowserDoesNot', + defaultMessage: '当前浏览器不支持文本复制', + }), + ); + } + } + }; + const Help = () => { + if (showCopyBtn) { + return ( +

    + {intl.formatMessage({ + id: 'OBD.component.CustomPasswordInput.KeepThePasswordInMind', + defaultMessage: '请牢记密码,也可复制密码并妥善保存', + })} +

    + ); + } + return ( +
    + ); + }; + + return ( + {msgInfo?.errorMsg}

    + ) : ( + + ) + } + rules={[ + { + required: true, + message: intl.formatMessage({ + id: 'OBD.component.CustomPasswordInput.EnterAPassword', + defaultMessage: '请输入密码', + }), + }, + ]} + name={name} + {...props} + > +
    + handleChange(e.target.value)} + value={value} + style={{ width: 328 }} + /> + + + {showCopyBtn && ( + + )} +
    +
    + ); +} diff --git a/web/src/component/DeployConfig/constants.ts b/web/src/component/DeployConfig/constants.ts new file mode 100644 index 0000000..dee126d --- /dev/null +++ b/web/src/component/DeployConfig/constants.ts @@ -0,0 +1,82 @@ +import { intl } from '@/utils/intl'; + +export type VersionInfoType = { + version: string; + md5: string; + release: string; + versionType: string; + value?: string; +}; + +export type TableDataType = { + name: string; + versionInfo: VersionInfoType[]; + componentInfo: ComponentMetaType; + key:string +}; + +export type ClusterNameType = { + label: string; + value: string; +}; + +export type ComponentMetaType = { name: string; desc: string; url: string ,key:string}; + +export const OCEANBASE = 'oceanbase'; +export const OBPROXY = 'obproxy'; +export const OCP = 'ocp-server'; +export const OCEANBASE_META:ComponentMetaType = { + key:OCEANBASE, + name:'OceanBase', + desc: intl.formatMessage({ + id: 'OBD.component.DeployConfig.FinancialLevelDistributedDatabasesAre', + defaultMessage: + '金融级分布式数据库,具备数据强一致,高扩展、高性价比稳定可靠等特征', + }), + url: 'https://www.oceanbase.com/docs/oceanbase-database-cn', +} + +export const OCP_META:ComponentMetaType = { + key:OCP, + name:'OCP', + desc: intl.formatMessage({ + id: 'OBD.component.DeployConfig.EnterpriseLevelDataManagementPlatform', + defaultMessage: + '以 OceanBase 为核心的企业级数据管理平台,实现 OceanBase 全生命周期运维管理', + }), + url: 'https://www.oceanbase.com/docs/common-oceanbase-database-cn-10000000001577895', +} + +export const OBPROXY_META:ComponentMetaType = { + key:OBPROXY, + name:'OBProxy', + desc: intl.formatMessage({ + id: 'OBD.component.DeployConfig.OceanbaseADedicatedDatabaseProxy', + defaultMessage: + 'OceanBase 数据库专用代理服务器,可将用户的 SQL 请求转发至最佳目标 OBServer', + }), + url: 'https://www.oceanbase.com/docs/odp-doc-cn', +} +export const CompoentsInfo:ComponentMetaType[] = [OCP_META,OCEANBASE_META,OBPROXY_META] + + +export const OCPComponent:TableDataType = { + key:OCP, + name:'OCP', + versionInfo:[], + componentInfo:OCP_META, +} + +export const OBComponent:TableDataType = { + key:OCEANBASE, + name:'OceanBase', + versionInfo:[], + componentInfo:OCEANBASE_META, +} + +export const OBProxyComponent:TableDataType = { + key:OBPROXY, + name:'OBProxy', + versionInfo:[], + componentInfo:OBPROXY_META, +} \ No newline at end of file diff --git a/web/src/component/DeployConfig/index.less b/web/src/component/DeployConfig/index.less new file mode 100644 index 0000000..e69de29 diff --git a/web/src/component/DeployConfig/index.tsx b/web/src/component/DeployConfig/index.tsx new file mode 100644 index 0000000..56fa8e9 --- /dev/null +++ b/web/src/component/DeployConfig/index.tsx @@ -0,0 +1,1039 @@ +import { commonStyle, STABLE_OCP_VERSION } from '@/pages/constants'; +import { queryAllComponentVersions } from '@/services/ob-deploy-web/Components'; +import { + getClusterNames, + getConnectInfo, +} from '@/services/ocp_installer_backend/OCP'; +import { + clusterNameReg, + errorHandler, + getErrorInfo, + updateClusterNameReg, +} from '@/utils'; +import copy from 'copy-to-clipboard'; +import { getTailPath } from '@/utils/helper'; +import { intl } from '@/utils/intl'; +import customRequest from '@/utils/useRequest'; +import { InfoCircleOutlined, CopyOutlined } from '@ant-design/icons'; +import { ProCard, ProForm, ProFormText } from '@ant-design/pro-components'; +import { useRequest, useUpdateEffect } from 'ahooks'; +import { + Button, + Select, + Space, + Spin, + Table, + Tag, + Tooltip, + Alert, + message, +} from 'antd'; +import type { ColumnsType } from 'antd/es/table'; +import { FormInstance } from 'antd/lib/form'; +import NP from 'number-precision'; +import { useEffect, useRef, useState } from 'react'; +import { getLocale, history, useModel } from 'umi'; +import EnStyles from '../../pages/Obdeploy/indexEn.less'; +import ZhStyles from '../../pages/Obdeploy/indexZh.less'; +import CustomFooter from '../CustomFooter'; +import ErrorCompToolTip from '../ErrorCompToolTip'; +import { listRemoteMirrors } from '@/services/ob-deploy-web/Mirror'; +import ExitBtn from '../ExitBtn'; +import type { + ClusterNameType, + TableDataType, + VersionInfoType, +} from './constants'; +import { + CompoentsInfo, + OBComponent, + OBPROXY, + OBProxyComponent, + OCEANBASE, + OCP, + OCPComponent, +} from './constants'; + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; + +export default function DeployConfig({ + setCurrent, + current, + connectForm, + clearConnection, +}: API.StepProp & { + connectForm?: FormInstance; + clearConnection?: () => void; +}) { + const { + getInfoByName, + setErrorVisible, + errorsList, + setErrorsList, + setOcpNewFirstTime, + ocpConfigData, + setOcpConfigData, + selectCluster, + setSelectCluster, + } = useModel('global'); + const { + obVersionInfo, + setObVersionInfo, + ocpVersionInfo, + setOcpVersionInfo, + obproxyVersionInfo, + setObproxyVersionInfo, + deployMemory, + setDeployMemory, + tableData, + setTableData, + } = useModel('ocpInstallData'); + const [componentLoading, setComponentLoading] = useState(false); + const taiPath = getTailPath(); + const isUpdate = taiPath === 'update'; + const isNewDB = taiPath === 'install'; + const [form] = ProForm.useForm(); + const checkRegInfo = { + reg: isUpdate ? updateClusterNameReg : clusterNameReg, + msg: isUpdate + ? intl.formatMessage({ + id: 'OBD.component.DeployConfig.ItStartsWithALetter.1', + defaultMessage: + '以英文字母开头、英文或数字结尾,可包含英文、数字、连字符和下划线,且长度为 2 ~ 32', + }) + : intl.formatMessage({ + id: 'OBD.component.DeployConfig.ItStartsWithALetter', + defaultMessage: + '以英文字母开头、英文或数字结尾,可包含英文、数字和下划线,且长度为 2 ~ 32', + }), + }; + const { components = {} } = ocpConfigData || {}; + const { oceanbase = {} } = components || {}; + const [clusterOption, setClusterOption] = useState([]); + const selectClusetNameRef = useRef(); + const searchTextRef = useRef(); + const [existNoVersion, setExistNoVersion] = useState(false); + const wholeComponents = useRef([]); + const [unavailableList, setUnavailableList] = useState([]); + //查询version的前两位和type相匹配的obproxyInfo + const findObproxy = (version: string, type: 'ce' | 'business') => { + const obproxyVersionInfo = tableData?.find( + (item: TableDataType) => item.key === OBPROXY, + )?.versionInfo; + const target = obproxyVersionInfo?.find( + (item: VersionInfoType) => + // 类型以及版本号前两位相同 + item.versionType === type && + version[0] === item.version[0] && + version[2] === item.version[2], + ); + return target; + }; + + const onVersionChange = (versionInfo: any, record: any) => { + const _version = versionInfo.value; + const [version, release, md5] = _version.split('-'); + const versionType = record.versionInfo.find( + (item: VersionInfoType) => + item.version === version && + item.md5 === md5 && + item.release === release, + ).versionType; + let target; + if (record.key === OCEANBASE) { + if (obVersionInfo?.versionType !== versionType) { + target = findObproxy(_version, versionType); + } else if ( + obVersionInfo?.version[0] !== _version[0] || + obVersionInfo?.version[2] !== _version[2] + ) { + target = findObproxy(_version, versionType); + } + if (target) { + target.value = `${target.version}-${target.release}`; + setObproxyVersionInfo(target); + } + setObVersionInfo({ + version, + release, + md5, + versionType, + value: _version, + }); + } + if (record.key === OCP) { + setOcpVersionInfo({ + version, + release, + md5, + versionType, + value: _version, + }); + } + }; + const getColumns = () => { + const columns: ColumnsType = [ + { + title: intl.formatMessage({ + id: 'OBD.component.DeployConfig.ProductName', + defaultMessage: '产品名称', + }), + dataIndex: 'name', + width: locale === 'zh-CN' ? 134 : 140, + render: (name, record) => { + return ( + <> + {name} + {!record.versionInfo.length && ( + + )} + + ); + }, + }, + { + title: intl.formatMessage({ + id: 'OBD.component.DeployConfig.Version', + defaultMessage: '版本', + }), + dataIndex: 'versionInfo', + width: 220, + render: (_, record) => { + let selectVersion = + record.key === OCEANBASE + ? obVersionInfo + : record.key === OBPROXY + ? obproxyVersionInfo + : ocpVersionInfo; + + if (selectVersion) { + selectVersion.valueInfo = { + value: selectVersion?.value, + label: ( +
    +
    + V {selectVersion?.version} + {selectVersion?.release ? `-${selectVersion?.release}` : ''} +
    + {selectVersion?.versionType === 'ce' ? ( + + {intl.formatMessage({ + id: 'OBD.component.DeployConfig.CommunityEdition', + defaultMessage: '社区版', + })} + + ) : ( + + {intl.formatMessage({ + id: 'OBD.component.DeployConfig.CommercialEdition', + defaultMessage: '商业版', + })} + + )} +
    + ), + }; + } else { + selectVersion = {}; + } + return ( + // 版本联动 ocp是社区版,ob也得是社区版,obproxy不支持选择并且版本号与ob前两位一致 + + {record.key === OBPROXY ? ( + // 用div包裹可以使Tooltip生效 +
    + onVersionChange(value, record)} + style={{ width: 207 }} + > + {_.map((item: any) => ( + +
    +
    + V {item.version} + {item?.release ? `-${item?.release}` : ''} +
    + {item.versionType === 'ce' ? ( + + {intl.formatMessage({ + id: 'OBD.component.DeployConfig.CommunityEdition', + defaultMessage: '社区版', + })} + + ) : ( + + {intl.formatMessage({ + id: 'OBD.component.DeployConfig.CommercialEdition', + defaultMessage: '商业版', + })} + + )} +
    +
    + ))} + + )} + + ); + }, + }, + { + title: intl.formatMessage({ + id: 'OBD.component.DeployConfig.Description', + defaultMessage: '描述', + }), + dataIndex: 'componentInfo', + render: (_, record) => ( + <> + {record.componentInfo.desc || '-'} + + {intl.formatMessage({ + id: 'OBD.component.DeployConfig.LearnMore', + defaultMessage: '了解更多', + })} + + + ), + }, + ]; + + return columns; + }; + const nameValidator = async (_: any, value: string) => { + if (value) { + if (!checkRegInfo.reg.test(value)) { + return Promise.reject(new Error(checkRegInfo.msg)); + } + if (!isUpdate) { + try { + const { success, data } = await getInfoByName({ name: value }); + if (success) { + if (['CONFIGURED', 'DESTROYED'].includes(data?.status)) { + return Promise.resolve(); + } + return Promise.reject( + new Error( + intl.formatMessage( + { + id: 'OBD.component.DeployConfig.ADeploymentNameWithValue', + defaultMessage: '已存在为 {value} 的部署名称,请指定新名称', + }, + { value: value }, + ), + ), + ); + } + return Promise.resolve(); + } catch ({ response, data, type }: any) { + if (response?.status === 404) { + if (isUpdate) { + return Promise.reject( + new Error( + intl.formatMessage( + { + id: 'OBD.component.DeployConfig.TheDeploymentNameWithValue', + defaultMessage: '不存在为 {value} 的部署名称', + }, + { value: value }, + ), + ), + ); + } + return Promise.resolve(); + } else { + const errorInfo = getErrorInfo({ response, data, type }); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + } + } + } + } + }; + + const caculateSize = (originSize: number): number => { + return Number(NP.divide(NP.divide(originSize, 1024), 1024).toFixed(2)); + }; + const getVersion = (name: string, info?: any[]) => { + if (!info) return []; + return info.map((item) => ({ + versionType: item.version_type, + version: item.version, + release: item.release, + md5: item.md5, + })); + }; + + const getRecommendInfo = (data: any) => { + if (data.key === OCP) { + let stableVersionArr = data.info.filter((item: any) => { + const versionArr = item.version.split('.'); + return ( + versionArr[0] === STABLE_OCP_VERSION[0] && + versionArr[1] === STABLE_OCP_VERSION[1] && + versionArr[2] === STABLE_OCP_VERSION[2] + ); + }); + const temp = stableVersionArr.map((item: any) => + Number(item?.release?.split('.')[0]), + ); + if (temp && temp.length >= 2) { + const maxRelease = temp.sort( + (pre: number, next: number) => next - pre, + )[0]; + return stableVersionArr.find( + (stableVersion: any) => + Number(stableVersion?.release?.split('.')[0]) === maxRelease, + ); + } else { + return data.info[0]; + } + } + return data.info[0]; + }; + + const judgVersions = (length: number) => { + if (length !== wholeComponents.current.length) { + setExistNoVersion(true); + } else { + setExistNoVersion(false); + } + }; + + //初始值 最新版本 + const setInitVersion = (data: any) => { + let versionInfo = getRecommendInfo(data); + let detail = { + version: versionInfo.version, + release: versionInfo.release, + md5: versionInfo.md5, + versionType: versionInfo.version_type || 'business', + value: `${versionInfo.version}-${versionInfo.release}`, + }; + if (data.name === OCEANBASE) { + setObVersionInfo(detail); + } + if (data.name === OCP) { + setOcpVersionInfo(detail); + } + if (data.name === OBPROXY) { + setObproxyVersionInfo(detail); + } + }; + + const { run: getClusterList } = useRequest(getClusterNames, { + manual: true, + onSuccess: (res) => { + if (res.success) { + let clusterNames = res.data?.name.map((val: string) => ({ + label: val, + value: val, + })); + setClusterOption(clusterNames || []); + } + }, + }); + + //获取连接信息默认值 + const { run: getConnectInfoReq } = useRequest(getConnectInfo, { + manual: true, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }); + + const prevStep = () => { + setOcpConfigData({}); + setErrorVisible(false); + setErrorsList([]); + setObVersionInfo(undefined); + setOcpVersionInfo(undefined); + setObproxyVersionInfo(undefined); + setTableData(undefined); + if (isUpdate) { + history.push('/updateWelcome'); + } else { + history.push('/ocpInstaller'); + } + }; + + const formateConnectData = (data: API.ConnectInfo) => { + return { + host: data.host, + port: data.port, + database: data.database, + accessUser: data.user || 'ocp@ocp_meta', + accessCode: data.password, + }; + }; + + const changeClusterName = (newName: string): boolean => { + let oldName = ocpConfigData?.components?.oceanbase?.appname; + return oldName !== newName; + }; + + const nextStep = () => { + if (form.getFieldsError(['appname'])[0].errors.length) return; + form.validateFields().then(async (values) => { + let newComponents: API.Components, newOcpConfigData: any; + if (!isNewDB) { + newComponents = { + oceanbase: { + appname: values?.appname, + }, + ocpserver: { + ...(components?.ocpserver || {}), + component: + ocpVersionInfo?.versionType === 'ce' + ? 'ocp-server-ce' + : 'ocp-server', + version: ocpVersionInfo?.version, + release: ocpVersionInfo?.release, + package_hash: ocpVersionInfo?.md5, + }, + }; + } else { + newComponents = { + oceanbase: { + ...(components?.oceanbase || {}), + component: + obVersionInfo?.versionType === 'ce' ? 'oceanbase-ce' : OCEANBASE, + appname: values?.appname, + version: obVersionInfo?.version, + release: obVersionInfo?.release, + package_hash: obVersionInfo?.md5, + }, + obproxy: { + ...(components?.obproxy || {}), + component: + obproxyVersionInfo?.versionType === 'ce' ? 'obproxy-ce' : OBPROXY, + version: obproxyVersionInfo?.version, + release: obproxyVersionInfo?.release, + package_hash: obproxyVersionInfo?.md5, + }, + ocpserver: { + ...(components?.ocpserver || {}), + component: + ocpVersionInfo?.versionType === 'ce' + ? 'ocp-server-ce' + : 'ocp-server', + version: ocpVersionInfo?.version, + release: ocpVersionInfo?.release, + package_hash: ocpVersionInfo?.md5, + }, + }; + } + newOcpConfigData = { + ...ocpConfigData, + components: newComponents, + }; + if (isUpdate && changeClusterName(values?.appname)) { + try { + const { success, data } = await getConnectInfoReq({ + name: values?.appname, + }); + if (success && data) { + //首次进入 设置初始值 + if (!ocpConfigData.updateConnectInfo) { + newOcpConfigData.updateConnectInfo = + formateConnectData(data) || {}; + } else { + //重置状态 + clearConnection && clearConnection(); + connectForm?.setFieldsValue({ + ...formateConnectData(data), + }); + } + } + } catch (err) {} + } + + setOcpConfigData({ ...newOcpConfigData }); + setCurrent(current + 1); + setOcpNewFirstTime(false); + setErrorVisible(false); + setErrorsList([]); + }); + }; + + const oparete = (item: any, dataSource: any, memory: number) => { + const component = CompoentsInfo.find( + (compoentInfo) => compoentInfo.key === item.name, + ); + let temp: TableDataType = { + name: component?.name!, + versionInfo: getVersion(item.name, item.info), + componentInfo: component!, + key: component?.key!, + }; + setInitVersion(item); + memory += caculateSize(getRecommendInfo(item).estimated_size); + dataSource.push(temp); + return memory; + }; + + const sortComponent = (dataSource: any[]) => { + let OCPComp = dataSource.find((comp) => comp.key === OCP); + let OBComp = dataSource.find((comp) => comp.key === OCEANBASE); + let ProxyComp = dataSource.find((comp) => comp.key === OBPROXY); + dataSource[0] = OCPComp; + dataSource[1] = OBComp; + dataSource[2] = ProxyComp; + }; + + const completionComponent = (dataSource: any[]) => { + for (let component of wholeComponents.current) { + if (!dataSource.find((item) => item.name === component.name)) { + dataSource.push(component); + } + } + }; + + const { run: fetchListRemoteMirrors } = useRequest(listRemoteMirrors, { + onSuccess: () => { + setComponentLoading(false); + }, + onError: ({ response, data, type }: any) => { + if (response?.status === 503) { + setTimeout(() => { + fetchListRemoteMirrors(); + }, 1000); + } else { + const errorInfo = getErrorInfo({ response, data, type }); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + setComponentLoading(false); + } + }, + }); + + const { run: fetchAllComponentVersions, loading: versionLoading } = + customRequest(queryAllComponentVersions, { + onSuccess: async ({ + success, + data, + }: API.OBResponseDataListComponent_) => { + if (success && data?.items) { + let dataSource: any[] = [], + memory = 0; + for (let item of data?.items) { + if (!isNewDB) { + wholeComponents.current = [OCPComponent]; + if (item.name === OCP) { + if (item.info?.length) { + memory = oparete(item, dataSource, memory); + } + } + } else { + wholeComponents.current = [ + OCPComponent, + OBComponent, + OBProxyComponent, + ]; + + if ( + item.name === OCP || + item.name === OCEANBASE || + item.name === OBPROXY + ) { + if (item.info?.length) { + memory = oparete(item, dataSource, memory); + } + } + } + } + + //需判断是否区分部署有无metadb 升级wholeComponents + const noVersion = + dataSource.length !== wholeComponents.current.length; + judgVersions(dataSource.length); + + if (noVersion) { + const { success: mirrorSuccess, data: mirrorData } = + await fetchListRemoteMirrors(); + if (mirrorSuccess) { + const nameList: string[] = []; + if (mirrorData?.total < 2) { + const mirrorName = mirrorData?.items?.map( + (item: API.Mirror) => item.section_name, + ); + + const noDataName = [...mirrorName, ...mirrors].filter( + (name) => + mirrors.includes(name) && !mirrorName.includes(name), + ); + + noDataName.forEach((name) => { + nameList.push(name); + }); + } + if (mirrorData?.total) { + mirrorData?.items?.forEach((item: API.Mirror) => { + if (!item.available) { + nameList.push(item.section_name); + } + }); + } + setUnavailableList(nameList); + } + } else { + setComponentLoading(false); + } + + completionComponent(dataSource); + isNewDB && sortComponent(dataSource); + setDeployMemory(memory); + setTableData(dataSource); + setComponentLoading(false); + } + }, + onError: ({ response, data, type }: any) => { + if (response?.status === 503) { + setTimeout(() => { + fetchAllComponentVersions(); + }, 1000); + } else { + const errorInfo = getErrorInfo({ response, data, type }); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + setComponentLoading(false); + } + }, + }); + + useEffect(() => { + getClusterList(); + if (!obVersionInfo || !obproxyVersionInfo || !ocpVersionInfo) { + setComponentLoading(true); + fetchAllComponentVersions(); + } + }, []); + const handleChangeCluster = (val: string) => { + setSelectCluster(val); + form.setFieldValue('appname', val); + }; + + const handleSearchCluster = (val: string) => { + if (val) { + searchTextRef.current = val; + } + }; + + const handleChangeSearchText = () => { + const select = clusterOption.find((option) => { + return option.value === searchTextRef.current; + }); + if (!select && searchTextRef.current) { + setClusterOption([ + { value: searchTextRef.current, label: searchTextRef.current }, + ...clusterOption, + ]); + } + }; + + const handleCopy = (content: string) => { + copy(content); + message.success( + intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.CopiedSuccessfully', + defaultMessage: '复制成功', + }), + ); + }; + + const clusterNameRules = [ + { + required: true, + message: intl.formatMessage({ + id: 'OBD.component.DeployConfig.EnterAClusterName', + defaultMessage: '请输入集群名称', + }), + validateTrigger: 'onChange', + }, + { + pattern: checkRegInfo.reg, + message: checkRegInfo.msg, + + validateTrigger: 'onChange', + }, + { validator: nameValidator, validateTrigger: 'onBlur' }, + ]; + + const cluserNameProps = { + name: 'appname', + label: intl.formatMessage({ + id: 'OBD.component.DeployConfig.ClusterName', + defaultMessage: '集群名称', + }), + rules: clusterNameRules, + placeholder: intl.formatMessage({ + id: 'OBD.component.DeployConfig.PleaseEnter', + defaultMessage: '请输入', + }), + validateTrigger: ['onBlur', 'onChange'], + }; + + useEffect(() => { + if (searchTextRef.current) { + setSelectCluster(searchTextRef.current); + form.setFieldValue('appname', searchTextRef.current); + } + }, [clusterOption]); + + useUpdateEffect(() => { + form.validateFields(['appname']); + }, [selectCluster]); + + return ( + <> + + + + + + {isUpdate ? ( + <> + + { + setAddress(value); + }} + /> + + + { + setAddress(oldAddress); + setEdit(false); + }} + /> + + + { + if (onOk) { + onOk(address); + } + }} + /> + + + ) : ( + <> + {address} + + + { + setEdit(true); + }} + /> + + + + )} + + ); +}; + +export default EditText; diff --git a/web/src/component/Empty/index.less b/web/src/component/Empty/index.less new file mode 100644 index 0000000..a426267 --- /dev/null +++ b/web/src/component/Empty/index.less @@ -0,0 +1,32 @@ +.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/web/src/component/Empty/index.tsx b/web/src/component/Empty/index.tsx new file mode 100644 index 0000000..21023e3 --- /dev/null +++ b/web/src/component/Empty/index.tsx @@ -0,0 +1,64 @@ +import React from 'react'; +import { Empty } from '@oceanbase/design'; +import type { EmptyProps as AntdEmptyProps } from 'antd/es/empty'; +import { PageContainer } from '@oceanbase/ui'; + +import PageCard from '@/component/PageCard'; +import styles from './index.less'; + +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 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/web/src/component/EnvPreCheck/CheckFailuredItem.tsx b/web/src/component/EnvPreCheck/CheckFailuredItem.tsx new file mode 100644 index 0000000..2340733 --- /dev/null +++ b/web/src/component/EnvPreCheck/CheckFailuredItem.tsx @@ -0,0 +1,240 @@ +import { intl } from '@/utils/intl'; +import React, { useState } from 'react'; +import { + Button, + Space, + Checkbox, + Typography, + Tag, + Spin, +} from '@oceanbase/design'; +import { + CloseCircleFilled, + QuestionCircleFilled, + ReadFilled, +} from '@ant-design/icons'; +import { findByValue } from '@oceanbase/util'; +import { useRequest } from 'ahooks'; +import { errorHandler } from '@/utils'; +import * as Metadb from '@/services/ocp_installer_backend/Metadb'; +import { ERROR_CODE_LIST } from '@/constant/envPresCheck'; +import Prechecked from '@/component/Icon/Prechecked'; +import styles from './index.less'; +const { Text } = Typography; + +export interface CheckFailuredItemProps { + id?: number; + loading?: boolean; + precheckMetadbResult: any; + onSuccess?: () => void; +} + +const CheckFailuredItem: React.FC = ({ + id, + loading, + onSuccess, + precheckMetadbResult, +}) => { + let precheckStatus; + // const { precheckStatus } = useSelector((state: DefaultRootState) => state.global); + const precheck_failed_list = + precheckMetadbResult?.precheck_result?.filter( + (item) => item.result === 'FAILED', + ) || []; + + const [precheckFailedList, setlrecheckFailedList] = + useState<[]>(precheck_failed_list); + + const { runAsync: recoverMetadbDeployment } = useRequest( + Metadb.recoverMetadbDeployment, + { + manual: true, + onSuccess: (res) => { + if (res?.success && onSuccess) { + onSuccess(); + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }, + ); + + // recoverable: false 手动 + // recoverable: true 自动 + const onChange = (e: CheckboxChangeEvent) => { + setlrecheckFailedList( + e?.target?.checked + ? precheck_failed_list.filter((item) => item.recoverable === false) + : precheck_failed_list, + ); + }; + + return ( +
    + + {`失败项 ${precheck_failed_list.length}/${ + precheckMetadbResult?.precheck_result?.length || 0 + }`} + + {precheckStatus === 'RUNNING' ? null : ( + + {intl.formatMessage({ + id: 'OBD.component.EnvPreCheck.CheckFailuredItem.OnlyManualFixes', + defaultMessage: '只看手动修复项', + })} + + )} + + + + + <> + {precheckFailedList.length === 0 || loading ? ( +
    + {precheckStatus === 'RUNNING' && ( +
    + +
    + +
    + )} + +
    + {precheckStatus === 'FINISHED' && + precheckMetadbResult?.task_info?.result === 'SUCCESSFUL' && ( +
    + +
    + {intl.formatMessage({ + id: 'OBD.component.EnvPreCheck.CheckFailuredItem.GreatCheckAllSuccessful', + defaultMessage: '太棒了!检查全部成功!', + })} +
    +
    + )} +
    +
    + ) : ( + <> + {precheckFailedList.map((item: API.PreCheckResult) => ( +
    + + + {`目录空间(${item?.name})`} + +
    + + + {intl.formatMessage({ + id: 'OBD.component.EnvPreCheck.CheckFailuredItem.Reason', + defaultMessage: '原因:', + })} + + + + {`ERR-${item.code}`} + + {findByValue(ERROR_CODE_LIST, item.code).label} + +
    +
    + + + {intl.formatMessage({ + id: 'OBD.component.EnvPreCheck.CheckFailuredItem.Suggestions', + defaultMessage: '建议:', + })} + + + {item.recoverable ? ( + + {intl.formatMessage({ + id: 'OBD.component.EnvPreCheck.CheckFailuredItem.AutomaticRepair', + defaultMessage: '自动修复', + })} + + ) : ( + + {intl.formatMessage({ + id: 'OBD.component.EnvPreCheck.CheckFailuredItem.ManualRepair', + defaultMessage: '手动修复', + })} + + )} + {item.advisement} + +
    + + {intl.formatMessage({ + id: 'OBD.component.EnvPreCheck.CheckFailuredItem.LearnMore', + defaultMessage: '了解更多方案', + })} + +
    + ))} + {precheckStatus === 'RUNNING' || + (loading && )} + + )} + +
    + ); +}; + +export default CheckFailuredItem; diff --git a/web/src/component/EnvPreCheck/CheckItem.tsx b/web/src/component/EnvPreCheck/CheckItem.tsx new file mode 100644 index 0000000..3f9f2d8 --- /dev/null +++ b/web/src/component/EnvPreCheck/CheckItem.tsx @@ -0,0 +1,139 @@ +import { intl } from '@/utils/intl'; +import React, { useEffect, useState } from 'react'; +import { Button, Progress } from '@oceanbase/design'; +import { Timeline } from 'antd'; +import { + CheckCircleTwoTone, + CloseCircleTwoTone, + LoadingOutlined, +} from '@ant-design/icons'; +import NP from 'number-precision'; +import styles from './index.less'; + +export interface CheckItemProps { + precheckMetadbResult?: API.PrecheckTaskInfo; + refresh?: () => void; +} + +const statusColorConfig = { + PASSED: 'green', + PENDING: 'gray', + FAILED: 'red', +}; + +const CheckItem: React.FC = ({ + refresh, + precheckMetadbResult, +}) => { + // const { precheckStatus } = useSelector((state: DefaultRootState) => state.global); + let precheckStatus; + + const [currentPrecheckMetadbResult, setCurrentPrecheckMetadbResult] = + useState(precheckMetadbResult || {}); + + const total = precheckMetadbResult?.precheck_result?.length || 0; + const passedCount = + precheckMetadbResult?.precheck_result?.filter( + (item) => item.result === 'PASSED', + ).length || 0; + const currentPassedCount = + currentPrecheckMetadbResult?.precheck_result?.filter( + (item) => item.result === 'PASSED', + ).length || 0; + + useEffect(() => { + if (passedCount !== currentPassedCount) { + setCurrentPrecheckMetadbResult(precheckMetadbResult); + } + if (precheckStatus === 'RUNNING') { + setTimeout(() => { + const timelineContainer = document.getElementById('timeline-container'); + const runningItemDom = document.getElementById('running-timeline-item'); + if (timelineContainer) { + timelineContainer.scrollTop = NP.minus( + NP.strip(runningItemDom?.offsetTop), + 150, + ); + } + }, 10); + } + }, [precheckStatus, passedCount]); + + const renderTimelineItemsIcon = (result?: string) => { + switch (result) { + case 'PASSED': + return ( + + ); + case 'FAILED': + return ; + default: + return ; + } + }; + + return ( +
    +
    + + {intl.formatMessage( + { + id: 'OBD.component.EnvPreCheck.CheckItem.CheckItemPassedcountTotal', + defaultMessage: '检查项 {{passedCount}}/{{total}}', + }, + { passedCount: passedCount, total: total }, + )} + + +
    + +
    + +
    + + {currentPrecheckMetadbResult?.precheck_result?.map( + (item: any, index: number) => ( + + {item?.name} {item?.server} + + ), + )} + +
    + ); +}; + +export default CheckItem; diff --git a/web/src/component/EnvPreCheck/index.less b/web/src/component/EnvPreCheck/index.less new file mode 100644 index 0000000..1606ae0 --- /dev/null +++ b/web/src/component/EnvPreCheck/index.less @@ -0,0 +1,61 @@ +.precheck { + :global { + .ant-card-head { + border-bottom: none; + } + } + .checkItem { + min-height: 656px; + background-color: #f8fafe; + border-radius: 8px; + + .checkItemTitle { + display: flex; + justify-content: space-between; + padding: 16px; + border-bottom: 2px solid #e2e8f3; + } + + .checnProgress { + position: relative; + top: -14px; + :global { + .ant-progress-inner { + background-color: #e2e8f3; + } + .ant-progress-outer { + height: 2px !important; + } + .ant-progress-bg { + height: 2px !important; + } + } + } + + .checkSteps { + margin-left: 16px; + :global { + .ant-steps-item:first-child { + .ant-steps-item-icon { + display: none; + } + } + .ant-steps-item > .ant-steps-item-container > .ant-steps-item-tail { + padding: 0 !important; + } + } + } + + .checkFailuredContent { + display: flex; + flex-direction: column; + padding: 16px; + border-bottom: 1px solid #e2e8f3; + + .checkFailuredItem { + display: flex; + white-space: nowrap; + } + } + } +} diff --git a/web/src/component/EnvPreCheck/index.tsx b/web/src/component/EnvPreCheck/index.tsx new file mode 100644 index 0000000..533bd3e --- /dev/null +++ b/web/src/component/EnvPreCheck/index.tsx @@ -0,0 +1,246 @@ +import { intl } from '@/utils/intl'; +import React, { useEffect } from 'react'; +import { Card, Row, Col } from '@oceanbase/design'; +import { useRequest } from 'ahooks'; +import { errorHandler } from '@/utils'; +import * as Metadb from '@/services/ocp_installer_backend/Metadb'; +import * as OCP from '@/services/ocp_installer_backend/OCP'; +import CheckItem from './CheckItem'; +import CheckFailuredItem from './CheckFailuredItem'; +import ContentWithQuestion from '../ContentWithQuestion'; +import styles from './index.less'; + +export interface EnvPreCheckProps { + id?: number; + installType?: string; +} + +const EnvPreCheck: React.FC = ({ id, installType }) => { + // const dispatch = useDispatch(); + let precheckStatus, precheckMetadbResult; + + // const { precheckStatus, precheckMetadbResult } = useSelector( + // (state: DefaultRootState) => state.global + // ); + + // 发起MetaDb的预检查 + const { + run: precheckMetadbDeploymentFn, + refresh: rePrecheckMetadbDeployment, + } = useRequest(Metadb.precheckMetadbDeployment, { + manual: true, + onSuccess: (res) => { + if (res.success) { + // dispatch({ + // type: 'global/update', + // payload: { + // precheckStatus: res?.data?.status, + // precheckResult: res?.data?.result, + // }, + // }); + getMetadbPrecheckTask({ + id: id, + task_id: res.data?.id, + }); + } + }, + }); + + //MetaDb的预检查结果 + const { + data: metadbPrecheckTaskData, + run: getMetadbPrecheckTask, + refresh: reGetMetadbPrecheckTask, + loading: metadbPrecheckTaskLoading, + } = useRequest(Metadb.getMetadbPrecheckTask, { + manual: true, + onSuccess: (res) => { + if (res?.success) { + // dispatch({ + // type: 'global/update', + // payload: { + // precheckResult: res?.data?.task_info?.result || '', + // precheckStatus: res?.data?.task_info?.status || '', + // precheckMetadbResult: res?.data || {}, + // }, + // }); + if (res?.data?.task_info?.status === 'RUNNING') { + setTimeout(() => { + reGetMetadbPrecheckTask(); + }, 2000); + } + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }); + + const precheckMetadTask = metadbPrecheckTaskData?.data || {}; + + // 发起OCP的预检查 + const { run: precheckOcpDeployment, refresh: rePrecheckOcpDeployment } = + useRequest(OCP.precheckOcpDeployment, { + manual: true, + onSuccess: (res) => { + if (res.success) { + // dispatch({ + // type: 'global/update', + // payload: { + // precheckStatus: res?.data?.status, + // precheckResult: res?.data?.result, + // }, + // }); + precheckOcp({ + id: id, + task_id: res.data?.id, + }); + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }); + + const { + data: precheckOcpDatas, + run: precheckOcp, + refresh, + loading, + } = useRequest(OCP.precheckOcp, { + manual: true, + onSuccess: (res) => { + if (res?.success) { + // dispatch({ + // type: 'global/update', + // payload: { + // precheckResult: res?.data?.task_info?.result || '', + // precheckStatus: res?.data?.task_info?.status || '', + // precheckMetadbResult: res?.data || {}, + // }, + // }); + if (res?.data?.task_info?.status === 'RUNNING') { + setTimeout(() => { + refresh(); + }, 2000); + } + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }); + + const precheckOcpData = precheckOcpDatas?.data || {}; + + useEffect(() => { + if (id) { + if (installType === 'OCP') { + precheckOcpDeployment({ + id: id, + }); + } else { + precheckMetadbDeploymentFn({ + id: id, + }); + } + } + }, [id]); + + return ( + + ) + } + bodyStyle={{ paddingTop: 0, minHeight: 680 }} + > + {installType === 'OCP' ? ( +
    + ) : ( +
    + )} + + + + { + if (installType === 'OCP') { + rePrecheckOcpDeployment(); + } else { + rePrecheckMetadbDeployment(); + } + }} + precheckMetadbResult={ + id + ? installType === 'OCP' + ? precheckOcpData + : precheckMetadTask + : precheckMetadbResult + } + /> + + + { + if (installType === 'OCP') { + rePrecheckOcpDeployment(); + } else { + rePrecheckMetadbDeployment(); + } + }} + precheckMetadbResult={ + id + ? installType === 'OCP' + ? precheckOcpData + : precheckMetadTask + : precheckMetadbResult + } + /> + + + + ); +}; + +export default EnvPreCheck; diff --git a/web/src/component/ErrorBoundary.tsx b/web/src/component/ErrorBoundary.tsx new file mode 100644 index 0000000..233f307 --- /dev/null +++ b/web/src/component/ErrorBoundary.tsx @@ -0,0 +1,87 @@ +import { intl } from '@/utils/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< + ErrorBoundaryProps, + ErrorBoundaryState +> { + 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/web/src/component/ErrorCompToolTip/index.less b/web/src/component/ErrorCompToolTip/index.less new file mode 100644 index 0000000..76ad121 --- /dev/null +++ b/web/src/component/ErrorCompToolTip/index.less @@ -0,0 +1,17 @@ +.iconContainer { + position: relative; + display: inline-block; + width: 16px; + height: 16px; + margin-left: 8px; + color: #fff; + font-size: 12px; + line-height: 22px; + vertical-align: middle; + border-radius: 50%; + .icon { + position: absolute; + top: 2px; + left: 2px; + } +} diff --git a/web/src/component/ErrorCompToolTip/index.tsx b/web/src/component/ErrorCompToolTip/index.tsx new file mode 100644 index 0000000..be8a7be --- /dev/null +++ b/web/src/component/ErrorCompToolTip/index.tsx @@ -0,0 +1,19 @@ +import { Tooltip } from "antd"; +import { CloseOutlined } from '@ant-design/icons'; + +import styles from './index.less' + +interface ErrorCompToolTipProps { + title:string, + status:'warning' | 'error' +} + +export default function ErrorCompToolTip({title,status}:ErrorCompToolTipProps) { + return ( + + + + + + ); +} diff --git a/web/src/component/ExitBtn.tsx b/web/src/component/ExitBtn.tsx new file mode 100644 index 0000000..a065c63 --- /dev/null +++ b/web/src/component/ExitBtn.tsx @@ -0,0 +1,88 @@ +import { intl } from '@/utils/intl'; +import { Button } from 'antd'; +import { useRequest, history } from 'umi'; +import { ExclamationCircleOutlined } from '@ant-design/icons'; +import { Modal } from '@oceanbase/design'; +import { errorHandler } from '@/utils'; +import { useModel } from 'umi'; +import * as Process from '@/services/ocp_installer_backend/Process'; +import { PathType } from '@/pages/type'; +import { getTailPath } from '@/utils/helper'; + +export default function ExitBtn() { + const { setInstallStatus, setInstallResult } = useModel('ocpInstallData'); + const path: PathType = getTailPath() as PathType; + // 退出 + const { run: suicide, loading: suicideLoading } = useRequest( + Process.suicide, + { + manual: true, + onSuccess: () => { + if (path === 'configuration' || path === 'install') { + setInstallStatus(''); + setInstallResult(''); + } + history.push(`/quit?path=${path}`); + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }, + ); + + return ( + + ); +} diff --git a/web/src/component/ExitPageWrapper/index.tsx b/web/src/component/ExitPageWrapper/index.tsx new file mode 100644 index 0000000..21aa4c8 --- /dev/null +++ b/web/src/component/ExitPageWrapper/index.tsx @@ -0,0 +1,82 @@ +import { useEffect } from 'react'; +import { history } from 'umi'; +import { PathType } from '@/pages/type'; +import { TIME_REFRESH } from '@/pages/constants'; + +export default function ExitPageWrapper(props: { + target?: PathType; + children: React.ReactNode; +}) { + const { target } = props; + let path: PathType | undefined; + path = target + ? target + : //@ts-ignore + (history.location.query.path as PathType | undefined); + const PATH_HANDLES = [ + { + paths: ['guide', 'ocpInstaller', 'update'], + exec(path: PathType) { + history.push(`/${path}`); + }, + }, + { + paths: ['configuration', 'install'], + exec(path: PathType) { + history.push(`/ocpinstaller/${path}`); + }, + }, + { + paths: ['obdeploy'], + exec(path: PathType) { + history.push('/'); + }, + }, + ]; + const setStorage = () => { + if (path) { + sessionStorage.setItem( + 'pathInfo', + JSON.stringify({ + path, + timestamp: new Date().getTime(), + }), + ); + } + }; + const toTargetPage = (path: PathType) => { + sessionStorage.removeItem('pathInfo'); + const targetHandler = PATH_HANDLES.find((item) => + item.paths.includes(path), + ); + if (targetHandler) { + targetHandler.exec(path); + } + }; + + useEffect(() => { + let sessionData; + try { + sessionData = JSON.parse(sessionStorage.getItem('pathInfo') as string); + } catch (e) { + + } finally { + if (sessionData) { + const isRefresh = + new Date().getTime() - sessionData.timestamp <= TIME_REFRESH; + if (isRefresh) { + toTargetPage(sessionData.path); + } + } + } + + window.addEventListener('beforeunload', setStorage); + return () => { + window.removeEventListener('beforeunload', setStorage); + }; + }, []); + + return
    + {props.children} +
    ; +} diff --git a/web/src/component/FooterToolbar/index.less b/web/src/component/FooterToolbar/index.less new file mode 100644 index 0000000..b475494 --- /dev/null +++ b/web/src/component/FooterToolbar/index.less @@ -0,0 +1,17 @@ +.container { + width: 100% !important; + height: 72px; + background-color: #F5F8FE; + padding: 0 10%; + display: flex; + align-items: center; + justify-content: flex-end; + +} +:global { + .ant-affix { + box-shadow: 0 -1px 0 0 #E8EAF3; + } +} + + diff --git a/web/src/component/FooterToolbar/index.tsx b/web/src/component/FooterToolbar/index.tsx new file mode 100644 index 0000000..173d59f --- /dev/null +++ b/web/src/component/FooterToolbar/index.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { Affix } from '@oceanbase/design'; +import type { AffixProps } from '@oceanbase/design'; + +import styles from './index.less'; + +export interface BatchOperationBarProps extends AffixProps { + style?: React.CSSProperties; +} + +const FooterToolbar: React.FC = ({ children, style, ...restProps }) => { + return ( + +
    {children}
    +
    + ); +}; + +export default FooterToolbar; diff --git a/web/src/component/Icon/ArrowIcon.tsx b/web/src/component/Icon/ArrowIcon.tsx new file mode 100644 index 0000000..2707425 --- /dev/null +++ b/web/src/component/Icon/ArrowIcon.tsx @@ -0,0 +1,14 @@ +import type { ImgHTMLAttributes } from 'react'; +import React from 'react'; + +interface ArrowIconProps extends ImgHTMLAttributes { + size?: number; + className?: string; + style?: React.CSSProperties; +} + +const ArrowIcon: React.FC = ({ size = 12, ...restProps }) => { + return ; +}; + +export default ArrowIcon; diff --git a/web/src/component/Icon/ClusterIcon.tsx b/web/src/component/Icon/ClusterIcon.tsx new file mode 100644 index 0000000..45c2959 --- /dev/null +++ b/web/src/component/Icon/ClusterIcon.tsx @@ -0,0 +1,14 @@ +import type { ImgHTMLAttributes } from 'react'; +import React from 'react'; + +interface ClusterIconProps extends ImgHTMLAttributes { + size?: number; + className?: string; + style?: React.CSSProperties; +} + +const ClusterIcon: React.FC = ({ size = 12, ...restProps }) => { + return ; +}; + +export default ClusterIcon; diff --git a/web/src/component/Icon/NewIcon.tsx b/web/src/component/Icon/NewIcon.tsx new file mode 100644 index 0000000..30e7cde --- /dev/null +++ b/web/src/component/Icon/NewIcon.tsx @@ -0,0 +1,14 @@ +import type { ImgHTMLAttributes } from 'react'; +import React from 'react'; + +interface NewIconProps extends ImgHTMLAttributes { + size?: number; + className?: string; + style?: React.CSSProperties; +} + +const NewIcon: React.FC = ({ size = 12, ...restProps }) => { + return ; +}; + +export default NewIcon; diff --git a/web/src/component/Icon/Prechecked.tsx b/web/src/component/Icon/Prechecked.tsx new file mode 100644 index 0000000..6f894f9 --- /dev/null +++ b/web/src/component/Icon/Prechecked.tsx @@ -0,0 +1,14 @@ +import type { ImgHTMLAttributes } from 'react'; +import React from 'react'; + +interface PrecheckedProps extends ImgHTMLAttributes { + size?: number; + className?: string; + style?: React.CSSProperties; +} + +const Prechecked: React.FC = ({ size = 12, ...restProps }) => { + return ; +}; + +export default Prechecked; diff --git a/web/src/component/InputPort/index.tsx b/web/src/component/InputPort/index.tsx new file mode 100644 index 0000000..a7019fe --- /dev/null +++ b/web/src/component/InputPort/index.tsx @@ -0,0 +1,62 @@ +import { commonStyle } from '@/pages/constants'; +import { intl } from '@/utils/intl'; +import { ProFormDigit } from '@ant-design/pro-components'; +import { NamePath } from 'antd/es/form/interface'; + +interface InputPortProps { + name: NamePath; + label: React.ReactNode; + fieldProps?: any; + message?: string; + limit?: boolean; //是否需要限制端口号范围 +} + +/** + * default port range 1024~65535 + */ +export default function InputPort({ + name, + label, + fieldProps, + message, + limit = true, +}: InputPortProps) { + const rules: any = [ + { + required: true, + message: + message || + intl.formatMessage({ + id: 'OBD.component.InputPort.PleaseEnter', + defaultMessage: '请输入', + }), + }, + ]; + if (limit) { + rules.push(() => ({ + validator(_: any, value: number) { + if (value < 1024 || value > 65535) { + return Promise.reject( + intl.formatMessage({ + id: 'OBD.component.InputPort.ThePortNumberCanOnly', + defaultMessage: '端口号只支持 1024~65535 范围', + }), + ); + } + return Promise.resolve(); + }, + })); + } + return ( + + ); +} diff --git a/web/src/component/InsstallResult/index.less b/web/src/component/InsstallResult/index.less new file mode 100644 index 0000000..68463cb --- /dev/null +++ b/web/src/component/InsstallResult/index.less @@ -0,0 +1,58 @@ +@cardBackgroundColor: #f8fafe; + +.versionContainer{ + margin-bottom: 16px; + + .ocpVersion { + float: left; + width: calc(50% - 66px); + padding: 21px 0; + color: #5c6b8a; + font-size: 16px; + text-align: center; + background-color: #fff; + border: 1px solid #cdd5e4; + border-radius: 8px; + span { + padding-right: 8px; + color: #132039; + font-weight: 500; + position: relative; + .newVersionIcon{ + position: absolute; + right: -34px; + top: -20px; + } + } + } +} + +.componentTable { + :global { + .ant-table-thead > tr > th { + background-color: #f5f8fe !important; + } + } +} +.componentCard { + margin-bottom: 16px !important; + background-color: @cardBackgroundColor !important; + :global { + .ant-pro-card-body { + padding: 0 !important; + } + } + &.disabledCard { + opacity: 0.4; + } + &:last-child { + margin-bottom: 0 !important; + } +} +.upgradeReport { + :global { + .ant-card-head { + border-bottom: none; + } + } +} diff --git a/web/src/component/InsstallResult/index.tsx b/web/src/component/InsstallResult/index.tsx new file mode 100644 index 0000000..b2fe441 --- /dev/null +++ b/web/src/component/InsstallResult/index.tsx @@ -0,0 +1,559 @@ +import { intl } from '@/utils/intl'; +import React, { useEffect } from 'react'; +// import { useSelector } from 'umi'; +import { + Result, + Descriptions, + Card, + Space, + Table, + Typography, + Button, + Row, + Col, + Tag, +} from '@oceanbase/design'; +import { ProCard } from '@ant-design/pro-components'; +import { useRequest } from 'ahooks'; +import { useModel } from 'umi'; +import { Alert } from 'antd'; +import { errorHandler } from '@/utils'; +import * as OCP from '@/services/ocp_installer_backend/OCP'; +import type { ResultProps } from 'antd/es/result'; +import ArrowIcon from '@/component/Icon/ArrowIcon'; +import NewIcon from '@/component/Icon/NewIcon'; +import { copyText } from '@/utils'; +import styles from './index.less'; + +const { Text } = Typography; + +export interface InsstallResultProps extends ResultProps { + upgradeOcpInfo?: API.connectMetaDB; + ocpInfo?: any; + installStatus?: string; // RUNNING, FINISHED + installResult?: string; // SUCCESSFUL, FAILED + taskId?: number; + installType?: string; + type?: string; // install update +} + +const InsstallResult: React.FC = ({ + ocpInfo, + upgradeOcpInfo, + installStatus, + installResult, + type, + installType, + ...restProps +}) => { + let isHaveMetadb; + const { ocpConfigData } = useModel('global'); + const version: string = ocpConfigData?.components?.ocpserver?.version; + // 获取 升级主机列表 + const { data: upgraadeAgentHosts, run: getOcpNotUpgradingHost } = useRequest( + OCP.getOcpNotUpgradingHost, + { + manual: true, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }, + ); + + const upgraadeHosts = upgraadeAgentHosts?.data || {}; + + useEffect(() => { + if ( + type === 'update' && + installStatus === 'FINISHED' && + installResult === 'SUCCESSFUL' + ) { + getOcpNotUpgradingHost(); + } + }, [type, installStatus, installResult]); + + const columns = [ + { + title: intl.formatMessage({ + id: 'OBD.component.InsstallResult.ComponentName', + defaultMessage: '组件名称', + }), + dataIndex: 'name', + width: '20%', + }, + { + title: intl.formatMessage({ + id: 'OBD.component.InsstallResult.NodeIp', + defaultMessage: '节点 IP', + }), + dataIndex: 'ip', + render: (ip: string[]) => { + if (!ip || !ip.length) { + return '-'; + } + return ip.map((item: string) => {item}); + }, + }, + ]; + + return ( +
    + + } + title={ + installResult === 'SUCCESSFUL' ? ( +
    + {type === 'update' ? ( + + {intl.formatMessage({ + id: 'OBD.component.InsstallResult.OcpUpgradedSuccessfully', + defaultMessage: 'OCP 升级成功', + })} + + ) : ( + + {installType === 'OCP' ? ( + <> + {isHaveMetadb === 'install' ? ( + + {intl.formatMessage({ + id: 'OBD.component.InsstallResult.OcpDeployedSuccessfully', + defaultMessage: 'OCP 部署成功', + })} + + ) : ( + + {intl.formatMessage({ + id: 'OBD.component.InsstallResult.OcpDeployedSuccessfully', + defaultMessage: 'OCP 部署成功', + })} + + )} + + ) : ( + + {intl.formatMessage({ + id: 'OBD.component.InsstallResult.MetadbDeployedSuccessfully', + defaultMessage: 'MetaDB 部署成功', + })} + + )} + + )} +
    + ) : ( + <> + {type === 'update' ? ( +
    + {intl.formatMessage({ + id: 'OBD.component.InsstallResult.OcpUpgradeFailed', + defaultMessage: 'OCP 升级失败', + })} +
    + ) : ( +
    + {installType === 'OCP' ? ( + <> + {isHaveMetadb === 'install' ? ( + + {intl.formatMessage({ + id: 'OBD.component.InsstallResult.OcpDeploymentFailed', + defaultMessage: 'OCP 部署失败', + })} + + ) : ( + + {intl.formatMessage({ + id: 'OBD.component.InsstallResult.OcpDeploymentFailed', + defaultMessage: 'OCP 部署失败', + })} + + )} + + ) : ( + + {intl.formatMessage({ + id: 'OBD.component.InsstallResult.MetadbDeploymentFailed', + defaultMessage: 'MetaDB 部署失败', + })} + + )} +
    + )} + + ) + } + subTitle={ + installResult === 'FAILED' && + installStatus === 'FINISHED' && + intl.formatMessage({ + id: 'OBD.component.InsstallResult.PleaseCheckTheLogInformation', + defaultMessage: '请查看日志信息获取失败原因,联系技术支持同学处理', + }) + } + {...restProps} + /> + + {installStatus === 'FINISHED' && ( + <> + {installStatus === 'FINISHED' && installResult === 'SUCCESSFUL' ? ( + <> + {type === 'update' ? ( + + {upgraadeHosts?.address?.length > 0 && ( + +
  1. +

    + {intl.formatMessage({ + id: 'OBD.component.InsstallResult.ThereAreHostsThatHave.1', + defaultMessage: + '·存在未升级 OCP Agent 的主机,建议您在 OCP\n 平台「主机管理」模块安装新版本 OCP Agent。', + })} +

    +

    + {' '} + {intl.formatMessage({ + id: 'OBD.component.InsstallResult.HostNotUpgraded', + defaultMessage: '未升级主机:', + })} + + {upgraadeHosts?.address?.join()} + +

    +
  2. + + } + /> + )} + + + +
    + {intl.formatMessage({ + id: 'OBD.component.InsstallResult.PreUpgradeVersion', + defaultMessage: '升级前版本:', + })} + V {upgradeOcpInfo?.ocp_version} +
    +
    + +
    +
    + {intl.formatMessage({ + id: 'OBD.component.InsstallResult.UpgradedVersion', + defaultMessage: '升级后版本:', + })} + + V {version}{' '} + + +
    + +
    + + + + + {intl.formatMessage({ + id: 'OBD.component.InsstallResult.Click', + defaultMessage: '点击', + })} + + + {' '} + {intl.formatMessage({ + id: 'OBD.component.InsstallResult.OcpReleaseRecords', + defaultMessage: 'OCP 发布记录', + })}{' '} + + {intl.formatMessage({ + id: 'OBD.component.InsstallResult.LearnMoreAboutTheNew', + defaultMessage: '了解新版本更多信息', + })} + + + ) : ( + <> + {installType === 'OCP' && ( + + +
    + {intl.formatMessage({ + id: 'OBD.component.InsstallResult.PleaseKeepTheFollowingAccess', + defaultMessage: + '请妥善保存以下访问地址及账密信息,及时更新 OCP\n 初始密码,如需了解更多,请访问', + })}{' '} + + {intl.formatMessage({ + id: 'OBD.component.InsstallResult.OceanbaseDocumentCenter', + defaultMessage: 'OceanBase 文档中心', + })} + +
    + + + } + /> + + + + {ocpInfo?.url?.join(',') || '-'} + + + {ocpInfo?.account || '-'} + + + {ocpInfo?.password ? ( + + {ocpInfo?.password} + + ) : ( + '-' + )} + + +
    + )} + + )} + + ) : null} + + )} + + ); +}; + +export default InsstallResult; diff --git a/web/src/component/InstallProcess/index.less b/web/src/component/InstallProcess/index.less new file mode 100644 index 0000000..d805fb2 --- /dev/null +++ b/web/src/component/InstallProcess/index.less @@ -0,0 +1,92 @@ +.progressEffectContainer { + position: relative; + height: 185px; + .computer { + position: absolute; + top: 55px; + left: 16px; + .computerAnimate { + width: 150px; + } + } + .progress { + position: absolute; + top: 97px; + left: 153px; + .progressAnimate { + width: 320px; + } + .progressVedio { + width: 285px; + height: 11px; + background-color: #fff; + :global { + .vjs-text-track-display { + background-color: #fff !important; + } + .vjs-poster { + top: 1px !important; + left: 1px !important; + background-position: 0 0 !important; + background-size: 100% !important; + } + .vjs-modal-dialog { + background: #fff !important; + } + .vjs-error-display:before { + content: '' !important; + } + } + } + } + .spaceman { + position: absolute; + top: 57px; + left: 133px; + .spacemanAnimate { + width: 320px; + } + } + .database { + position: absolute; + top: 55px; + right: 36px; + .sqlAnimate { + width: 150px; + } + } +} +.deploymentTitle { + position: absolute; + top: 32px; + left: 50%; + color: #132039; + font-weight: 500; + font-size: 16px; + transform: translateX(-50%); +} + +.deploymentName { + position: absolute; + bottom: 16px; + left: 50%; + color: #8592ad; + font-size: 12px; + transform: translateX(-50%); +} + +.installSubCard { + padding: 0 24px; + background-color: #fff; + :global { + .ant-card-head { + padding: 0; + border-bottom: none; + } + } + .installLog { + margin: 0 !important; + overflow: auto; + color: #8592ad; + } +} diff --git a/web/src/component/InstallProcess/index.tsx b/web/src/component/InstallProcess/index.tsx new file mode 100644 index 0000000..3c2caec --- /dev/null +++ b/web/src/component/InstallProcess/index.tsx @@ -0,0 +1,462 @@ +import { intl } from '@/utils/intl'; +import React, { useEffect, useState } from 'react'; +import { Card, Row, Col, Spin, Space } from '@oceanbase/design'; +import { CaretRightOutlined, CaretDownOutlined } from '@ant-design/icons'; +import { useRequest } from 'ahooks'; +import * as Metadb from '@/services/ocp_installer_backend/Metadb'; +import * as OCP from '@/services/ocp_installer_backend/OCP'; +import { errorHandler } from '@/utils'; +import lottie from 'lottie-web'; +import videojs from 'video.js'; +import NP from 'number-precision'; +import 'video.js/dist/video-js.css'; +import { getLocale } from 'umi'; +import styles from './index.less'; +import InsstallResult from '@/component/InsstallResult'; + +export interface InstallProcessProps { + id?: number; + type?: 'install' | 'update'; + isReinstall?: boolean; + installType: string; + ocpInfo?: any; + installInfo?: any; + upgradeOcpInfo?: any; + onSuccess?: () => void; + cluster_name?: string; + installStatus: string; + setInstallStatus: React.Dispatch>; + setInstallResult: React.Dispatch>; +} + +let timerLogScroll: NodeJS.Timer; +let timerProgress: NodeJS.Timer; +// const locale = getLocale(); +// const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; +const InstallProcess: React.FC = ({ + id, + type, + ocpInfo, + isReinstall, + installType, + installInfo, + upgradeOcpInfo, + cluster_name, + installStatus, + setInstallStatus, + setInstallResult, +}) => { + const [toBottom, setToBottom] = useState(true); + const [progress, setProgress] = useState(0); + const [showProgress, setShowProgress] = useState(0); + const [lottieProgress, setlottieProgress] = useState(); + const [openLog, setOpenLog] = useState(false); + const progressCoverInitWidth = 282; + let Video: any; + const [progressCoverStyle, setProgreddCoverStyle] = useState({ + width: progressCoverInitWidth, + background: '#fff', + borderRadius: '5px', + }); + + // 安装与升级 + const getInstallTaskFn = + installType === 'OCP' + ? type === 'update' + ? OCP.getOcpUpgradeTask + : OCP.getOcpInstallTask + : Metadb.getMetadbInstallTask; + const getInstallTaskLogFn = + installType === 'OCP' + ? type === 'update' + ? OCP.getOcpUpgradeTaskLog + : OCP.getOcpInstallTaskLog + : Metadb.getMetadbInstallTaskLog; + // 重装 + const getReinstallTaskFn = + installType === 'OCP' + ? OCP.getOcpReinstallTask + : Metadb.getMetadbReinstallTask; + const getreInstallTaskLogFn = + installType === 'OCP' + ? OCP.getOcpReinstallTaskLog + : Metadb.getMetadbReinstallTaskLog; + + const getTaskFn = isReinstall ? getReinstallTaskFn : OCP.getOcpUpgradeTask; + const getTaskLogFn = isReinstall + ? getreInstallTaskLogFn + : getInstallTaskLogFn; + + const { run: getInstallTask, data: installResultData } = useRequest( + getTaskFn, + { + manual:true, + onSuccess: ({ success, data }) => { + if (success) { + setOpenLog(data?.result === 'FAILED' || data?.result === 'RUNNING'); + setInstallStatus(data?.status); + setInstallResult(data?.result); + clearInterval(timerProgress); + + if (data?.status && data?.status === 'RUNNING') { + setTimeout(() => { + if (type === 'update') { + getInstallTask({ + cluster_name, + task_id: installInfo?.id, + }); + } + }, 2000); + } + // if (data.result === 'SUCCESSFUL' || data.result === 'SUCCESSFUL' || data?.status === 'FINISHED') { + // lottie.stop() + // } + const finished = data?.info?.filter( + (item) => + item.status === 'FINISHED' && item.result === 'SUCCESSFUL', + ).length; + + const newProgress = Number( + NP.divide(finished, data?.info?.length).toFixed(2), + ); + + setProgress(newProgress); + const step = NP.minus(newProgress, progress); + let stepNum = 1; + timerProgress = setInterval(() => { + const currentProgressNumber = NP.plus( + progress, + NP.times(NP.divide(step, 100), stepNum), + ); + if (currentProgressNumber >= 1) { + clearInterval(timerProgress); + } else { + stepNum += 1; + setShowProgress(currentProgressNumber); + } + }, 10); + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + setInstallStatus('FINISHED'); + setInstallResult('FAILED'); + }, + }, + ); + + const installResult = installResultData?.data || {}; + + const { run: getInstallTaskLog, data: installLogData } = useRequest( + getTaskLogFn, + { + manual:true, + onSuccess: ({ success }: API.OBResponseInstallLog_) => { + if (success && installStatus === 'RUNNING') { + setTimeout(() => { + getInstallTaskLog({ + cluster_name, + task_id: installInfo?.id, + }); + }, 2000); + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + setInstallStatus('FINISHED'); + setInstallResult('FAILED'); + }, + }, + ); + + const installLog = installLogData?.data || {}; + + const toLogBottom = () => { + const log = document.getElementById('installLog'); + if (log) { + log.scrollTop = log.scrollHeight; + } + }; + + const handleScroll = (e?: any) => { + e = e || window.event; + const dom = e.target; + if (dom.scrollTop + dom.clientHeight === dom.scrollHeight) { + setToBottom(true); + } else { + setToBottom(false); + } + }; + const getAnimate = () => { + const computerAnimate = document.querySelector('.computer-animate'); + const progressAnimate = document.querySelector('.progress-animate'); + const spacemanAnimate = document.querySelector('.spaceman-animate'); + const sqlAnimate = document.querySelector('.database-animate'); + + if (progressAnimate) { + Video = videojs(progressAnimate, { + controls: false, + autoplay: true, + loop: true, + preload: 'auto', + }); + } + + lottie.loadAnimation({ + prefetch: true, + container: computerAnimate, + renderer: 'svg', + loop: true, + autoplay: true, + path: '/assets/computer/data.json', + }); + + lottie.loadAnimation({ + prefetch: true, + container: spacemanAnimate, + renderer: 'svg', + loop: true, + autoplay: true, + path: '/assets/spaceman/data.json', + }); + + lottie.loadAnimation({ + prefetch: true, + container: sqlAnimate, + renderer: 'svg', + loop: true, + autoplay: true, + path: '/assets/database/data.json', + }); + }; + + useEffect(() => { + if (installInfo.id) { + if (type === 'update') { + setInstallResult('RUNNING'); + setInstallStatus('RUNNING'); + getInstallTask({ + cluster_name, + task_id: installInfo?.id, + }); + getInstallTaskLog({ + cluster_name, + task_id: installInfo?.id, + }); + } + } + }, [installInfo, isReinstall]); + + useEffect(() => { + // lottie.play(); + getAnimate(); + const log = document.querySelector('#installLog'); + log.addEventListener('scroll', handleScroll); + + return () => { + log.removeEventListener('DOMMouseScroll', handleScroll); + clearInterval(timerLogScroll); + clearInterval(timerProgress); + Video.dispose(); + }; + }, [id, installInfo?.id]); + + useEffect(() => { + if (toBottom) { + toLogBottom(); + timerLogScroll = setInterval(() => toLogBottom()); + } else { + clearInterval(timerLogScroll); + } + }, [toBottom]); + + useEffect(() => { + let newCoverStyle: any = { ...progressCoverStyle }; + const newCoverWidth = NP.times( + NP.minus(1, showProgress), + progressCoverInitWidth, + ); + + if (showProgress > 0) { + newCoverStyle = { + width: `${newCoverWidth}px`, + background: + 'linear-gradient( to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 10px, rgba(255, 255, 255, 1) )', + }; + } + setProgreddCoverStyle(newCoverStyle); + }, [showProgress]); + + useEffect(() => { + if (lottieProgress) { + lottieProgress.goToAndStop( + NP.times(showProgress, lottieProgress.totalFrames - 1), + true, + ); + } + }, [lottieProgress, showProgress]); + + return ( + + + + {installStatus === 'RUNNING' ? ( +
    +
    + + {installType}{' '} + {type === 'update' + ? intl.formatMessage({ + id: 'OBD.component.InstallProcess.Upgraded', + defaultMessage: '升级中', + }) + : intl.formatMessage({ + id: 'OBD.component.InstallProcess.Deploying', + defaultMessage: '部署中', + })} + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + {intl.formatMessage({ + id: 'OBD.component.InstallProcess.Deploying.1', + defaultMessage: '正在部署', + })} + {installResult?.current} + +
    + ) : ( + + )} + + + + {type === 'update' + ? intl.formatMessage({ + id: 'OBD.component.InstallProcess.UpgradeLogs', + defaultMessage: '升级日志', + }) + : intl.formatMessage({ + id: 'OBD.component.InstallProcess.DeploymentLogs', + defaultMessage: '部署日志', + })} + { + setOpenLog(!openLog); + }} + > + {openLog ? : } + + + } + bodyStyle={{ + padding: 24, + }} + className={`${styles.installSubCard} resource-card card-background-color`} + style={{ + background: installStatus === 'RUNNING' ? '#F8FAFE' : '#fff', + }} + > +
    +              {openLog && (
    +                <>
    +                  {installLog?.log}
    +                  {installStatus === 'RUNNING' ? (
    +                    
    +
    +
    +
    +
    +
    + ) : null} + +
    + +
    + + )} +
    +
    + + + + ); +}; + +export default InstallProcess; diff --git a/web/src/component/InstallProcessNew/index.tsx b/web/src/component/InstallProcessNew/index.tsx new file mode 100644 index 0000000..70805b8 --- /dev/null +++ b/web/src/component/InstallProcessNew/index.tsx @@ -0,0 +1,452 @@ +import { intl } from '@/utils/intl'; +import { useEffect, useState } from 'react'; +import { useModel } from 'umi'; +import { ProCard } from '@ant-design/pro-components'; +import useCustomRequest from '@/utils/useRequest'; +import { useRequest } from 'ahooks'; +import { + queryInstallStatus, + queryInstallLog, +} from '@/services/ob-deploy-web/Deployments'; +import { getErrorInfo } from '@/utils'; +import * as OCP from '@/services/ocp_installer_backend/OCP'; +import lottie from 'lottie-web'; +import NP from 'number-precision'; +import videojs from 'video.js'; +import 'video.js/dist/video-js.css'; +import { getLocale } from 'umi'; +import CustomFooter from '../CustomFooter'; +import ExitBtn from '../ExitBtn'; +import EnStyles from '@/pages/Obdeploy/indexEn.less'; +import ZhStyles from '@/pages/Obdeploy/indexZh.less'; + +interface InstallProcessNewProps { + current: number; + setCurrentStep: React.Dispatch>; + name?: string; + id?: number; //connectId + task_id?: number; + type?: 'install' | 'update'; + installStatus: string; + setInstallStatus: React.Dispatch>; + cluster_name?: string; +} + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; + +let timerLogScroll: NodeJS.Timer; +let timerProgress: NodeJS.Timer; + +export default function InstallProcessNew({ + setCurrentStep, + name, + current, + id, + task_id, + installStatus, + setInstallStatus, + type, + cluster_name, +}: InstallProcessNewProps) { + const { setErrorVisible, setErrorsList, errorsList } = useModel('global'); + const { setInstallResult, isReinstall, logData, setLogData } = + useModel('ocpInstallData'); + const progressCoverInitWidth = 282; + const [toBottom, setToBottom] = useState(true); + const [progress, setProgress] = useState(0); + const [showProgress, setShowProgress] = useState(0); + const [progressCoverStyle, setProgreddCoverStyle] = useState({ + width: progressCoverInitWidth, + background: '#fff', + borderRadius: '5px', + }); + const [currentPage, setCurrentPage] = useState(true); + const [statusData, setStatusData] = useState({}); + const [opcStatusData, setOpcStatusData] = useState({}); + let Video: any; + + const getInstallTaskFn = + type === 'update' ? OCP.getOcpUpgradeTask : OCP.getOcpInstallTask; + const getInstallTaskLogFn = + type === 'update' ? OCP.getOcpUpgradeTaskLog : OCP.getOcpInstallTaskLog; + const getReinstallTaskFn = OCP.getOcpReinstallTask; + const getreInstallTaskLogFn = OCP.getOcpReinstallTaskLog; + const getTaskFn = isReinstall ? getReinstallTaskFn : getInstallTaskFn; + const getTaskLogFn = isReinstall + ? getreInstallTaskLogFn + : getInstallTaskLogFn; + + const { run: fetchInstallStatus } = useCustomRequest(queryInstallStatus, { + onSuccess: ({ success, data }: API.OBResponseTaskInfo_) => { + if (success) { + setStatusData(data || {}); + clearInterval(timerProgress); + if (data?.status !== 'RUNNING') { + setInstallStatus(data?.status); + setCurrentPage(false); + setTimeout(() => { + setCurrentStep(current + 1); + setErrorVisible(false); + setErrorsList([]); + }, 2000); + } else { + setTimeout(() => { + fetchInstallStatus({ name }); + }, 2000); + } + const newProgress = NP.divide(data?.finished, data?.total).toFixed(2); + setProgress(newProgress); + let step = NP.minus(newProgress, progress); + let stepNum = 1; + timerProgress = setInterval(() => { + const currentProgressNumber = NP.plus( + progress, + NP.times(NP.divide(step, 100), stepNum), + ); + + if (currentProgressNumber >= 1) { + clearInterval(timerProgress); + } else { + stepNum += 1; + setShowProgress(currentProgressNumber); + } + }, 10); + } + }, + onError: (e: any) => { + if (currentPage) { + setTimeout(() => { + fetchInstallStatus({ name }); + }, 2000); + } + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }); + + const { run: handleInstallLog } = useCustomRequest(queryInstallLog, { + onSuccess: ({ success, data }: API.OBResponseInstallLog_) => { + if (success && installStatus === 'RUNNING') { + setLogData(data || {}); + setTimeout(() => { + handleInstallLog({ name }); + }, 2000); + } + }, + onError: (e: any) => { + if (installStatus === 'RUNNING' && currentPage) { + setTimeout(() => { + handleInstallLog({ name }); + }, 2000); + } + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }); + // ocp + const { run: getInstallTask } = useRequest(getTaskFn, { + manual: true, + onSuccess: ({ success, data }) => { + if (success) { + setOpcStatusData(data || {}); + clearInterval(timerProgress); + setInstallResult(data?.result); + if (data?.status && data?.status !== 'RUNNING') { + setInstallStatus(data?.status); + setCurrentPage(false); + setTimeout(() => { + setCurrentStep(current + 1); + setErrorVisible(false); + setErrorsList([]); + }, 2000); + } else { + setTimeout(() => { + getInstallTask({ id, task_id }); + }, 2000); + } + const finished = data?.info?.filter( + (item) => item.status === 'FINISHED' && item.result === 'SUCCESSFUL', + ).length; + const newProgress = Number( + NP.divide(finished, data?.info?.length).toFixed(2), + ); + setProgress(newProgress); + let step = NP.minus(newProgress, progress); + let stepNum = 1; + timerProgress = setInterval(() => { + const currentProgressNumber = NP.plus( + progress, + NP.times(NP.divide(step, 100), stepNum), + ); + + if (currentProgressNumber >= 1) { + clearInterval(timerProgress); + } else { + stepNum += 1; + setShowProgress(currentProgressNumber); + } + }, 10); + } + }, + onError: (e: any) => { + if (currentPage) { + setTimeout(() => { + getInstallTask({ id, task_id }); + }, 2000); + } + setInstallResult('FAILED'); + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }); + const { run: getInstallTaskLog } = useRequest(getTaskLogFn, { + manual: true, + onSuccess: ({ success, data }: API.OBResponseInstallLog_) => { + if (success) setLogData(data || {}); + if (success && installStatus === 'RUNNING') { + setTimeout(() => { + if (type === 'update') { + getInstallTaskLog({ cluster_name, task_id }); + } else { + getInstallTaskLog({ id, task_id }); + } + }, 2000); + } + }, + onError: (e: any) => { + if (installStatus === 'RUNNING' && currentPage) { + setTimeout(() => { + if (type === 'update') { + getInstallTaskLog({ cluster_name, task_id }); + } else { + getInstallTaskLog({ id, task_id }); + } + }, 2000); + } + setInstallResult('FAILED'); + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }); + + const toLogBottom = () => { + const log = document.getElementById('installLog'); + if (log) { + log.scrollTop = log.scrollHeight; + } + }; + + const handleScroll = (e?: any) => { + e = e || window.event; + const dom = e.target; + if (dom.scrollTop + dom.clientHeight === dom.scrollHeight) { + setToBottom(true); + } else { + setToBottom(false); + } + }; + + const getAnimate = () => { + const computerAnimate = document.querySelector('.computer-animate'); + const progressAnimate = document.querySelector('.progress-animate'); + const spacemanAnimate = document.querySelector('.spaceman-animate'); + const sqlAnimate = document.querySelector('.database-animate'); + + if (progressAnimate) { + Video = videojs(progressAnimate, { + controls: false, + autoplay: true, + loop: true, + preload: 'auto', + }); + } + + lottie.loadAnimation({ + prefetch: true, + container: computerAnimate, + renderer: 'svg', + loop: true, + autoplay: true, + path: '/assets/computer/data.json', + }); + + lottie.loadAnimation({ + prefetch: true, + container: spacemanAnimate, + renderer: 'svg', + loop: true, + autoplay: true, + path: '/assets/spaceman/data.json', + }); + + lottie.loadAnimation({ + prefetch: true, + container: sqlAnimate, + renderer: 'svg', + loop: true, + autoplay: true, + path: '/assets/database/data.json', + }); + }; + + useEffect(() => { + if (name) { + fetchInstallStatus({ name }); + handleInstallLog({ name }); + } else if (id && task_id) { + setInstallResult('RUNNING'); + setInstallStatus('RUNNING'); + getInstallTask({ id, task_id }); + if (type === 'update') { + getInstallTaskLog({ cluster_name, task_id }); + } else { + getInstallTaskLog({ id, task_id }); + } + } + }, [name, id, task_id]); + + useEffect(() => { + getAnimate(); + const log = document.querySelector('#installLog'); + log.addEventListener('scroll', handleScroll); + return () => { + log.removeEventListener('DOMMouseScroll', handleScroll); + clearInterval(timerLogScroll); + clearInterval(timerProgress); + Video.dispose(); + }; + }, []); + + useEffect(() => { + if (toBottom) { + toLogBottom(); + timerLogScroll = setInterval(() => toLogBottom()); + } else { + clearInterval(timerLogScroll); + } + }, [toBottom]); + + useEffect(() => { + let newCoverStyle: any = { ...progressCoverStyle }; + const newCoverWidth = NP.times( + NP.minus(1, showProgress), + progressCoverInitWidth, + ); + + if (showProgress > 0) { + newCoverStyle = { + width: `${newCoverWidth}px`, + background: + 'linear-gradient( to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 10px, rgba(255, 255, 255, 1) )', + }; + } + setProgreddCoverStyle(newCoverStyle); + }, [showProgress]); + + const getText = (name?: string) => { + return intl.formatMessage( + { + id: 'OBD.pages.components.InstallProcess.DeployingName', + defaultMessage: '正在部署 {name}', + }, + { name: name }, + ); + }; + return ( + + +
    +
    + {type === 'update' ? ( + <> + {intl.formatMessage({ + id: 'OBD.component.InstallProcessNew.Upgrading', + defaultMessage: '升级中...', + })} + + ) : ( + <> + {' '} + {intl.formatMessage({ + id: 'OBD.pages.components.InstallProcess.Deploying', + defaultMessage: '部署中...', + })} + + )} +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + {getText(statusData?.current)} + +
    + +
    +          {logData?.log}
    +          {installStatus === 'RUNNING' ? (
    +            
    +
    +
    +
    +
    +
    + ) : null} +
    +
    + + + +
    + ); +} diff --git a/web/src/component/InstallResult/index.less b/web/src/component/InstallResult/index.less new file mode 100644 index 0000000..235a393 --- /dev/null +++ b/web/src/component/InstallResult/index.less @@ -0,0 +1,41 @@ +.ocpVersion { + float: left; + width: calc(50% - 66px); + padding: 21px 0; + color: #5c6b8a; + font-size: 16px; + text-align: center; + background-color: #fff; + border: 1px solid #cdd5e4; + border-radius: 8px; + span { + padding-right: 8px; + color: #132039; + font-weight: 500; + } + } + + .upgradeReport { + :global { + .ant-card-head { + border-bottom: none; + } + } + } + + +.installSubCard { + padding: 0 24px; + background-color: #fff; + :global { + .ant-card-head { + padding: 0; + border-bottom: none; + } + } + .installLog { + margin: 0 !important; + overflow: auto; + color: #8592ad; + } +} diff --git a/web/src/component/InstallResult/index.tsx b/web/src/component/InstallResult/index.tsx new file mode 100644 index 0000000..ff36769 --- /dev/null +++ b/web/src/component/InstallResult/index.tsx @@ -0,0 +1,743 @@ +import { intl } from '@/utils/intl'; +import React, { useEffect, useState } from 'react'; +import { + Modal, + Result, + Descriptions, + Card, + Space, + Table, + Typography, + Button, + Row, + Col, + Tag, +} from '@oceanbase/design'; +import { useRequest } from 'ahooks'; +import { + ExclamationCircleOutlined, + CaretRightOutlined, + CaretDownOutlined, +} from '@ant-design/icons'; +import { Alert, Spin } from 'antd'; +import { history, useModel } from 'umi'; +import { errorHandler } from '@/utils'; +import * as Process from '@/services/ocp_installer_backend/Process'; +import * as OCP from '@/services/ocp_installer_backend/OCP'; +import type { ResultProps } from 'antd/es/result'; +import ArrowIcon from '@/component/Icon/ArrowIcon'; +import NewIcon from '@/component/Icon/NewIcon'; +import { copyText } from '@/utils'; +import CustomFooter from '../CustomFooter'; +import ExitBtn from '../ExitBtn'; +import styles from './index.less'; +import { getTailPath } from '@/utils/helper'; + +const { Text } = Typography; + +export interface InsstallResultProps extends ResultProps { + upgradeOcpInfo?: any; + ocpInfo?: any; + installStatus?: string; // RUNNING, FINISHED + installResult?: string; // SUCCESSFUL, FAILED + taskId?: number; + type?: string; // install update + current: number; + setCurrent: React.Dispatch>; +} + +const InstallResult: React.FC = ({ + ocpInfo, + upgradeOcpInfo, + installStatus, + installResult, + type, + setCurrent, + current, + ...restProps +}) => { + let isHaveMetadb = 'install'; + const isUpdate = getTailPath() === 'update'; + // 获取 升级主机列表 + const { data: upgraadeAgentHosts, run: getOcpNotUpgradingHost } = useRequest( + OCP.getOcpNotUpgradingHost, + { + manual: true, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }, + ); + const { logData, setInstallStatus, setInstallResult } = + useModel('ocpInstallData'); + const [openLog, setOpenLog] = useState( + installResult === 'FAILED' ? true : false, + ); + const { setIsReinstall, connectId, setInstallTaskId } = + useModel('ocpInstallData'); + const upgraadeHosts = upgraadeAgentHosts?.data || {}; + + // 重装ocp + const { + // data: reInstallOcpData, + run: reInstallOcp, + loading: reInstallOcpLoading, + } = useRequest(OCP.reinstallOcp, { + manual: true, + onSuccess: (res) => { + if (res?.success) { + res.data?.id && setInstallTaskId(res.data?.id); + setIsReinstall(true); + setInstallStatus('RUNNING'); + setCurrent(current - 1); + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }); + + // 退出 + const { run: suicide, loading: suicideLoading } = useRequest( + Process.suicide, + { + manual: true, + onSuccess: (res) => { + if (res?.success) { + setInstallStatus(''); + setInstallResult(''); + history.push(`/quit?type=${isUpdate ? 'update' : 'install'}`); + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }, + ); + + // 销毁 OCP 安装残留 + const { run: destroyOcp, loading: destroyOCPLoading } = useRequest( + OCP.destroyOcp, + { + manual: true, + onSuccess: (data) => { + if (data?.success) { + setCurrent(3); + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }, + ); + + useEffect(() => { + if ( + type === 'update' && + installStatus === 'FINISHED' && + installResult === 'SUCCESSFUL' + ) { + getOcpNotUpgradingHost(); + } + }, [type, installStatus, installResult]); + + const columns = [ + { + title: intl.formatMessage({ + id: 'OBD.component.InstallResult.ComponentName', + defaultMessage: '组件名称', + }), + dataIndex: 'name', + width: '20%', + }, + { + title: intl.formatMessage({ + id: 'OBD.component.InstallResult.NodeIp', + defaultMessage: '节点 IP', + }), + dataIndex: 'ip', + render: (text, record) => { + if (!text || text === '') { + return '-'; + } + const addressList = text.split(','); + return addressList.map((item: string) => {item}); + }, + }, + ]; + + return ( +
    + + } + title={ + installResult === 'SUCCESSFUL' ? ( +
    + {type === 'update' ? ( + + {intl.formatMessage({ + id: 'OBD.component.InstallResult.OcpUpgradedSuccessfully', + defaultMessage: 'OCP 升级成功', + })} + + ) : ( + + <> + {isHaveMetadb === 'install' ? ( + + {intl.formatMessage({ + id: 'OBD.component.InstallResult.OcpDeployedSuccessfully', + defaultMessage: 'OCP 部署成功', + })} + + ) : ( + + {intl.formatMessage({ + id: 'OBD.component.InstallResult.OcpDeployedSuccessfully', + defaultMessage: 'OCP 部署成功', + })} + + )} + + + )} +
    + ) : ( + <> + {type === 'update' ? ( +
    + {intl.formatMessage({ + id: 'OBD.component.InstallResult.OcpUpgradeFailed', + defaultMessage: 'OCP 升级失败', + })} +
    + ) : ( +
    + <> + {isHaveMetadb === 'install' ? ( + + {intl.formatMessage({ + id: 'OBD.component.InstallResult.OcpDeploymentFailed', + defaultMessage: 'OCP 部署失败', + })} + + ) : ( + + {intl.formatMessage({ + id: 'OBD.component.InstallResult.OcpDeploymentFailed', + defaultMessage: 'OCP 部署失败', + })} + + )} + +
    + )} + + ) + } + subTitle={ + installResult === 'FAILED' && + installStatus === 'FINISHED' && + intl.formatMessage({ + id: 'OBD.component.InstallResult.PleaseCheckTheLogInformation', + defaultMessage: '请查看日志信息获取失败原因,联系技术支持同学处理', + }) + } + {...restProps} + /> + +
    + {installStatus === 'FINISHED' && installResult === 'SUCCESSFUL' ? ( + <> + {type === 'update' ? ( + + {upgraadeHosts?.address?.length > 0 && ( + + {/* 备份文件保存地址:/abc/def/hijk,可根据需要对备份文件进行维护管理 */} +
  3. + {intl.formatMessage({ + id: 'OBD.component.InstallResult.WeRecommendThatYouInstall', + defaultMessage: + '存在未升级 OCP Agent 的主机,建议您在 OCP 平台「主机管理」模块安装新版本 OCP Agent。', + })} +
    + {upgraadeHosts?.address?.join()} +
  4. + {/*
  5. + ·备份文件保存地址:/abc/def/hijk, 可根据需要对备份文件进行维护管理 +
  6. */} + + } + /> + )} + + +
    +
    + {intl.formatMessage({ + id: 'OBD.component.InstallResult.PreUpgradeVersion', + defaultMessage: '升级前版本:', + })} + V {upgradeOcpInfo?.ocp_version} +
    +
    + +
    +
    + {intl.formatMessage({ + id: 'OBD.component.InstallResult.UpgradedVersion', + defaultMessage: '升级后版本:', + })} + + V {upgradeOcpInfo?.upgrade_version} + +
    + + +
    + + + {intl.formatMessage({ + id: 'OBD.component.InstallResult.Click', + defaultMessage: '点击', + })} + + + {' '} + {intl.formatMessage({ + id: 'OBD.component.InstallResult.OcpReleaseRecords', + defaultMessage: 'OCP 发布记录', + })}{' '} + + {intl.formatMessage({ + id: 'OBD.component.InstallResult.LearnMoreAboutTheNew', + defaultMessage: '了解新版本更多信息', + })} + + + ) : ( + + +
    + {intl.formatMessage({ + id: 'OBD.component.InstallResult.PleaseKeepTheFollowingAccess', + defaultMessage: + '请妥善保存以下访问地址及账密信息,及时更新 OCP\n 初始密码,如需了解更多,请访问', + })}{' '} + + {intl.formatMessage({ + id: 'OBD.component.InstallResult.OceanbaseDocumentCenter', + defaultMessage: 'OceanBase 文档中心', + })} + +
    + + + } + /> + + + + {ocpInfo?.url?.join(',') || '-'} + + + {ocpInfo?.account || '-'} + + + {ocpInfo?.password ? ( + + {ocpInfo?.password} + + ) : ( + '-' + )} + + +
    + )} + + ) : null} + + + + {type === 'update' + ? intl.formatMessage({ + id: 'OBD.component.InstallResult.UpgradeLogs', + defaultMessage: '升级日志', + }) + : intl.formatMessage({ + id: 'OBD.component.InstallResult.DeploymentLogs', + defaultMessage: '部署日志', + })} + { + setOpenLog(!openLog); + }} + > + {openLog ? : } + + + } + bodyStyle={{ + padding: 0, + }} + className={`${styles.installSubCard} resource-card card-background-color`} + style={{ + background: installStatus === 'RUNNING' ? '#F8FAFE' : '#fff', + }} + > +
    +            {openLog && (
    +              <>
    +                {logData?.log}
    +                {installStatus === 'RUNNING' ? (
    +                  
    +
    +
    +
    +
    +
    + ) : null} + +
    + +
    + + )} +
    +
    + + + {installResult === 'SUCCESSFUL' ? ( + + ) : ( + <> + + + + + )} + + + ); +}; + +export default InstallResult; diff --git a/web/src/component/MetaDBConfig/ClusterConfig.tsx b/web/src/component/MetaDBConfig/ClusterConfig.tsx new file mode 100644 index 0000000..4cd7881 --- /dev/null +++ b/web/src/component/MetaDBConfig/ClusterConfig.tsx @@ -0,0 +1,337 @@ +import { intl } from '@/utils/intl'; +import { Space, Input, Button, Row } from 'antd'; +import { ProFormText, ProForm, ProFormDigit } from '@ant-design/pro-components'; +import { RightOutlined, DownOutlined } from '@ant-design/icons'; +import { useEffect, useState } from 'react'; +import { FormInstance } from 'antd/lib/form'; +import { useModel } from 'umi'; + +import { + commonStyle, + componentsConfig, + componentVersionTypeToComponent, +} from '@/pages/constants'; +import useRequest from '@/utils/useRequest'; +import { queryComponentParameters } from '@/services/ob-deploy-web/Components'; +import ConfigTable from '@/pages/Obdeploy/ClusterConfig/ConfigTable'; +import { showConfigKeys } from '@/constant/configuration'; +import Parameter from '@/pages/Obdeploy/ClusterConfig/Parameter'; +import InputPort from '../InputPort'; +import { + generateRandomPassword as generatePassword, + passwordRules, + getErrorInfo, +} from '@/utils'; +import styles from './indexZh.less'; +import { oceanbaseAddonAfter } from '@/constant/configuration'; + +export default function ClusterConfig({ form }: { form: FormInstance }) { + const [isShowMoreConfig, setIsShowMoreConfig] = useState(false); + const [clusterMoreLoading, setClusterMoreLoading] = useState(false); + const { + ocpClusterMore, + setOcpClusterMore, + ocpConfigData, + setOcpConfigData, + ocpClusterMoreConfig, + setOcpClusterMoreConfig, + setErrorVisible, + setErrorsList, + errorsList, + } = useModel('global'); + const { components = {}, home_path } = ocpConfigData || {}; + const { oceanbase = {} } = components; + const [rootPassword, setRootPassword] = useState( + oceanbase.root_password || '', + ); + const { run: getMoreParamsters } = useRequest(queryComponentParameters); + const getInitialParameters = ( + currentComponent: string, + dataSource: API.MoreParameter[], + data: API.NewParameterMeta[], + ) => { + const currentComponentNameConfig = data?.filter( + (item) => item.component === currentComponent, + )?.[0]; + if (currentComponentNameConfig) { + const parameters: any = {}; + currentComponentNameConfig.configParameter.forEach((item) => { + let parameter = { + ...item, + key: item.name, + params: { + value: item.default, + adaptive: item.auto, + auto: item.auto, + require: item.require, + type: item.type, + }, + }; + dataSource?.some((dataItem) => { + if (item.name === dataItem.key) { + parameter = { + key: dataItem.key, + description: parameter.description, + params: { + ...parameter.params, + ...dataItem, + }, + }; + return true; + } + return false; + }); + if ( + (parameter.params.type === 'CapacityMB' || + parameter.params.type === 'Capacity') && + parameter.params.value == '0' + ) { + parameter.params.value += 'GB'; + } + parameters[item.name] = parameter; + }); + return parameters; + } else { + return undefined; + } + }; + + const formatMoreConfig = (dataSource: API.ParameterMeta[]) => { + return dataSource.map((item) => { + const component = componentVersionTypeToComponent[item.component] + ? componentVersionTypeToComponent[item.component] + : item.component; + const componentConfig = componentsConfig[component]; + // filter out existing parameters + let configParameter = item?.config_parameters.filter((parameter) => { + return !showConfigKeys?.[componentConfig.componentKey]?.includes( + parameter.name, + ); + }); + const newConfigParameter: API.NewConfigParameter[] = configParameter.map( + (parameterItem) => { + if(parameterItem.name === "cluster_id")parameterItem.default = '0' + return { + ...parameterItem, + parameterValue: { + value: parameterItem.default, + adaptive: parameterItem.auto, + auto: parameterItem.auto, + require: parameterItem.require, + }, + }; + }, + ); + + const result: API.NewParameterMeta = { + ...item, + componentKey: componentConfig.componentKey, + label: componentConfig.labelName, + configParameter: newConfigParameter, + }; + result.configParameter.forEach((item) => { + Object.assign(item.parameterValue, { type: item.type }); + }); + return result; + }); + }; + const getClusterMoreParamsters = async () => { + setClusterMoreLoading(true); + try { + const { success, data } = await getMoreParamsters( + {}, + { + filters: [ + { + component: oceanbase?.component, + version: oceanbase?.version, + is_essential_only: true, + }, + ], + }, + ); + if (success) { + const newClusterMoreConfig = formatMoreConfig(data?.items); + setOcpClusterMoreConfig(newClusterMoreConfig); + form.setFieldsValue({ + oceanbase: { + parameters: getInitialParameters( + oceanbase?.component, + oceanbase?.parameters, + newClusterMoreConfig, + ), + }, + }); + } + } catch (e: any) { + setOcpClusterMore(false); + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + } + setClusterMoreLoading(false); + }; + + const handleCluserMoreChange = () => { + setOcpClusterMore(!ocpClusterMore); + if (!ocpClusterMoreConfig?.length) { + getClusterMoreParamsters(); + } + }; + + const setPassword = (password: string) => { + form.setFieldValue(['oceanbase', 'root_password'], password); + form.validateFields([['oceanbase', 'root_password']]); + setRootPassword(password); + }; + + const generateRandomPassword = () => { + const password = generatePassword(); + setPassword(password); + }; + + useEffect(() => { + if (isShowMoreConfig) { + } + }, [isShowMoreConfig]); + + return ( +
    +

    + {intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.ClusterConfig.ClusterConfiguration', + defaultMessage: '集群配置', + })} +

    +
    + { + setPassword(e.target.value); + }, + }} + placeholder={intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.ClusterConfig.PleaseEnter', + defaultMessage: '请输入', + })} + validateFirst + /> + + +
    + + {oceanbaseAddonAfter}, + style: { width: 552 }, + }} + /> + + + + + + + + + + + +
    + handleCluserMoreChange()} + className={styles.moreConfigText} + > + + {intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.ClusterConfig.MoreConfigurations', + defaultMessage: '更多配置', + })} + + {!ocpClusterMore ? : } + +
    + } + /> +
    + ); +} diff --git a/web/src/component/MetaDBConfig/ConfigTable.tsx b/web/src/component/MetaDBConfig/ConfigTable.tsx new file mode 100644 index 0000000..eed2bf7 --- /dev/null +++ b/web/src/component/MetaDBConfig/ConfigTable.tsx @@ -0,0 +1,72 @@ +import { intl } from '@/utils/intl'; +import { Space } from 'antd'; +import { getLocale } from 'umi'; + +import styles from './indexZh.less'; +interface ConfigTableProps { + dataSource: API.NewParameterMeta[]; + loading: boolean; +} +const locale = getLocale(); +const getMoreColumns = () => { + const columns = [ + { + title: intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.ConfigTable.ClusterParameterName', + defaultMessage: '集群参数名称', + }), + dataIndex: 'name', + width: 250, + render: (text: string) => text || '-', + }, + { + title: intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.ConfigTable.ParameterValue', + defaultMessage: '参数值', + }), + width: locale === 'zh-CN' ? 280 : 360, + dataIndex: 'parameterValue', + render: () => { + return ( +

    + {intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.ConfigTable.ParameterValue', + defaultMessage: '参数值', + })} +

    + // + // + // + ); + }, + }, + { + title: intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.ConfigTable.Introduction', + defaultMessage: '介绍', + }), + dataIndex: 'description', + render: (text:string) => + text ?
    {text}
    : '-', + }, + ]; + + return columns; +}; + +export default function ConfigTable() { + return ( + + aa + + ); +} diff --git a/web/src/component/MetaDBConfig/DataBaseNodeConfig.tsx b/web/src/component/MetaDBConfig/DataBaseNodeConfig.tsx new file mode 100644 index 0000000..4d2427d --- /dev/null +++ b/web/src/component/MetaDBConfig/DataBaseNodeConfig.tsx @@ -0,0 +1,436 @@ +import { intl } from '@/utils/intl'; +import { EditableProTable, ProForm, ProCard } from '@ant-design/pro-components'; +import { useRef, useState } from 'react'; +import type { + ProColumns, + EditableFormInstance, +} from '@ant-design/pro-components'; +import { useModel } from 'umi'; +import { Tooltip, Popconfirm, message, Select } from 'antd'; +import { QuestionCircleOutlined, DeleteOutlined } from '@ant-design/icons'; + +import ServerTags from '@/pages/Obdeploy/ServerTags'; +import styles from './indexZh.less'; + +interface DataBaseNodeConfigProps { + tableFormRef: React.MutableRefObject< + EditableFormInstance | undefined + >; + dbConfigData: API.DBConfig[]; + setDBConfigData: React.Dispatch>; +} + +export default function DataBaseNodeConfig({ + tableFormRef, + dbConfigData, + setDBConfigData, +}: DataBaseNodeConfigProps) { + const { ocpConfigData, ocpNameIndex, setOcpNameIndex } = useModel('global'); + const { components = {} } = ocpConfigData || {}; + const { oceanbase = {} } = components; + const [editableForm] = ProForm.useForm(); + const [allZoneOBServer, setAllZoneOBServer] = useState({}); + const [allOBServer, setAllOBServer] = useState([]); + const [lastDeleteServer, setLastDeleteServer] = useState(''); + const serverReg = + /^((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])?$/; + + const [editableKeys, setEditableRowKeys] = useState(() => + dbConfigData.map((item) => item.id), + ); + const formatOptions = (data: string[]) => + data?.map((item) => ({ label: item, value: item })); + const nameValidator = ({ field }: any, value: string) => { + const currentId = field.split('.')[0]; + let validtor = true; + const reg = /^[a-zA-Z]([a-zA-Z0-9_]{0,30})[a-zA-Z0-9]$/; + if (value) { + if (reg.test(value)) { + dbConfigData.some((item) => { + if (currentId !== item.id && item.name === value) { + validtor = false; + return true; + } + return false; + }); + } else { + return Promise.reject( + new Error( + intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.DataBaseNodeConfig.ItStartsWithALetter', + defaultMessage: + '以英文字母开头,英文或数字结尾,可包含英文数字和下划线且长度在 2-32 个字符之间', + }), + ), + ); + } + } + if (validtor) { + return Promise.resolve(); + } + return Promise.reject( + new Error( + intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.DataBaseNodeConfig.ZoneNameAlreadyOccupied', + defaultMessage: 'Zone 名称已被占用', + }), + ), + ); + }; + const serversValidator = (_: any, value: string[], type: string) => { + let validtor = true; + if (value && value.length) { + value.some((item) => { + validtor = serverReg.test(item.trim()); + return !serverReg.test(item.trim()); + }); + } + if (validtor) { + return Promise.resolve(); + } + if (type === 'OBServer') { + return Promise.reject( + new Error( + intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.DataBaseNodeConfig.EnterTheCorrectIpAddress', + defaultMessage: '请输入正确的 IP 地址', + }), + ), + ); + } else { + return Promise.reject( + new Error( + intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.DataBaseNodeConfig.SelectTheCorrectObproxyNode', + defaultMessage: '请选择正确的 OBProxy 节点', + }), + ), + ); + } + }; + + const columns: ProColumns[] = [ + { + title: ( + <> + {intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.DataBaseNodeConfig.ZoneName', + defaultMessage: 'Zone 名称', + })} + + + + + + ), + + dataIndex: 'name', + width: 224, + formItemProps: { + rules: [ + { + required: true, + whitespace: false, + message: intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.DataBaseNodeConfig.ThisItemIsRequired', + defaultMessage: '此项是必填项', + }), + }, + { validator: nameValidator }, + ], + }, + }, + { + title: ( + <> + {intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.DataBaseNodeConfig.ObserverNodes', + defaultMessage: 'OBServer 节点', + })} + + + + + + ), + + dataIndex: 'servers', + formItemProps: { + rules: [ + { + required: true, + message: intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.DataBaseNodeConfig.ThisItemIsRequired', + defaultMessage: '此项是必填项', + }), + }, + { + validator: (_: any, value: string[]) => + serversValidator(_, value, 'OBServer'), + }, + ], + }, + renderFormItem: (_: any, { isEditable, record }: any) => { + return isEditable ? ( + + ) : null; + }, + }, + { + title: ( + <> + {intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.DataBaseNodeConfig.RootserverNodes', + defaultMessage: 'RootServer 节点', + })} + + + + + + ), + + dataIndex: 'rootservice', + formItemProps: { + rules: [ + { + required: true, + message: intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.DataBaseNodeConfig.ThisOptionIsRequired', + defaultMessage: '此项是必选项', + }), + }, + { + pattern: serverReg, + message: intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.DataBaseNodeConfig.SelectTheCorrectRootserverNode', + defaultMessage: '请选择正确的 RootServer 节点', + }), + }, + ], + }, + width: 224, + renderFormItem: (_: any, { isEditable, record }: any) => { + // rootservice options are items entered by the OBServer + const options = record?.servers ? formatOptions(record?.servers) : []; + return isEditable ? ( + form.validateFields([['ocpserver', 'servers']])} + onChange={selectChange} + /> + + + + ); +} diff --git a/web/src/component/MetaDBConfig/OBProxyConfig.tsx b/web/src/component/MetaDBConfig/OBProxyConfig.tsx new file mode 100644 index 0000000..46c1d9c --- /dev/null +++ b/web/src/component/MetaDBConfig/OBProxyConfig.tsx @@ -0,0 +1,261 @@ +import { intl } from '@/utils/intl'; +import { ProCard, ProForm, ProFormSelect } from '@ant-design/pro-components'; +import { useState } from 'react'; +import { RightOutlined, DownOutlined } from '@ant-design/icons'; +import { FormInstance } from 'antd/lib/form'; +import { Row, Input, Space } from 'antd'; +import { useModel } from 'umi'; + +import useRequest from '@/utils/useRequest'; +import styles from './indexZh.less'; +import { getErrorInfo } from '@/utils'; +import Parameter from '@/pages/Obdeploy/ClusterConfig/Parameter'; +import { queryComponentParameters } from '@/services/ob-deploy-web/Components'; +import ConfigTable from '@/pages/Obdeploy/ClusterConfig/ConfigTable'; +import InputPort from '../InputPort'; +import { componentsConfig } from '@/pages/constants'; +import { ocpServersValidator } from '@/utils'; +import { showConfigKeys } from '@/constant/configuration'; +import { componentVersionTypeToComponent } from '@/pages/constants'; +import { obproxyAddonAfter } from '@/constant/configuration'; +export default function OBProxyConfig({ form }: { form: FormInstance }) { + const { + ocpConfigData, + proxyMoreConfig, + setProxyMoreConfig, + setErrorVisible, + setErrorsList, + errorsList, + } = useModel('global'); + const { isShowMoreConfig, setIsShowMoreConfig } = useModel('ocpInstallData'); + const { components = {} } = ocpConfigData || {}; + const { obproxy = {} } = components; + const [proxyMoreLoading, setProxyMoreLoading] = useState(false); + const { run: getMoreParamsters } = useRequest(queryComponentParameters); + const getInitialParameters = ( + currentComponent: string, + dataSource: API.MoreParameter[], + data: API.NewParameterMeta[], + ) => { + const currentComponentNameConfig = data?.filter( + (item) => item.component === currentComponent, + )?.[0]; + if (currentComponentNameConfig) { + const parameters: any = {}; + currentComponentNameConfig.configParameter.forEach((item) => { + let parameter = { + ...item, + key: item.name, + params: { + value: item.default, + adaptive: item.auto, + auto: item.auto, + require: item.require, + type: item.type, + }, + }; + dataSource?.some((dataItem) => { + if (item.name === dataItem.key) { + parameter = { + key: dataItem.key, + description: parameter.description, + params: { + ...parameter.params, + ...dataItem, + }, + }; + return true; + } + return false; + }); + if ( + (parameter.params.type === 'CapacityMB' || + parameter.params.type === 'Capacity') && + parameter.params.value == '0' + ) { + parameter.params.value += 'GB'; + } + parameters[item.name] = parameter; + }); + return parameters; + } else { + return undefined; + } + }; + + const formatMoreConfig = (dataSource: API.ParameterMeta[]) => { + return dataSource.map((item) => { + const component = componentVersionTypeToComponent[item.component] + ? componentVersionTypeToComponent[item.component] + : item.component; + const componentConfig = componentsConfig[component]; + // filter out existing parameters + let configParameter = item?.config_parameters.filter((parameter) => { + return !showConfigKeys?.[componentConfig.componentKey]?.includes( + parameter.name, + ); + }); + const newConfigParameter: API.NewConfigParameter[] = configParameter.map( + (parameterItem) => { + return { + ...parameterItem, + parameterValue: { + value: parameterItem.default, + adaptive: parameterItem.auto, + auto: parameterItem.auto, + require: parameterItem.require, + }, + }; + }, + ); + + const result: API.NewParameterMeta = { + ...item, + componentKey: componentConfig.componentKey, + label: componentConfig.labelName, + configParameter: newConfigParameter, + }; + result.configParameter.forEach((item) => { + Object.assign(item.parameterValue, { type: item.type }); + }); + return result; + }); + }; + const getProxyMoreParamsters = async () => { + setProxyMoreLoading(true); + try { + const { success, data } = await getMoreParamsters( + {}, + { + filters: [ + { + component: obproxy?.component, + version: obproxy?.version, + is_essential_only: true, + }, + ], + }, + ); + if (success) { + const newClusterMoreConfig = formatMoreConfig(data?.items); + setProxyMoreConfig(newClusterMoreConfig); + form.setFieldsValue({ + obproxy: { + parameters: getInitialParameters( + obproxy?.component, + obproxy?.parameters, + newClusterMoreConfig, + ), + }, + }); + } + } catch (e: any) { + // aaa TypeError: Cannot read properties of undefined (reading 'setFieldsValue') + setIsShowMoreConfig(false); + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + } + setProxyMoreLoading(false); + }; + + const handleCluserMoreChange = () => { + setIsShowMoreConfig(!isShowMoreConfig); + if (!proxyMoreConfig?.length) { + getProxyMoreParamsters(); + } + }; + return ( + + + + + + + + + {/* + + */} + + + + {obproxyAddonAfter}} /> + +
    + handleCluserMoreChange()} + className={styles.moreConfigText} + > + + {intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.OBProxyConfig.MoreConfigurations', + defaultMessage: '更多配置', + })} + + {!isShowMoreConfig ? : } + +
    + } + showVisible={isShowMoreConfig} + loading={proxyMoreLoading} + /> +
    + ); +} diff --git a/web/src/component/MetaDBConfig/UserConfig.tsx b/web/src/component/MetaDBConfig/UserConfig.tsx new file mode 100644 index 0000000..9e95351 --- /dev/null +++ b/web/src/component/MetaDBConfig/UserConfig.tsx @@ -0,0 +1,278 @@ +import { intl } from '@/utils/intl'; +import { ProForm, ProFormDigit } from '@ant-design/pro-components'; +import { Input, Checkbox, Tooltip } from 'antd'; +import { QuestionCircleOutlined } from '@ant-design/icons'; +import type { FormInstance } from 'antd/lib/form'; +import { useModel } from 'umi'; +import type { CheckboxChangeEvent } from 'antd/es/checkbox'; + +import { commonStyle } from '@/pages/constants'; +import { nameReg } from '@/utils'; +import styles from './indexZh.less'; +import { useState } from 'react'; +import { getTailPath } from '@/utils/helper'; +import { DOCS_USER } from '@/constant/docs'; + +type UserInfoType = { + user?: string; + password?: string; + launch_user?: string; +}; + +export default function UserConfig({ form }: { form: FormInstance }) { + const { useRunningUser, setUseRunningUser, setUsername } = + useModel('ocpInstallData'); + const { ocpConfigData = {} } = useModel('global'); + const { auth = {}, launch_user = '' } = ocpConfigData; + const [userInfo, setUserInfo] = useState({ + ...auth, + launch_user, + }); + const isNewDB = getTailPath() === 'install'; + const onChange = (e: CheckboxChangeEvent) => { + setUseRunningUser(e.target.checked); + if (e.target.checked) { + setUsername(form.getFieldValue('launch_user')); + } else { + if (form.getFieldValue('launch_user')) { + form.setFieldValue('launch_user', undefined); + setUserInfo({ ...userInfo, launch_user: undefined }); + } + if (userInfo.user) { + if (isNewDB) { + form.setFieldValue( + ['obproxy', 'home_path'], + `/home/${userInfo.user}`, + ); + form.setFieldValue( + ['oceanbase', 'home_path'], + `/home/${userInfo.user}`, + ); + } + form.setFieldValue( + ['ocpserver', 'home_path'], + `/home/${userInfo.user}`, + ); + form.setFieldValue( + ['ocpserver', 'log_dir'], + `/home/${userInfo.user}/logs`, + ); + form.setFieldValue( + ['ocpserver', 'soft_dir'], + `/home/${userInfo.user}/software`, + ); + } + setUsername(form.getFieldValue(['auth', 'user'])); + } + }; + + const passwordChange = (e: any) => { + userInfo + ? setUserInfo({ ...userInfo, password: e.target.value }) + : setUserInfo({ password: e.target.value }); + form.setFieldValue(['auth', 'password'], e.target.value); + }; + const userChange = (e: any) => { + userInfo + ? setUserInfo({ ...userInfo, user: e.target.value }) + : setUserInfo({ user: e.target.value }); + form.setFieldValue(['auth', 'user'], e.target.value); + if (!form.getFieldValue('launch_user')) { + let value = ''; + if (e.target.value !== 'root') { + value = `/home/${e.target.value}`; + } else { + value = `/${e.target.value}`; + } + if (isNewDB) { + form.setFieldValue(['obproxy', 'home_path'], value); + form.setFieldValue(['oceanbase', 'home_path'], value); + } + form.setFieldValue(['ocpserver', 'home_path'], value); + form.setFieldValue( + ['ocpserver', 'log_dir'], + `/home/${e.target.value}/logs`, + ); + form.setFieldValue( + ['ocpserver', 'soft_dir'], + `/home/${e.target.value}/software`, + ); + } + setUsername(e.target.value); + }; + + const launchUserChange = (e: any) => { + userInfo + ? setUserInfo({ ...userInfo, launch_user: e.target.value }) + : setUserInfo({ launch_user: e.target.value }); + form.setFieldValue('launch_user', e.target.value); + if (isNewDB) { + form.setFieldValue(['obproxy', 'home_path'], `/home/${e.target.value}`); + form.setFieldValue(['oceanbase', 'home_path'], `/home/${e.target.value}`); + } + form.setFieldValue(['ocpserver', 'home_path'], `/home/${e.target.value}`); + form.setFieldValue( + ['ocpserver', 'log_dir'], + `/home/${e.target.value}/logs`, + ); + form.setFieldValue( + ['ocpserver', 'soft_dir'], + `/home/${e.target.value}/software`, + ); + setUsername(e.target.value); + }; + return ( +
    +

    + {intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.UserConfig.DeployUserConfiguration', + defaultMessage: '部署用户配置', + })} +

    + + + +

    + {intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.UserConfig.PleaseProvideTheHostUser', + defaultMessage: '请提供主机用户名用以自动化配置平台专用操作系统用户', + })} + + + {intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.UserConfig.ViewHelpDocuments', + defaultMessage: '查看帮助文档', + })} + +

    + + + + + + + {intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.UserConfig.UseTheRunningUser', + defaultMessage: '使用运行用户', + })} + + {useRunningUser && ( + + {intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.UserConfig.RunningUsername', + defaultMessage: '运行用户名', + })} + + + + + } + rules={ + useRunningUser + ? [ + { + required: true, + message: intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.UserConfig.EnterARunningUsername', + defaultMessage: '请输入运行用户名', + }), + }, + { + pattern: nameReg, + message: intl.formatMessage({ + id: 'OBD.component.MetaDBConfig.UserConfig.ItStartsWithALetter', + defaultMessage: + '以英文字母开头,可包含英文、数字、下划线和连字符,且不超过32位', + }), + }, + ] + : [] + } + > + + + )} +
    + ); +} diff --git a/web/src/component/MetaDBConfig/helper.ts b/web/src/component/MetaDBConfig/helper.ts new file mode 100644 index 0000000..95edda5 --- /dev/null +++ b/web/src/component/MetaDBConfig/helper.ts @@ -0,0 +1,81 @@ +import { FormInstance } from 'antd'; +/** + * + * @param errorFields 待排序数组 + * @param sortArr 字段顺序 + * @returns + */ +const sortErrorFields = (errorFields: any, sortArr: string[]) => { + let res: any[] = []; + for (let name of sortArr) { + let target; + if (name === 'dbNode') { + target = errorFields.find( + (errorField: any) => !isNaN(parseFloat(errorField.name[0])), + ); + } else { + target = errorFields.find( + (errorField: any) => errorField.name[0] === name, + ); + } + if (target) res.push(target); + } + return res; +}; +/** + * 滚动聚焦于失败项 + */ +const formValidScorllHelper = ( + result: [ + PromiseSettledResult, + PromiseSettledResult, + ], + form: FormInstance, +) => { + let errorFields: any; + const sortErrArr = [ + 'auth', + 'launch_user', + 'ocpserver', + 'dbNode', + 'oceanbase', + 'obproxy', + ]; + if (result[0].status === 'rejected' && result[1].status === 'rejected') { + errorFields = result[0].reason.errorFields.toSpliced( + 2, + 0, + ...result[1].reason.errorFields, + ); + } else { + errorFields = + result[0].status === 'rejected' + ? result[0].reason.errorFields + : result[1].reason.errorFields; + } + //errorFields[0]应该是页面最上方的错误项 因此需要排序 + const sortFields = sortErrorFields(errorFields, sortErrArr); + //数据库节点sortFields[0].name[0])为数字 + if (!isNaN(parseFloat(sortFields[0].name[0]))) { + window.scrollTo(0, 500); + return; + } + form.scrollToField(sortFields[0].name, { + behavior: (actions) => { + actions.forEach(({ el, top, left }) => { + const META_SCROLLTOPS = { + auth: 0, + launch_user: 200, + ocpserver: 400, + oceanbase: 800, + obproxy: 2200, + }; + const scrollTop = META_SCROLLTOPS[sortFields[0].name[0]]; + el.scrollTop = scrollTop !== undefined ? scrollTop : top; + el.scrollLeft = left; + }); + }, + }); +}; + +export { formValidScorllHelper, sortErrorFields }; diff --git a/web/src/component/MetaDBConfig/index.tsx b/web/src/component/MetaDBConfig/index.tsx new file mode 100644 index 0000000..ac7be7b --- /dev/null +++ b/web/src/component/MetaDBConfig/index.tsx @@ -0,0 +1,304 @@ +import { intl } from '@/utils/intl'; +import { Space, Button } from 'antd'; +import { ProCard, ProForm } from '@ant-design/pro-components'; +import { useModel } from 'umi'; +import { useRef, useState } from 'react'; +import type { EditableFormInstance } from '@ant-design/pro-components'; + +import CustomFooter from '../CustomFooter'; +import OBProxyConfig from './OBProxyConfig'; +import ClusterConfig from './ClusterConfig'; +import UserConfig from './UserConfig'; +import NodeConfig from './NodeConfig'; +import DataBaseNodeConfig from './DataBaseNodeConfig'; +import { formValidScorllHelper } from './helper'; +import ExitBtn from '../ExitBtn'; + +interface MetaDBConfig { + setCurrent: React.Dispatch>; + current: number; +} + +interface FormValues extends API.Components { + auth?: { + user?: string; + password?: string; + port?: number; + }; + ocpserver?: { + servers?: string[]; + }; + launch_user?: string; +} + +export const addonAfter = '/oceanbase'; + +export default function MetaDBConfig({ setCurrent, current }: MetaDBConfig) { + const { + ocpConfigData, + setOcpConfigData, + setErrorVisible, + setErrorsList, + ocpClusterMoreConfig, + proxyMoreConfig, + } = useModel('global'); + const { components = {}, auth, launch_user } = ocpConfigData; + const { oceanbase = {}, ocpserver = {}, obproxy = {} } = components; + const initDBConfigData = oceanbase?.topology?.length + ? oceanbase?.topology?.map((item: API.Zone, index: number) => ({ + id: (Date.now() + index).toString(), + ...item, + servers: item?.servers?.map((server) => server?.ip), + })) + : [ + { + id: (Date.now() + 1).toString(), + name: 'zone1', + servers: [], + rootservice: undefined, + }, + { + id: (Date.now() + 2).toString(), + name: 'zone2', + servers: [], + rootservice: undefined, + }, + { + id: (Date.now() + 3).toString(), + name: 'zone3', + servers: [], + rootservice: undefined, + }, + ]; + + const [dbConfigData, setDBConfigData] = + useState(initDBConfigData); + const tableFormRef = useRef>(); + const formatParameters = (dataSource: any) => { + if (dataSource) { + const parameterKeys = Object.keys(dataSource); + return parameterKeys.map((key) => { + const { params, ...rest } = dataSource[key]; + return { + key, + ...rest, + ...params, + }; + }); + } else { + return []; + } + }; + const setData = (dataSource: FormValues) => { + let newAuth = { ...auth, ...dataSource.auth }; + let newComponents: API.Components = { ...components }; + dataSource.oceanbase.home_path; + newComponents.obproxy = { + ...(components.obproxy || {}), + ...dataSource.obproxy, + parameters: formatParameters(dataSource.obproxy?.parameters), + }; + newComponents.ocpserver = { + ...(components.ocpserver || {}), + ...dataSource.ocpserver, + }; + newComponents.oceanbase = { + ...(components.oceanbase || {}), + ...dataSource.oceanbase, + topology: dbConfigData?.map((item) => ({ + ...item, + servers: item?.servers?.map((server) => ({ ip: server })), + })), + parameters: formatParameters(dataSource.oceanbase?.parameters), + }; + let newConfigData = { + ...ocpConfigData, + components: newComponents, + auth: newAuth, + }; + if (dataSource.launch_user) { + newConfigData.launch_user = dataSource.launch_user; + } + setOcpConfigData(newConfigData); + }; + const prevStep = () => { + const formValues = form.getFieldsValue(true); + setData(formValues); + setErrorVisible(false); + setErrorsList([]); + setCurrent(current - 1); + }; + + const nextStep = () => { + const tableFormRefValidate = () => { + return tableFormRef?.current?.validateFields().then((values) => { + return values; + }); + }; + + const formValidate = () => { + return form.validateFields().then((values) => { + return values; + }); + }; + + Promise.allSettled([formValidate(), tableFormRefValidate()]) + .then((result) => { + if ( + result[0].status === 'rejected' || + result[1].status === 'rejected' + ) { + formValidScorllHelper(result,form); + return; + } + const formValues = result[0].value; + setData(formValues); + setCurrent(current + 1); + setErrorVisible(false); + setErrorsList([]); + window.scrollTo(0, 0); + }) + }; + + const [form] = ProForm.useForm(); + const getInitialParameters = ( + currentComponent: string, + dataSource: API.MoreParameter[], + data: API.NewParameterMeta[], + ) => { + const currentComponentNameConfig = data?.filter( + (item) => item.component === currentComponent, + )?.[0]; + if (currentComponentNameConfig) { + const parameters: any = {}; + currentComponentNameConfig.configParameter.forEach((item) => { + let parameter = { + ...item, + key: item.name, + params: { + value: item.default, + adaptive: item.auto, + auto: item.auto, + require: item.require, + type: item.type, + }, + }; + dataSource?.some((dataItem) => { + if (item.name === dataItem.key) { + parameter = { + key: dataItem.key, + description: parameter.description, + params: { + ...parameter.params, + ...dataItem, + }, + }; + return true; + } + return false; + }); + if ( + (parameter.params.type === 'CapacityMB' || + parameter.params.type === 'Capacity') && + parameter.params.value == '0' + ) { + parameter.params.value += 'GB'; + } + parameters[item.name] = parameter; + }); + return parameters; + } else { + return []; + } + }; + const initialValues: FormValues = { + auth: { + user: auth?.user || undefined, + password: auth?.password || undefined, + port: auth?.port || 22, + }, + ocpserver: { + servers: ocpserver?.servers?.length ? ocpserver?.servers : undefined, + }, + oceanbase: { + root_password: oceanbase?.root_password || undefined, + data_dir: oceanbase?.data_dir || '/data/1', + redo_dir: oceanbase?.redo_dir || '/data/log1', + mysql_port: oceanbase?.mysql_port || 2881, + rpc_port: oceanbase?.rpc_port || 2882, + home_path: oceanbase?.home_path || '/home/admin', + parameters: getInitialParameters( + oceanbase?.component, + oceanbase?.parameters, + ocpClusterMoreConfig, + ), + }, + obproxy: { + servers: obproxy?.servers?.length ? obproxy?.servers : undefined, + listen_port: obproxy?.listen_port || 2883, + prometheus_listen_port: obproxy?.prometheus_listen_port || 2884, + home_path: obproxy?.home_path || '/home', + parameters: getInitialParameters( + obproxy?.component, + obproxy?.parameters, + proxyMoreConfig, + ), + }, + launch_user: launch_user || undefined, + }; + + return ( + + + + + + + + + + + + + + + + + + ); +} diff --git a/web/src/component/MetaDBConfig/indexEn.less b/web/src/component/MetaDBConfig/indexEn.less new file mode 100644 index 0000000..e69de29 diff --git a/web/src/component/MetaDBConfig/indexZh.less b/web/src/component/MetaDBConfig/indexZh.less new file mode 100644 index 0000000..690c8f3 --- /dev/null +++ b/web/src/component/MetaDBConfig/indexZh.less @@ -0,0 +1,85 @@ +@subTitleColor: #5c6b8a; +.userConfigContainer { + :global { + .ant-form-item { + margin-bottom: 0px; + } + .ant-col { + padding: 0 !important; + } + } + .descText { + margin-top: 8px; + margin-bottom: 16px; + margin-left: 4px; + color: #8592ad; + font-weight: 400; + font-size: 14px; + line-height: 22px; + letter-spacing: 0; + } +} + +.nodeEditabletable { + :global { + .ant-table, + .ant-table-wrapper .ant-table-thead > tr > th, + .ant-table-thead > tr > th { + background-color: rgba(0, 0, 0, 0) !important; + } + .ant-table { + color: #132039 !important; + } + .ant-table-thead > tr > th { + color: @subTitleColor !important; + font-weight: normal !important; + border: none; + } + .ant-table-thead > tr > th::before { + display: none; + } + .ant-table-tbody > tr > td, + .ant-table-thead > tr > th { + padding-left: 0 !important; + } + .ant-pro-card-body { + padding: 0; + } + } +} + +.titleText { + color: #132039; + font-weight: 500; + font-size: 16px; + line-height: 24px; + letter-spacing: 0; + text-align: left; +} + +.passwordInput { + display: flex; + align-items: flex-end; + :global { + .ant-col-xs-24 { + flex: 0 0 0; + } + } +} + +.moreConfigText { + color: #5c6b8a; + cursor: pointer; +} +.moreConfigText > span { + margin-right: 8px; +} + +.clusterContainer { + margin-top: 24px; + :global { + .ant-col { + padding: 0 !important; + } + } +} diff --git a/web/src/component/ModifyOCPResourcePoolModal/index.tsx b/web/src/component/ModifyOCPResourcePoolModal/index.tsx new file mode 100644 index 0000000..6b9251b --- /dev/null +++ b/web/src/component/ModifyOCPResourcePoolModal/index.tsx @@ -0,0 +1,435 @@ +import { intl } from '@/utils/intl'; +import { Row, Col, Form, Modal, Card, Spin } from '@oceanbase/design'; +import React, { useEffect, useState } from 'react'; +// import { Pie } from '@alipay/ob-charts'; +import { useRequest } from 'ahooks'; +import { Alert } from 'antd'; +import { errorHandler } from '@/utils'; +import * as OCP from '@/services/ocp_installer_backend/OCP'; +import SliderAndInputNumber from '@/component/SliderAndInputNumber'; +import { find } from 'lodash'; + +export interface ModifyResourcePoolModalProps { + currentOcpDeploymentConfig?: any; + createOCPDeployment: (params) => void; + monitorDisplay?: boolean; + visible?: boolean; + loading?: boolean; + id: number; +} + +const ModifyResourcePoolModal: React.FC = ({ + currentOcpDeploymentConfig, + createOCPDeployment, + monitorDisplay, + loading, + visible, + id, + ...restProps +}) => { + const [form] = Form.useForm(); + const { validateFields, setFieldsValue } = form; + + // OCP-SERVER + const [ocpCpuFree, setOcpCpuFree] = useState(1); + const [ocpMemoryFree, setOcpMemoryFree] = useState(1); + + // 剩余cpu + const [cpu_Free, setCpu_Free] = useState(10); + // // 剩余内存 + const [memory_Free, setMemory_Free] = useState(10); + + // 其他已使用内存 + const [otherUsedMemory, setOtherUsedMemory] = useState(1); + + // 剩余cpu + const [cpuFree, setCpuFree] = useState(1); + // 剩余内存 + const [memoryFree, setMemoryFree] = useState(1); + + // OCP 租户 + const [ocpTenantCpuFree, setOcpTenantCpuFree] = useState(2); + const [ocpTenantMemoryFree, setOcpTenantMemoryFree] = useState(4); + + // 原信息租户 + const [tenantCpuFree, setTenantCpuFree] = useState(2); + const [tenantMemoryFree, setTenantMemoryFree] = useState(4); + + // 监控数据租户 + const [monitorCpuFree, setMonitorCpuFree] = useState(4); + const [monitorMemory, setMonitorMemory] = useState(8); + + // 查询主机的资源 + const { + data: resourceData, + run: getOcpDeploymentResource, + loading: getOcpDeploymentResourceLoading, + } = useRequest(OCP.getOcpDeploymentResource, { + manual: true, + onSuccess: (res) => { + if (res.success) { + const ocpDeploymentResource = res?.data || {}; + const { cpu_free, memory_free, memory_total } = + ocpDeploymentResource?.metadb?.servers?.length > 0 + ? ocpDeploymentResource?.metadb?.servers[0] + : {}; + + setCpu_Free(cpu_free); + setMemory_Free(memory_free); + setOcpCpuFree(cpu_free); + setOcpMemoryFree(memory_free > 5 ? 5 : 1); + setOtherUsedMemory(memory_total - memory_free); + setCpuFree(cpu_free > 7 ? cpu_free - 7 : cpu_free); + setMemoryFree(memory_free - (memory_free > 5 ? 13 : 14)); + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }); + const ocpResource = resourceData?.data; + + useEffect(() => { + // 如果用户如有上次的手动输入,需要采用用户输入 + if (currentOcpDeploymentConfig?.id) { + const { meta_tenant, monitor_tenant, parameters } = + currentOcpDeploymentConfig?.config; + setFieldsValue({ + ocpMemory: + find(parameters, (item) => item?.name === 'memory_size')?.value || 1, + ocpCPU: find(parameters, (item) => item?.name === 'ocpCPU')?.value || 1, + tenantCPU: meta_tenant?.resource?.cpu || 2, + tenantMemory: meta_tenant?.resource?.memory || 3, + monitorCPU: monitor_tenant?.resource?.cpu || 4, + monitorMemory: monitor_tenant?.resource?.memory || 8, + }); + } + }, [currentOcpDeploymentConfig?.id]); + + useEffect(() => { + if (id && visible) { + getOcpDeploymentResource({ id }); + } + }, [id, visible]); + + const handleSubmit = () => { + validateFields().then((values) => { + if (createOCPDeployment) { + createOCPDeployment(values); + } + }); + }; + + const resourceList = [ + { + type: intl.formatMessage({ + id: 'OBD.component.ModifyOCPResourcePoolModal.OcpServerMemory', + defaultMessage: 'OCP-Server 内存', + }), + value: ocpMemoryFree, + }, + ...(!monitorDisplay + ? [ + { + type: intl.formatMessage({ + id: 'OBD.component.ModifyOCPResourcePoolModal.OcpTenantMemory', + defaultMessage: 'OCP 租户内存', + }), + value: ocpTenantMemoryFree, + }, + ] + : [ + { + type: intl.formatMessage({ + id: 'OBD.component.ModifyOCPResourcePoolModal.MetadataTenantMemory', + defaultMessage: '元信息租户 内存', + }), + value: tenantMemoryFree, + }, + { + type: intl.formatMessage({ + id: 'OBD.component.ModifyOCPResourcePoolModal.MonitorDataTenantMemory', + defaultMessage: '监控数据租户内存', + }), + value: monitorMemory, + }, + ]), + + { + type: intl.formatMessage({ + id: 'OBD.component.ModifyOCPResourcePoolModal.OtherUsedMemory', + defaultMessage: '其他已使用内存', + }), + value: otherUsedMemory, + }, + { + type: intl.formatMessage({ + id: 'OBD.component.ModifyOCPResourcePoolModal.RemainingMemory', + defaultMessage: '剩余内存', + }), + value: memoryFree, + }, + ]; + + const config1 = { + data: resourceList, + angleField: 'value', + colorField: 'type', + innerRadius: 0.8, + isDonut: true, + lineWidth: 20, + label: false, + style: { + textAlign: 'center', + fontSize: 14, + }, + }; + + return ( + + + + +
    + +
    + + {/* */} + + + + + + { + setOcpCpuFree(val); + setCpuFree( + cpu_Free - + val - + (monitorDisplay + ? ocpTenantCpuFree + : tenantCpuFree + monitorCpuFree), + ); + }} + /> + + + { + setOcpMemoryFree(val); + setMemoryFree( + memory_Free - + val - + (monitorDisplay + ? ocpTenantMemoryFree + : tenantMemoryFree + monitorMemory), + ); + }} + /> + + + + {/* 当 ./ocp_installer.sh launch 以 -mix 参数启动时,仅展示 OCP 租户,不再区分元信息/监控数据租户,仅通过数据库用户名做访问区分,如图 */} + {!monitorDisplay ? ( + + + + { + setOcpTenantCpuFree(val); + setCpuFree(cpu_Free - val - ocpCpuFree); + }} + /> + + + { + setOcpTenantMemoryFree(val); + setMemoryFree(memory_Free - val - ocpMemoryFree); + }} + /> + + + + ) : ( + <> + + + + { + setTenantCpuFree(val); + setCpuFree( + cpu_Free - val - (ocpCpuFree + monitorCpuFree), + ); + }} + /> + + + { + setTenantMemoryFree(val); + setMemoryFree( + memory_Free - val - (ocpMemoryFree + monitorMemory), + ); + }} + /> + + + + + + + { + setMonitorCpuFree(val); + setCpuFree( + cpu_Free - val - (ocpCpuFree + tenantCpuFree), + ); + }} + /> + + + { + setMonitorMemory(val); + setMemoryFree( + memory_Free - + val - + (ocpMemoryFree + tenantMemoryFree), + ); + }} + /> + + + + + )} + + + + + ); +}; + +export default ModifyResourcePoolModal; diff --git a/web/src/component/MyCard/index.less b/web/src/component/MyCard/index.less new file mode 100644 index 0000000..efaf3e6 --- /dev/null +++ b/web/src/component/MyCard/index.less @@ -0,0 +1,17 @@ +@import '~@oceanbase/design/es/theme/index.less'; + +.card { + .header { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + margin-bottom: 20px; + + .title { + color: @colorText; + font-size: 16px; + font-family: PingFangSC-Medium; + } + } +} diff --git a/web/src/component/MyCard/index.tsx b/web/src/component/MyCard/index.tsx new file mode 100644 index 0000000..afd731d --- /dev/null +++ b/web/src/component/MyCard/index.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import { Card, Spin } from '@oceanbase/design'; +import type { CardProps } from '@oceanbase/design/es/card'; +import styles from './index.less'; + +export interface MyCardProps extends CardProps { + children: React.ReactNode; + title?: React.ReactNode; + extra?: React.ReactNode; + loading?: boolean; + className?: string; + headStyle?: React.CSSProperties; +} + +const MyCard = ({ + children, + title, + extra, + loading = false, + className, + headStyle, + bodyStyle, + ...restProps +}: MyCardProps) => ( + + {(title || extra) && ( +
    + {title && {title}} + {extra && {extra}} +
    + )} +
    + {children} +
    +
    +); + +export default MyCard; diff --git a/web/src/component/MyDrawer/index.tsx b/web/src/component/MyDrawer/index.tsx new file mode 100644 index 0000000..a39fd31 --- /dev/null +++ b/web/src/component/MyDrawer/index.tsx @@ -0,0 +1,97 @@ +import { intl } from '@/utils/intl'; +import type { MouseEvent } from 'react'; +import React from 'react'; +import { Button, Drawer, Space } from '@oceanbase/design'; +import type { ButtonProps } from 'antd/es/button'; +import type { DrawerProps } from 'antd/es/drawer'; +import { isBoolean } from 'lodash'; + +export type EventType = MouseEvent< + HTMLElement, + MouseEvent +>; + +export interface MyDrawerProps extends DrawerProps { + onOk?: (e: EventType) => void; + onCancel?: (e: EventType) => void; + confirmLoading?: boolean; + footer?: React.ReactNode; + extra?: React.ReactNode; + cancelText?: string; + okText?: string; + okButtonProps?: ButtonProps; +} + +const MyDrawer: React.FC = ({ + children, + onClose, + onOk, + onCancel, + cancelText = intl.formatMessage({ + id: 'OBD.component.MyDrawer.Cancel', + defaultMessage: '取消', + }), + okText = intl.formatMessage({ + id: 'OBD.component.MyDrawer.Ok', + defaultMessage: '确定', + }), + okButtonProps, + confirmLoading = false, + footer = true, + extra, + bodyStyle = {}, + ...restProps +}) => { + return ( + + {children} + {(footer || extra) && ( +
    + {extra} + + {isBoolean(footer) ? ( + + + + + ) : ( + footer + )} + +
    + )} +
    + ); +}; + +export default MyDrawer; diff --git a/web/src/component/MyDropdown.tsx b/web/src/component/MyDropdown.tsx new file mode 100644 index 0000000..f973c76 --- /dev/null +++ b/web/src/component/MyDropdown.tsx @@ -0,0 +1,115 @@ +import { intl } from '@/utils/intl'; +import React, { useState, useEffect } from 'react'; +import { Dropdown, Menu } from '@oceanbase/design'; +import { DownOutlined, CaretDownOutlined } from '@ant-design/icons'; +import type { DropDownProps } from 'antd/es/dropdown'; +import { toString } from 'lodash'; +import { ALL } from '@/constant'; +import ContentWithIcon from '@/component/ContentWithIcon'; + +type MenuItem = { + value?: string | number; + label?: string; + [key: string]: any; +}; + +export interface MyDropdownProps extends Omit { + value?: string | number; + // 需要设置默认值优先级使用 defaultMenuKey,使用 value 可能与 menuKey 的 useEffect 的逻辑产生意外的情况 + defaultMenuKey?: string | number; + menuList: MenuItem[]; + showAll?: boolean; + allLabel?: string; + onChange?: (value: number | string) => void; + valueProp?: string; + style?: React.CSSProperties; + className?: string; + // 是否使用实心的图标 + isSolidIcon?: boolean; +} + +const MyDropdown: React.FC = ({ + value, + defaultMenuKey, + menuList = [], + showAll = false, + allLabel, + onChange, + valueProp = 'value', + style = {}, + className, + isSolidIcon = false, + ...restProps +}) => { + const newMenuList = showAll + ? [ + { + value: ALL, + label: + allLabel || + intl.formatMessage({ + id: 'OBD.src.component.MyDropdown.All', + defaultMessage: '全部', + }), + }, + + ...menuList, + ] + : menuList; + + const firstMenuKey = newMenuList && newMenuList[0] && newMenuList[0].value; + + /** + * 需要加上 value,不然设置了 value 未设置 defaultMenuKey 会导致值一直在 firstMenuKey 和 value 死循环 + * 因为 useEffect 里面同时对 menuKey 和 value 进行了设置,首次设置会冲突 + * */ + const realDefaultMenuKey = defaultMenuKey || value; + const [menuKey, setMenuKey] = useState(realDefaultMenuKey || firstMenuKey); + // Dropdown 组件的 menuKey 是 string 类型,value 可能是非 string 类型的值,并且 menuKey 的初始化值可能不是 string 类型,统一转成 string 再做判断 + const menuItem = + newMenuList.find((item) => toString(item.value) === toString(menuKey)) || + {}; + + useEffect(() => { + if (onChange) { + onChange(menuItem[valueProp]); + } + }, [menuKey]); + + useEffect(() => { + if (value) { + // 为了保证 Dropdown 组件的 menuKey 是 string 类型,设置时需要转成 string + setMenuKey(toString(value)); + if (onChange) { + onChange(value); + } + } + }, [value]); + + const menu = ( + { + setMenuKey(key as string); + }} + > + {newMenuList.map((item) => ( + {item.label} + ))} + + ); + + return ( + + + + ); +}; + +export default MyDropdown; diff --git a/web/src/component/MyInput.tsx b/web/src/component/MyInput.tsx new file mode 100644 index 0000000..2b294df --- /dev/null +++ b/web/src/component/MyInput.tsx @@ -0,0 +1,28 @@ +import { intl } from '@/utils/intl'; +import React from 'react'; +import { Input } from '@oceanbase/design'; +import type { InputProps } from 'antd/es/input'; + +interface MyInputProps extends React.FC { + Search: typeof Input.Search; + Password: typeof Input.Password; + TextArea: typeof Input.TextArea; +} + +const MyInput: MyInputProps = (props) => { + return ( + + ); +}; + +MyInput.Search = Input.Search; +MyInput.Password = Input.Password; +MyInput.TextArea = Input.TextArea; + +export default MyInput; diff --git a/web/src/component/MySelect.tsx b/web/src/component/MySelect.tsx new file mode 100644 index 0000000..f3da4fc --- /dev/null +++ b/web/src/component/MySelect.tsx @@ -0,0 +1,23 @@ +import { intl } from '@/utils/intl'; +import React from 'react'; +import { Select } from '@oceanbase/design'; +import type { SelectProps } from 'antd/es/select'; + +const { Option, OptGroup } = Select; + +const MySelect: React.FC> = ({ children, ...restProps }) => ( + +); + +MySelect.Option = Option; +MySelect.OptGroup = OptGroup; + +export default MySelect; diff --git a/web/src/component/NoAuth/index.tsx b/web/src/component/NoAuth/index.tsx new file mode 100644 index 0000000..eaf59d6 --- /dev/null +++ b/web/src/component/NoAuth/index.tsx @@ -0,0 +1,21 @@ +import { intl } from '@/utils/intl'; +import React from 'react'; +import type { EmptyProps } from '@/component/Empty'; +import Empty from '@/component/Empty'; + +type NoAuthProps = EmptyProps; + +export default ({ + image = '/assets/common/no_auth.svg', + title = intl.formatMessage({ + id: 'OBD.component.NoAuth.NoPermissionToView', + defaultMessage: '暂无权限查看', + }), + description = intl.formatMessage({ + id: 'OBD.component.NoAuth.ContactTheAdministratorToActivate', + defaultMessage: '请联系管理员开通权限', + }), + ...restProps +}: NoAuthProps) => ( + +); diff --git a/web/src/component/OCPConfig/index.tsx b/web/src/component/OCPConfig/index.tsx new file mode 100644 index 0000000..976ae39 --- /dev/null +++ b/web/src/component/OCPConfig/index.tsx @@ -0,0 +1,681 @@ +import { intl } from '@/utils/intl'; +import React, { useState, useEffect } from 'react'; +import { Card, Form, Input, Row, Col, Descriptions } from '@oceanbase/design'; +import { some } from 'lodash'; +import { FORM_ITEM_SMALL_LAYOUT, SELECT_TOKEN_SPEARATORS } from '@/constant'; +import MyInput from '@/component/MyInput'; +import Password from '@/component/Password'; +import MySelect from '@/component/MySelect'; +import ContentWithQuestion from '@/component/ContentWithQuestion'; +// import { validatePassword } from '@/utils'; +// import tracert from '@/util/tracert'; +import validator from 'validator'; + +export interface OCPConfigProps { + form: any; + hosts?: string[]; + userInfo?: any; + createOcp?: any; + metadbType?: string; + clusterName?: string; + currentOcpDeploymentConfig: any; +} + +const OCPConfig: React.FC = ({ + form, + hosts, + userInfo, + clusterName, + createOcp, + metadbType = 'new', + currentOcpDeploymentConfig, +}) => { + const { getFieldsValue, setFieldsValue } = form; + const [adminPasswordPassed, setAdminPasswordPassed] = useState(true); + const [tenantPasswordPassed, setTenantPasswordPassed] = useState(true); + const [passed, setPassed] = useState(true); + + const { user } = getFieldsValue(); + + useEffect(() => { + if (userInfo?.username) { + const { home_path } = getFieldsValue(); + + setFieldsValue({ + user: userInfo?.username, + home_path: + !home_path || home_path === `/home/${userInfo?.username || 'root'}` + ? `/home/${userInfo?.username || 'root'}` + : home_path.split('/ocp')[0], + }); + } + + if (currentOcpDeploymentConfig && !createOcp && !user && !clusterName) { + const { + auth, + appname, + // admin_password, + meta_tenant, + monitor_tenant, + servers, + home_path, + server_port, + } = currentOcpDeploymentConfig; + + setFieldsValue({ + hosts: servers || hosts, + user: auth?.user, + // password: auth?.password, + appname: clusterName ? `${clusterName}-OCP` : appname || 'OCP', + // admin_password, + meta_tenant_name: meta_tenant?.name?.tenant_name, + // tenantPassword: meta_tenant?.password, + // monitorPassword: monitor_tenant?.password, + monitor_tenant_name: monitor_tenant?.name?.tenant_name, + home_path: + !home_path || home_path === `/home/${userInfo?.username || 'root'}` + ? `/home/${userInfo?.username || 'root'}` + : home_path.split('/ocp')[0], + server_port: server_port || 8080, + confirmTenantPassword: meta_tenant?.password, + confirmMonitorPassword: monitor_tenant?.password, + }); + } else if (hosts) { + setFieldsValue({ + hosts, + }); + } + }, [ + currentOcpDeploymentConfig, + createOcp, + hosts, + clusterName, + userInfo?.username, + ]); + + const validateConfirmTenantPassword = (rule, value, callback) => { + const { tenantPassword } = getFieldsValue(); + if (value && value !== tenantPassword) { + callback( + intl.formatMessage({ + id: 'OBD.component.OCPConfig.ThePasswordsEnteredTwiceAre', + defaultMessage: '两次输入的密码不一致,请重新输入', + }), + ); + } else { + callback(); + } + }; + + const validateConfirmMonitorPassword = (rule, value, callback) => { + const { monitorPassword } = getFieldsValue(); + if (value && value !== monitorPassword) { + callback( + intl.formatMessage({ + id: 'OBD.component.OCPConfig.ThePasswordsEnteredTwiceAre', + defaultMessage: '两次输入的密码不一致,请重新输入', + }), + ); + } else { + callback(); + } + }; + + const validate = (rule, values: any[], callback) => { + if ( + values && + some( + values, + (item) => + // ipv4 地址 + !validator.isIP(item, '4'), + ) + ) { + callback( + intl.formatMessage({ + id: 'OBD.component.OCPConfig.InvalidIpAddress', + defaultMessage: 'IP 地址不合法', + }), + ); + + return; + } + callback(); + }; + + const onFinish = (values) => { + }; + + return ( +
    + + {metadbType === 'old' && ( +
    + + + + + + + + + {intl.formatMessage({ + id: 'OBD.component.OCPConfig.IfYouHaveSetPassword', + defaultMessage: '如果您已设置免密,请忽略本选项', + })} + + } + > + + + + + )} + + + + {intl.formatMessage({ + id: 'OBD.component.OCPConfig.OcpServiceConfiguration', + defaultMessage: 'OCP 服务配置', + })} + + ) : ( +
    + {intl.formatMessage({ + id: 'OBD.component.OCPConfig.ServiceConfiguration', + defaultMessage: '服务配置', + })} +
    + ) + } + > + {metadbType === 'new' && ( + + + + )} + + + + + + } + rules={[ + { + required: true, + message: intl.formatMessage({ + id: 'OBD.component.OCPConfig.EnterAPassword', + defaultMessage: '请输入密码', + }), + }, + // { + // // 只对新密码进行密码校验,旧密码不做校验,避免老数据密码格式校验不通过时无法修改密码 + // // validator: validatePassword(adminPasswordPassed), + // }, + ]} + {...FORM_ITEM_SMALL_LAYOUT} + > + + + + + + +
    + + + + + + + + + + + + + + + + + {/* */} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default OCPConfig; diff --git a/web/src/component/OCPConfigNew/ResourcePlan.tsx b/web/src/component/OCPConfigNew/ResourcePlan.tsx new file mode 100644 index 0000000..09ce5be --- /dev/null +++ b/web/src/component/OCPConfigNew/ResourcePlan.tsx @@ -0,0 +1,353 @@ +import { intl } from '@/utils/intl'; +import { ProCard, ProFormText, ProFormDigit } from '@ant-design/pro-components'; +import { FormInstance } from 'antd/lib/form'; +import { Alert, Row, Col, message } from 'antd'; +import { useState } from 'react'; +import { useModel } from 'umi'; + +import { generateRandomPassword as generatePassword } from '@/utils'; +import { copyText } from '@/utils/helper'; +import CustomPasswordInput from '../CustomPasswordInput'; +import { resourceMap } from '@/pages/constants'; +import styles from './index.less'; +import { MsgInfoType } from './index'; +interface ResourcePlanProps { + form: FormInstance; + metaMsgInfo: MsgInfoType; + tenantMsgInfo: MsgInfoType; + setTenantMsgInfo: React.Dispatch< + React.SetStateAction + >; + + setMetaMsgInfo: React.Dispatch>; +} + +type ResourceType = { + hosts: number; + cpu: number; + memory: number; +}; + +export default function ResourcePlan({ + form, + metaMsgInfo, + tenantMsgInfo, + setTenantMsgInfo, + setMetaMsgInfo, +}: ResourcePlanProps) { + const { ocpConfigData = {} } = useModel('global'); + const { components = {} } = ocpConfigData; + const { ocpserver = {} } = components; + const { meta_tenant = {}, monitor_tenant = {} } = ocpserver; + const [tenantPassword, setTenantPassword] = useState( + meta_tenant.password || '', + ); + const [monitorPassword, setMonitorPassword] = useState( + monitor_tenant.password || '', + ); + + const handleSetTenantPassword = (password: string) => { + form.setFieldValue(['ocpserver', 'meta_tenant', 'password'], password); + form.validateFields([['ocpserver', 'meta_tenant', 'password']]); + setTenantPassword(password); + }; + + const handleSetMonitorPassword = (password: string) => { + form.setFieldValue(['ocpserver', 'monitor_tenant', 'password'], password); + form.validateFields([['ocpserver', 'monitor_tenant', 'password']]); + setMonitorPassword(password); + }; + + const hostsMapValue = (inputHosts: number, resourceMap: ResourceType[]) => { + let cpuRes, memoryRes; + const { cpu: maxCpu, memory: maxMemory } = + resourceMap[resourceMap.length - 1]; + for (let item of resourceMap) { + if (inputHosts <= item.hosts) { + cpuRes = item.cpu; + memoryRes = item.memory; + break; + } + } + if (!cpuRes) cpuRes = maxCpu; + if (!memoryRes) memoryRes = maxMemory; + return [cpuRes, memoryRes]; + }; + + const handleChangeHosts = (inputHosts: number) => { + const metaDBMap = resourceMap['metaDB'], + monitorDBMap = resourceMap['monitorDB'], + OCPMap = resourceMap['OCP']; + const [metaDBCpu, metaDBMemory] = hostsMapValue(inputHosts, metaDBMap); + const [monitorDBCpu, monitorDBMemory] = hostsMapValue( + inputHosts, + monitorDBMap, + ); + const [_, ocpMemory] = hostsMapValue(inputHosts, OCPMap); + form.setFieldsValue({ + ocpserver: { + memory_size: ocpMemory, + monitor_tenant: { + resource: { + cpu: monitorDBCpu, + memory: monitorDBMemory, + }, + }, + meta_tenant: { + resource: { + cpu: metaDBCpu, + memory: metaDBMemory, + }, + }, + }, + }); + }; + + return ( + + + +

    + {intl.formatMessage({ + id: 'OBD.component.OCPConfigNew.ResourcePlan.YouAreExpectedToNeed', + defaultMessage: '您预计需要管理:', + })} +

    + + handleChangeHosts(inputHosts), + }} + /> + + + {intl.formatMessage({ + id: 'OBD.component.OCPConfigNew.ResourcePlan.Table', + defaultMessage: '台', + })} + + +

    + {intl.formatMessage({ + id: 'OBD.component.OCPConfigNew.ResourcePlan.ResourceConfiguration', + defaultMessage: '资源配置', + })} +

    + + {' '} + + GiB + + {/* + + GIB + */} +

    + {intl.formatMessage({ + id: 'OBD.component.OCPConfigNew.ResourcePlan.MetadataTenantConfiguration', + defaultMessage: '元信息租户配置', + })} +

    + +
    + + + + + + + + + + + VCPUS + + + + GiB + +

    + {intl.formatMessage({ + id: 'OBD.component.OCPConfigNew.ResourcePlan.MonitorDataTenantConfiguration', + defaultMessage: '监控数据租户配置', + })} +

    + +
    + + + + + + + + + + + VCPUS + + + + GiB + + + ); +} diff --git a/web/src/component/OCPConfigNew/ServiceConfig.tsx b/web/src/component/OCPConfigNew/ServiceConfig.tsx new file mode 100644 index 0000000..136aa81 --- /dev/null +++ b/web/src/component/OCPConfigNew/ServiceConfig.tsx @@ -0,0 +1,297 @@ +import { intl } from '@/utils/intl'; +import { ProCard, ProForm, ProFormDigit } from '@ant-design/pro-components'; +import { Input, Tooltip, Button, Row, message, Form } from 'antd'; +import { FormInstance } from 'antd/lib/form'; +import { + QuestionCircleOutlined, + CheckCircleFilled, + CloseCircleFilled, +} from '@ant-design/icons'; +import { useEffect, useState } from 'react'; +import { useModel, getLocale } from 'umi'; +import { copyText } from '@/utils/helper'; +import { + generateRandomPassword as generatePassword, + passwordRules, + siteReg, +} from '@/utils'; +import styles from './index.less'; +import CustomPasswordInput from '../CustomPasswordInput'; +import { ocpAddonAfter } from '@/constant/configuration'; +import { MsgInfoType } from './index'; + +interface ServiceConfigProps { + form: FormInstance; + adminMsgInfo: MsgInfoType; + setAdminMsgInfo: React.Dispatch< + React.SetStateAction + >; +} + +const multipleNodesDesc = intl.formatMessage({ + id: 'OBD.component.OCPConfigNew.ServiceConfig.WeRecommendThatYouUse', + defaultMessage: + '建议使用负载均衡的地址作为外部访问 OCP 网站的入口, 实现 OCP 服务高可用。如无,您可选择使用 OCP 的节点 IP+端口进行设置,请后续登录 OCP 后进入系统管理->系统参数变更 ocp.site.url(重启生效)', +}); +const locale = getLocale(); + +export default function ServiceConfig({ + form, + adminMsgInfo, + setAdminMsgInfo, +}: ServiceConfigProps) { + const [checkStatus, setCheckStatus] = useState< + 'unchecked' | 'fail' | 'success' + >('unchecked'); + const { ocpConfigData } = useModel('global'); + const { isSingleOcpNode } = useModel('ocpInstallData'); + const { components = {} } = ocpConfigData; + const { ocpserver = {} } = components; + const [adminPassword, setAdminPassword] = useState( + ocpserver.admin_password || '', + ); + + const ip = + form.getFieldValue(['ocpserver', 'servers']) || ocpserver.servers || []; + const defaultSiteUrl = + (ocpserver.ocp_site_url || isSingleOcpNode === true) && ip.length + ? `http://${ip[0]}:8080` + : ''; + const [siteUrl, setSiteUrl] = useState(defaultSiteUrl); + const setPassword = (password: string) => { + form.setFieldValue(['ocpserver', 'admin_password'], password); + form.validateFields([['ocpserver', 'admin_password']]); + setAdminPassword(password); + }; + + const handleCheckSystemUser = () => { + let site = form.getFieldValue(['ocpserver', 'ocp_site_url']); + if (siteReg.test(site)) { + setCheckStatus('success'); + } else { + setCheckStatus('fail'); + } + }; + + const siteUrlChange = (e: any) => { + let { value } = e.target; + setCheckStatus('unchecked'); + setSiteUrl(value); + form.setFieldValue(['ocpserver', 'ocp_site_url'], value); + }; + + useEffect(() => { + if (typeof isSingleOcpNode !== 'undefined' && !ocpserver.ocp_site_url) { + if (isSingleOcpNode && ip.length) { + let url = `http://${ip[0]}:8080`; + setSiteUrl(url); + form.setFieldValue(['ocpserver', 'ocp_site_url'], url); + } else { + setSiteUrl(''); + form.setFieldValue(['ocpserver', 'ocp_site_url'], ''); + } + } + }, [isSingleOcpNode]); + + return ( + + + {intl.formatMessage({ + id: 'OBD.component.OCPConfigNew.ServiceConfig.AdminPassword', + defaultMessage: 'Admin 密码', + })} + + + + + + } + /> + + + {ocpAddonAfter}} /> + + + + + + + + + + + + ocp.site.url + + + + + } + rules={[ + { + required: true, + message: intl.formatMessage({ + id: 'OBD.component.OCPConfigNew.ServiceConfig.EnterOcpSiteUrl', + defaultMessage: '请输入ocp.site.url', + }), + }, + ]} + > +
    +
    +
    + { + form.validateFields([['ocpserver', 'ocp_site_url']]); + }} + // placeholder="例如:http://localhost:8080" + style={{ width: 328 }} + /> + + {checkStatus === 'success' && ( +
    + + + {intl.formatMessage({ + id: 'OBD.component.OCPConfigNew.ServiceConfig.TheCurrentVerificationIsSuccessful', + defaultMessage: '当前校验成功,请进行下一步', + })} + +
    + )} + + {checkStatus === 'fail' && ( +
    + + + {intl.formatMessage({ + id: 'OBD.component.OCPConfigNew.ServiceConfig.TheCurrentVerificationFailedPlease', + defaultMessage: '当前校验失败,请重新输入', + })} + +
    + )} +
    + +
    + {isSingleOcpNode === false && ( +

    {multipleNodesDesc}

    + )} +
    +
    +
    + +
    +
    +
    + ); +} diff --git a/web/src/component/OCPConfigNew/UserConfig.tsx b/web/src/component/OCPConfigNew/UserConfig.tsx new file mode 100644 index 0000000..d27a378 --- /dev/null +++ b/web/src/component/OCPConfigNew/UserConfig.tsx @@ -0,0 +1,14 @@ +import { ProCard } from '@ant-design/pro-components'; +import type { FormInstance } from 'antd/lib/form'; + +import MateDBUserConfig from '../MetaDBConfig/UserConfig'; +import NodeConfig from '../MetaDBConfig/NodeConfig'; + +export default function UserConfig({ form }: { form: FormInstance }) { + return ( + + + + + ); +} diff --git a/web/src/component/OCPConfigNew/index.less b/web/src/component/OCPConfigNew/index.less new file mode 100644 index 0000000..a212d1b --- /dev/null +++ b/web/src/component/OCPConfigNew/index.less @@ -0,0 +1,8 @@ +.titleText { + color: #132039; + font-weight: 500; + font-size: 16px; + line-height: 24px; + letter-spacing: 0; + text-align: left; +} diff --git a/web/src/component/OCPConfigNew/index.tsx b/web/src/component/OCPConfigNew/index.tsx new file mode 100644 index 0000000..537742b --- /dev/null +++ b/web/src/component/OCPConfigNew/index.tsx @@ -0,0 +1,407 @@ +import { intl } from '@/utils/intl'; +import { useRef } from 'react'; +import { ProForm } from '@ant-design/pro-components'; +import { Space, Button, message } from 'antd'; +import { useModel } from 'umi'; +import { useState } from 'react'; + +import ExitBtn from '../ExitBtn'; +import CustomFooter from '../CustomFooter'; +import ResourcePlan from './ResourcePlan'; +import ServiceConfig from './ServiceConfig'; +import UserConfig from './UserConfig'; +import { getTailPath } from '@/utils/helper'; + +type TenantType = { + name: { + tenant_name: string; + }; + password: string; + resource: { + cpu: number; + memory: number; + }; +}; + +interface FormValues extends API.Components { + auth?: { + user?: string; + password?: string; + port: number; + }; + ocpserver?: { + home_path?: string; + log_dir?: string; + soft_dir?: string; + ocp_site_url?: string; + admin_password?: string; + meta_tenant?: TenantType; + monitor_tenant?: TenantType; + memory_size?: number; + port?: number; + servers?: string[]; + manage_info?: { + cluster: number; + tenant: number; + machine: number; + }; + }; + launch_user?: string; +} + +// 无site_url +const rulePath: any[] = [ + ['ocpserver', 'manage_info', 'cluster'], + ['ocpserver', 'manage_info', 'tenant'], + ['ocpserver', 'manage_info', 'machine'], + ['ocpserver', 'memory_size'], + ['ocpserver', 'meta_tenant', 'name', 'tenant_name'], + ['ocpserver', 'meta_tenant', 'password'], + ['ocpserver', 'meta_tenant', 'resource', 'cpu'], + ['ocpserver', 'meta_tenant', 'resource', 'memory'], + ['ocpserver', 'monitor_tenant', 'name', 'tenant_name'], + ['ocpserver', 'monitor_tenant', 'password'], + ['ocpserver', 'monitor_tenant', 'resource', 'cpu'], + ['ocpserver', 'monitor_tenant', 'resource', 'memory'], + ['ocpserver', 'admin_password'], + ['ocpserver', 'home_path'], + ['ocpserver', 'log_dir'], + ['ocpserver', 'soft_dir'], + ['ocpserver', 'port'], +]; +export type MsgInfoType = { + validateStatus: 'success' | 'error'; + errorMsg: string | null; +}; + +// 使用旧的数据库多 OCP部署选择 +export default function OCPConfigNew({ setCurrent, current }: API.StepProp) { + const isUseNewDBRef = useRef(getTailPath() === 'install'); + const isOldDB = getTailPath() === 'configuration' + const { ocpConfigData, setOcpConfigData, setErrorVisible, setErrorsList } = + useModel('global'); + const { useRunningUser, isSingleOcpNode } = useModel('ocpInstallData'); + const { components = {}, auth = {}, launch_user } = ocpConfigData; + const { ocpserver = {} } = components; + const [form] = ProForm.useForm(); + const [adminMsgInfo, setAdminMsgInfo] = useState(); + const [metaMsgInfo, setMetaMsgInfo] = useState(); + const [tenantMsgInfo, setTenantMsgInfo] = useState(); + const user = useRunningUser ? launch_user : auth.user; + const prevStep = () => { + const formValues = form.getFieldsValue(true); + setData(formValues); + setErrorVisible(false); + setErrorsList([]); + setCurrent(current - 1); + }; + const setData = (dataSource: FormValues) => { + let newOcpserver: any = { + ...(ocpserver || {}), + ...dataSource.ocpserver, + }; + let result = { + ...ocpConfigData, + components: { + ...components, + ocpserver: newOcpserver, + }, + }; + if (isOldDB) { + if (dataSource.auth) result.auth = dataSource.auth; + if (dataSource.launch_user) result.launch_user = dataSource.launch_user; + } + setOcpConfigData({ ...result }); + }; + + const validateFields = async (rulePath?: any[]) => { + if ( + adminMsgInfo?.validateStatus === 'error' || + metaMsgInfo?.validateStatus === 'error' || + tenantMsgInfo?.validateStatus === 'error' + ) { + //两种情况会是 error 不符合要求 或者 没有填写 没有填写form.validateFields是可以检测到的 + let errorPromises: Promise[] = []; + if (adminMsgInfo?.validateStatus === 'error') { + errorPromises.push( + Promise.reject({ + errorFields: [ + { + errors: [adminMsgInfo.errorMsg], + name: ['ocpserver', 'admin_password'], + }, + ], + }), + ); + } + if(metaMsgInfo?.validateStatus === 'error'){ + errorPromises.push( + Promise.reject({ + errorFields: [ + { + errors: [metaMsgInfo.errorMsg], + name: ['ocpserver', 'meta_tenant', 'password'], + }, + ], + }), + ); + } + if(tenantMsgInfo?.validateStatus === 'error'){ + errorPromises.push( + Promise.reject({ + errorFields: [ + { + errors: [tenantMsgInfo.errorMsg], + name: ['ocpserver', 'monitor_tenant', 'password'], + }, + ], + }), + ); + } + return Promise.allSettled([...errorPromises,form.validateFields(rulePath)]) + } + return Promise.allSettled([form.validateFields(rulePath)]); + }; + + const sortErrorFields = (errorFields: any, sortArr: string[]) => { + let res: any[] = []; + for (let name of sortArr) { + let target = errorFields.find((errorField: any) => { + if (errorField.name[0] === 'ocpserver') { + return name === errorField.name[1]; + } else { + return name === errorField.name[0]; + } + }); + if (target) res.push(target); + } + return res; + }; + + const formValidScorllHelper = (result:PromiseSettledResult[])=>{ + let errorFields = []; + for(let item of result){ + if(item.status === 'rejected'){ + errorFields.push(...item.reason.errorFields) + } + } + for (let errField of errorFields) { + if (errField.name[1] && errField.name[1] === 'admin_password') { + setAdminMsgInfo({ + validateStatus: 'error', + errorMsg: errField.errors[0], + }); + } + if ( + errField.name[1] === 'meta_tenant' && + errField.name[2] === 'password' + ) { + setMetaMsgInfo({ + validateStatus: 'error', + errorMsg: errField.errors[0], + }); + } + if ( + errField.name[1] === 'monitor_tenant' && + errField.name[2] === 'password' + ) { + setTenantMsgInfo({ + validateStatus: 'error', + errorMsg: errField.errors[0], + }); + } + } + const userBlock = ['auth', 'launch_user', 'servers']; + const serviceBlock = [ + 'admin_password', + 'soft_dir', + 'log_dir', + 'home_path', + 'ocp_site_url', + 'port', + ]; + const resourceBlock = ['manage_info', 'memory_size']; + const tenantBlock = ['meta_tenant', 'monitor_tenant']; + let pathArr = isUseNewDBRef.current + ? [...serviceBlock, ...resourceBlock, ...tenantBlock] + : [...userBlock, ...serviceBlock, ...resourceBlock, ...tenantBlock]; + const sortFields = sortErrorFields(errorFields, pathArr); + form.scrollToField(sortFields[0].name, { + behavior: (actions) => { + actions.forEach(({ el, top, left }) => { + if ( + sortFields[0].name[0] === 'auth' || + sortFields[0].name[1] === 'servers' || + sortFields[0].name[0] === 'launch_user' + ) { + el.scrollTop = 0; + } else if (serviceBlock.includes(sortFields[0].name[1])) { + el.scrollTop = isUseNewDBRef.current ? 0 : 400; + } else if (resourceBlock.includes(sortFields[0].name[1])) { + el.scrollTop = isUseNewDBRef.current ? 400 : 900; + } else if (tenantBlock.includes(sortFields[0].name[1])) { + el.scrollTop = isUseNewDBRef.current ? 800 : 1300; + } + el.scrollLeft = left; + }); + }, + }); + message.destroy(); + } + + const nextStep = async () => { + let validatePromise: Promise; + if (isSingleOcpNode === false) { + validatePromise = validateFields(rulePath); + } else { + validatePromise = validateFields(); + } + validatePromise + .then((result) => { + if(result.find((item:any)=>item.status === 'rejected')) + { + formValidScorllHelper(result) + return + } + setData(result[0].value); + setCurrent(current + 1); + setErrorVisible(false); + setErrorsList([]); + window.scrollTo(0, 0); + }) + }; + let home_path = undefined, + log_dir = undefined, + soft_dir = undefined; + + if (isUseNewDBRef.current) { + let val = launch_user ? launch_user : auth.user; + home_path = launch_user + ? `/home/${launch_user}` + : auth.user === 'root' + ? '/root' + : `/home/${auth.user}`; + log_dir = `/home/${val}/logs`; + soft_dir = `/home/${val}/software`; + } + + let initialValues: FormValues = { + ocpserver: { + home_path: ocpserver?.home_path || home_path, + log_dir: ocpserver?.log_dir || log_dir, + soft_dir: ocpserver?.soft_dir || soft_dir, + port: ocpserver?.port || 8080, + ocp_site_url: ocpserver?.ocp_site_url || undefined, + admin_password: ocpserver?.admin_password || undefined, + memory_size: ocpserver?.memory_size || 4, + meta_tenant: ocpserver?.meta_tenant || { + resource: { + cpu: 2, + memory: 4, + }, + name: { + tenant_name: 'ocp_meta', + }, + }, + monitor_tenant: ocpserver?.monitor_tenant || { + resource: { + cpu: 2, + memory: 8, + }, + name: { + tenant_name: 'ocp_monitor', + }, + }, + manage_info: ocpserver?.manage_info || { + // cluster: 2, + // tenant: 4, + machine: 10, + }, + }, + launch_user: launch_user || undefined, + }; + + if (!isUseNewDBRef.current) { + initialValues = { + ...initialValues, + auth: { + user: auth?.user || undefined, + password: auth?.password || undefined, + port: auth?.port || 22, + }, + ocpserver: { + ...initialValues.ocpserver, + servers: ocpserver?.servers?.length ? ocpserver?.servers : undefined, + }, + launch_user: launch_user || undefined, + }; + rulePath.push( + ...[ + ['auth', 'user'], + ['auth', 'password'], + 'launch_user', + ['ocpserver', 'servers'], + ], + ); + } + + return ( + + + {!isUseNewDBRef.current && } + + + + + + + + + + ); +} diff --git a/web/src/component/OCPLogo.tsx b/web/src/component/OCPLogo.tsx new file mode 100644 index 0000000..bd644d1 --- /dev/null +++ b/web/src/component/OCPLogo.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import { isEnglish } from '@/utils'; + +export interface OCPLogoProps { + onClick?: (e: React.SyntheticEvent) => void; + height?: number; + mode?: 'default' | 'simple'; + style?: React.CSSProperties; + className?: string; +} + +const OCPLogo: React.FC = ({ + mode = 'default', + height = mode === 'default' ? 80 : 24, + style, + ...restProps +}) => { + const logoUrl = isEnglish() + ? '/assets/logo/ocp_express_logo_en.svg' + : '/assets/logo/ocp_express_logo_zh.svg'; + const simpleLogoUrl = isEnglish() + ? '/assets/logo/ocp_express_simple_logo_en.svg' + : '/assets/logo/ocp_express_simple_logo_zh.svg'; + return ( + logo + ); +}; + +export default OCPLogo; diff --git a/web/src/component/OCPPreCheck/CheckInfo/BasicInfo.tsx b/web/src/component/OCPPreCheck/CheckInfo/BasicInfo.tsx new file mode 100644 index 0000000..1033113 --- /dev/null +++ b/web/src/component/OCPPreCheck/CheckInfo/BasicInfo.tsx @@ -0,0 +1,104 @@ +import { intl } from '@/utils/intl'; +import { Row, Col, Tag } from 'antd'; +import { ProCard } from '@ant-design/pro-components'; +import { getLocale } from 'umi'; + +import type { BasicInfoProp } from './type'; +import styles from './index.less'; +import { leftCardStyle } from '.'; +interface BasicInfoProps { + basicInfoProp: BasicInfoProp; +} + +const locale = getLocale(); +export default function BasicInfo({ basicInfoProp }: BasicInfoProps) { + return ( + + + +
    + + + {basicInfoProp.appname} + + + {basicInfoProp.type} + + + + + + + {basicInfoProp.productsInfo.map((versionInfo, idx) => ( + + + + {versionInfo.productName} + {typeof versionInfo.isCommunity !== 'undefined' && ( + + {versionInfo.isCommunity + ? intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.BasicInfo.CommunityEdition', + defaultMessage: '社区版', + }) + : intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.BasicInfo.CommercialEdition', + defaultMessage: '商业版', + })} + + )} + + + V {versionInfo.version} + + + + ))} + + + + + ); +} diff --git a/web/src/component/OCPPreCheck/CheckInfo/ConfigInfo.tsx b/web/src/component/OCPPreCheck/CheckInfo/ConfigInfo.tsx new file mode 100644 index 0000000..ea9a0a4 --- /dev/null +++ b/web/src/component/OCPPreCheck/CheckInfo/ConfigInfo.tsx @@ -0,0 +1,412 @@ +import { intl } from '@/utils/intl'; +import { Row, Col, Tooltip, Space, Table } from 'antd'; +import { ProCard } from '@ant-design/pro-components'; +import type { ConnectInfoPropType } from './type'; +import { componentsConfig } from '@/pages/constants'; +import type { ColumnsType } from 'antd/es/table'; +import styles from './index.less'; +import type { DBNodeType } from './type'; +import PasswordCard from '@/component/PasswordCard'; +import { leftCardStyle } from '.'; +import { + oceanbaseAddonAfter, + obproxyAddonAfter, +} from '@/constant/configuration'; +interface BasicInfo { + isNewDB: boolean; + configInfoProp: ConnectInfoPropType; + oceanbase: any; + obproxy: any; +} +export default function ConfigInfo({ + isNewDB, + configInfoProp, + oceanbase, + obproxy, +}: BasicInfo) { + const { userConfig, ocpNodeConfig, clusterConfig, obproxyConfig, dbNode } = + configInfoProp; + const obConfigInfo = clusterConfig.info; + const obproxyConfigInfo = obproxyConfig.info; + const ObproxyServer = () => ( + <> + {obproxyConfigInfo.servers && + obproxyConfigInfo.servers.map((text: string, idx: number) => ( + + {text} + {idx !== obproxyConfigInfo.servers.length - 1 && <>,}{' '} + + ))} + + ); + + const configInfo = [ + { + key: 'cluster', + group: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ConfigInfo.ClusterConfiguration', + defaultMessage: '集群配置', + }), + content: [ + { + label: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ConfigInfo.RootSysPassword', + defaultMessage: 'root@sys 密码', + }), + colSpan: 5, + value: ( + +
    {obConfigInfo?.root_password}
    +
    + ), + }, + { + label: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ConfigInfo.SoftwarePath', + defaultMessage: '软件路径', + }), + value: ( + +
    + {obConfigInfo?.home_path} + {oceanbaseAddonAfter} +
    +
    + ), + }, + { + label: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ConfigInfo.DataPath', + defaultMessage: '数据路径', + }), + value: ( + +
    {obConfigInfo?.data_dir}
    +
    + ), + }, + { + label: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ConfigInfo.LogPath', + defaultMessage: '日志路径', + }), + value: ( + +
    {obConfigInfo?.redo_dir}
    +
    + ), + }, + { + label: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ConfigInfo.MysqlPort', + defaultMessage: 'mysql 端口', + }), + colSpan: 3, + value: obConfigInfo?.mysql_port, + }, + { + label: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ConfigInfo.RpcPort', + defaultMessage: 'rpc 端口', + }), + colSpan: 3, + value: obConfigInfo?.rpc_port, + }, + ], + + more: oceanbase?.parameters?.length + ? [ + { + label: componentsConfig['oceanbase'].labelName, + parameters: oceanbase?.parameters, + }, + ] + : [], + }, + { + key: 'obproxy', + group: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ConfigInfo.ObproxyConfiguration', + defaultMessage: 'OBProxy 配置', + }), + content: [ + { + label: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ConfigInfo.ObproxyNodes', + defaultMessage: 'OBProxy 节点', + }), + colSpan: 6, + value: ( + } placement="topLeft"> +
    + +
    +
    + ), + }, + { + label: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ConfigInfo.SoftwarePath', + defaultMessage: '软件路径', + }), + colSpan: 6, + value: ( + +
    + {obproxyConfigInfo?.home_path} + {obproxyAddonAfter} +
    +
    + ), + }, + { + label: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ConfigInfo.SqlPort', + defaultMessage: 'SQL 端口', + }), + colSpan: 6, + value: ( + +
    {obproxyConfigInfo?.listen_port}
    +
    + ), + }, + { + label: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ConfigInfo.PortExporter', + defaultMessage: 'Exporter 端口', + }), + colSpan: 6, + value: ( + +
    + {obproxyConfigInfo?.prometheus_listen_port} +
    +
    + ), + }, + ], + + more: obproxy?.parameters?.length + ? [ + { + label: componentsConfig['obproxy'].labelName, + parameters: obproxy?.parameters, + }, + ] + : [], + }, + ]; + + const getMoreColumns = (label: string) => { + const columns: ColumnsType = [ + { + title: label, + dataIndex: 'key', + render: (text) => text, + }, + { + title: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ConfigInfo.ParameterValue', + defaultMessage: '参数值', + }), + dataIndex: 'value', + render: (text, record) => + record.adaptive + ? intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ConfigInfo.AutomaticAllocation', + defaultMessage: '自动分配', + }) + : text || '-', + }, + { + title: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ConfigInfo.Introduction', + defaultMessage: '介绍', + }), + dataIndex: 'description', + render: (text) => ( + +
    {text}
    +
    + ), + }, + ]; + + return columns; + }; + + const dbNodeColums: ColumnsType = [ + { + title: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ConfigInfo.ZoneName', + defaultMessage: 'Zone 名称', + }), + dataIndex: 'name', + }, + { + title: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ConfigInfo.ObServerNodes', + defaultMessage: 'OB Server 节点', + }), + dataIndex: 'servers', + render: (_, record) => ( + <> + {_.map((item: { ip: string }, idx: number) => ( + + {item.ip} + {idx !== _.length - 1 && } + + ))} + + ), + }, + { + title: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ConfigInfo.RootServerNodes', + defaultMessage: 'Root Server 节点', + }), + dataIndex: 'rootservice', + }, + ]; + + return ( + + + +
    + + + {userConfig.user} + + + + {userConfig.port || '-'} + + + + + + + + + {ocpNodeConfig && + ocpNodeConfig.map((server, idx) => ( + + {server} + + ))} + + + + + +
    + + + + {configInfo?.map((item, index) => { + return ( + + + + {item.content.map((subItem) => ( + + {subItem.value} + + ))} + + + {item?.more?.length ? ( + + {item?.more.map((moreItem) => ( + +
    + + ))} + + ) : null} + + ); + })} + + + + + ); +} diff --git a/web/src/component/OCPPreCheck/CheckInfo/ConnectInfo.tsx b/web/src/component/OCPPreCheck/CheckInfo/ConnectInfo.tsx new file mode 100644 index 0000000..a91c659 --- /dev/null +++ b/web/src/component/OCPPreCheck/CheckInfo/ConnectInfo.tsx @@ -0,0 +1,57 @@ +import { intl } from '@/utils/intl'; +import { Row, Col } from 'antd'; +import { ProCard } from '@ant-design/pro-components'; +import styles from './index.less'; +import type { ConnectInfoType } from './type'; + +interface ConnectInfoProps { + connectInfoProp: ConnectInfoType[]; +} +export default function ConnectInfo({ connectInfoProp }: ConnectInfoProps) { + return ( + + + + {connectInfoProp.map((connectInfo, idx) => ( + + + {connectInfo.map((item, _idx) => ( + + {item.value} + + ))} + + + ))} + {/* + + + 111.222.3333 + + + 2882 + + + + + + + root@sys + + + 12345 + + + */} + + + + ); +} diff --git a/web/src/component/OCPPreCheck/CheckInfo/ResourceInfo.tsx b/web/src/component/OCPPreCheck/CheckInfo/ResourceInfo.tsx new file mode 100644 index 0000000..0c1ef26 --- /dev/null +++ b/web/src/component/OCPPreCheck/CheckInfo/ResourceInfo.tsx @@ -0,0 +1,271 @@ +import { intl } from '@/utils/intl'; +import { Row, Col } from 'antd'; +import { ProCard } from '@ant-design/pro-components'; +import type { ResourceInfoPropType } from './type'; +import styles from './index.less'; +import { leftCardStyle } from '.'; +import { ocpAddonAfter } from '@/constant/configuration'; +import PasswordCard from '@/component/PasswordCard'; +interface BasicInfoProps { + isNewDB: boolean; + resourceInfoProp: ResourceInfoPropType; +} + +export default function ResourceInfo({ + isNewDB, + resourceInfoProp, +}: BasicInfoProps) { + const { + serviceConfig, + resourcePlan, + memory_size, + tenantConfig, + monitorConfig, + ocpServer, + userConfig, + } = resourceInfoProp; + const serviceMap: any = { + admin_password: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ResourceInfo.AdminPassword', + defaultMessage: 'Admin密码', + }), + home_path: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ResourceInfo.SoftwarePath', + defaultMessage: '软件路径', + }), + log_dir: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ResourceInfo.LogPath', + defaultMessage: '日志路径', + }), + soft_dir: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.ResourceInfo.PackagePath', + defaultMessage: '软件包路径', + }), + ocp_site_url: 'ocp.site.url', + }; + return ( + + + {!isNewDB && userConfig && ( + + + + + {userConfig.user} + + + + {userConfig.port || '-'} + + + + + )} + + {!isNewDB && ocpServer && ( + + + + {ocpServer.map((server, idx) => ( + + {server} + + ))} + + + + )} + + + + + + {serviceConfig && + Object.keys(serviceConfig).map((key, idx) => ( + + {key === 'home_path' + ? `${serviceConfig[key]}${ocpAddonAfter}` + : `${serviceConfig[key]}`} + + ))} + + + + + + + + {/* + {resourcePlan.cluster} + + + {resourcePlan.tenant} + */} + + {resourcePlan.machine} + + + + + + + + + {memory_size} GiB + + + + + + + + + + {tenantConfig.info.tenant_name} + + + {tenantConfig.info.password} + + + + + + + {tenantConfig.resource.cpu} VCPUS + + + {tenantConfig.resource.memory} GiB + + + + + + + + + + + {monitorConfig.info.tenant_name} + + + {monitorConfig.info.password} + + + + + + + {monitorConfig.resource.cpu} VCPUS + + + {monitorConfig.resource.memory} GiB + + + + + + + + ); +} diff --git a/web/src/component/OCPPreCheck/CheckInfo/index.less b/web/src/component/OCPPreCheck/CheckInfo/index.less new file mode 100644 index 0000000..4242628 --- /dev/null +++ b/web/src/component/OCPPreCheck/CheckInfo/index.less @@ -0,0 +1,82 @@ +@cardBackgroundColor: #f8fafe; +@subTitleColor: #5c6b8a; + +.pageCard { + box-shadow: 0 2px 4px 0 rgba(19, 32, 57, 0.02), + 0 1px 6px -1px rgba(19, 32, 57, 0.02), 0 1px 2px 0 rgba(19, 32, 57, 0.03); + :global { + .ant-space-item { + .ant-col { + padding-right: 0 !important; + padding-left: 0 !important; + } + } + } + .dbTable { + :global { + .ant-table-tbody > tr > td { + border-bottom: 1px solid #e2e8f3 !important; + } + .ant-table-tbody > tr > td, + .ant-table-thead > tr > th { + background-color: #f5f8fe !important; + } + .ant-table-tbody > tr:last-child > td { + border: none !important; + } + .ant-table-tbody > tr:last-child > td:first-child { + border-bottom-left-radius: 8px !important; + } + .ant-table-tbody > tr:last-child > td:last-child { + border-bottom-right-radius: 8px !important; + } + } + } +} +.infoSubCard { + overflow: hidden; + border-radius: 8px; + .pwdIcon { + position: absolute; + top: 2px; + right: 0; + color: #8592ad; + font-size: 17px; + } + .versionTag{ + position: absolute; + right: 45px; + } + :global { + .ant-pro-card .ant-pro-card-body { + padding-top: 4px !important; + } + + .ant-pro-card-body, + .ant-pro-card-header { + background-color: @cardBackgroundColor !important; + } + .ant-pro-card-title { + color: @subTitleColor !important ; + font-weight: normal !important; + font-size: 14px !important; + } + .ant-pro-card-body { + color: #132039 !important; + } + .ant-pro-card-col.ant-pro-card-split-vertical { + border-inline-end: none !important; + .ant-pro-card::before { + position: absolute; + top: 50%; + width: 1px; + height: 48px; + background-color: #e8eaf3; + transform: translateY(-50%); + transition: #e8eaf3 0.3s; + content: ''; + inset-inline-end: 0; + } + } + } +} diff --git a/web/src/component/OCPPreCheck/CheckInfo/index.tsx b/web/src/component/OCPPreCheck/CheckInfo/index.tsx new file mode 100644 index 0000000..17ecee7 --- /dev/null +++ b/web/src/component/OCPPreCheck/CheckInfo/index.tsx @@ -0,0 +1,258 @@ +import { intl } from '@/utils/intl'; +import { Button, Space, Alert, Row, Col } from 'antd'; +import { ProCard } from '@ant-design/pro-components'; +import { useModel } from 'umi'; +import useRequest from '@/utils/useRequest'; +import { getErrorInfo } from '@/utils'; +import { createOcpDeploymentConfig } from '@/services/ocp_installer_backend/OCP'; +import CustomFooter from '../../CustomFooter'; +import BasicInfo from './BasicInfo'; +import ConfigInfo from './ConfigInfo'; +import ConnectInfo from './ConnectInfo'; +import ResourceInfo from './ResourceInfo'; +import ExitBtn from '@/component/ExitBtn'; +import { formatPreCheckData } from '../helper'; +import styles from '../index.less'; +import type { + BasicInfoProp, + ProductInfoType, + ConnectInfoType, + ConnectInfoPropType, + ResourceInfoPropType, +} from './type'; + +interface CheckInfoProps { + showNext: React.Dispatch>; + isNewDB: boolean; +} + +export const leftCardStyle = { width: 211 }; + +export default function CheckInfo({ + showNext, + current, + setCurrent, + isNewDB, +}: CheckInfoProps & API.StepProp) { + const { ocpConfigData, setErrorVisible, setErrorsList, errorsList } = + useModel('global'); + const { setConnectId, obVersionInfo, ocpVersionInfo, obproxyVersionInfo } = + useModel('ocpInstallData'); + const { components = {}, auth = {} } = ocpConfigData; + const { oceanbase = {}, obproxy = {}, ocpserver = {} } = components; + const basicInfoProp: BasicInfoProp = { + appname: oceanbase.appname, + type: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.InstallAll', + defaultMessage: '全部安装', + }), + productsInfo: [ + { + productName: 'OCP', + version: ocpserver.version, + isCommunity: ocpVersionInfo?.versionType === 'ce', + }, + ], + }; + const configInfoProp: ConnectInfoPropType = { + userConfig: { ...auth }, + ocpNodeConfig: ocpserver.servers, + clusterConfig: { + info: { + root_password: oceanbase.root_password, + home_path: oceanbase.home_path, + data_dir: oceanbase.data_dir, + redo_dir: oceanbase.redo_dir, + mysql_port: oceanbase.mysql_port, + rpc_port: oceanbase.rpc_port, + }, + }, + dbNode: oceanbase.topology, + obproxyConfig: { + info: { + servers: obproxy.servers, + home_path: obproxy.home_path, + listen_port: obproxy.listen_port, + prometheus_listen_port: obproxy.prometheus_listen_port, + }, + }, + }; + const connectInfoProp: ConnectInfoType[] = [ + [ + { + label: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.HostIp', + defaultMessage: '主机IP', + }), + value: ocpserver?.metadb?.host, + }, + { + label: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.AccessPort', + defaultMessage: '访问端口', + }), + value: ocpserver?.metadb?.port, + }, + ], + + [ + { + label: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.AccessAccount', + defaultMessage: '访问账号', + }), + value: ocpserver?.metadb?.user, + }, + { + label: intl.formatMessage({ + id: 'OBD.OCPPreCheck.CheckInfo.Password', + defaultMessage: '密码', + }), + value: ocpserver?.metadb?.password, + }, + ], + ]; + + const resourceInfoProp: ResourceInfoPropType = { + serviceConfig: { + admin_password: ocpserver.admin_password, + home_path: ocpserver.home_path, + log_dir: ocpserver.log_dir, + soft_dir: ocpserver.soft_dir, + ocp_site_url: ocpserver.ocp_site_url, + }, + resourcePlan: { ...ocpserver.manage_info }, + memory_size: ocpserver.memory_size, + tenantConfig: { + info: { + tenant_name: ocpserver?.meta_tenant?.name?.tenant_name, + password: ocpserver?.meta_tenant?.password, + }, + resource: { ...ocpserver?.meta_tenant?.resource }, + }, + monitorConfig: { + info: { + tenant_name: ocpserver?.monitor_tenant?.name?.tenant_name, + password: ocpserver?.monitor_tenant?.password, + }, + resource: { ...ocpserver?.monitor_tenant?.resource }, + }, + }; + if (isNewDB) { + let extraProducts: ProductInfoType[] = [ + { + productName: 'OceanBase', + version: oceanbase.version, + isCommunity: obVersionInfo?.versionType === 'ce', + }, + { + productName: 'OBProxy', + version: obproxy.version, + }, + ]; + + basicInfoProp.productsInfo.push(...extraProducts); + } + if (!isNewDB) { + resourceInfoProp.userConfig = { ...auth }; + resourceInfoProp.ocpServer = ocpserver.servers; + } + const { run: handleCreateConfig, loading } = useRequest( + createOcpDeploymentConfig, + { + onSuccess: ({ success, data }: API.OBResponse) => { + if (success) { + setConnectId(data); + showNext(true); + } + }, + onError: (e: any) => { + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }, + ); + + const nextStep = () => { + handleCreateConfig( + { name: oceanbase?.appname }, + formatPreCheckData(ocpConfigData), + ); + }; + const prevStep = () => { + setCurrent(current - 1); + }; + return ( + + + + + + + + + {!isNewDB ? ( + + ) : ( + + )} + + + + + + + + + + + + + + ); +} diff --git a/web/src/component/OCPPreCheck/CheckInfo/type.ts b/web/src/component/OCPPreCheck/CheckInfo/type.ts new file mode 100644 index 0000000..643bd61 --- /dev/null +++ b/web/src/component/OCPPreCheck/CheckInfo/type.ts @@ -0,0 +1,78 @@ +export type BasicInfoProp = { + appname: string; + type: string; + productsInfo: ProductInfoType[]; +}; + +export type ProductInfoType = { + productName: string; + version: string; + isCommunity?: boolean; +}; + +export type DBNodeType = { + id?: string; + name: string; + rootservice: string; + servers: string[]; +}; + +export type ConnectInfoType = { label: string; value: string }[]; + +export type ConnectInfoPropType = { + userConfig: { user: string; password: string; port: number }; + ocpNodeConfig: string[]; + dbNode: DBNodeType[]; + clusterConfig: { + info: { + root_password: string; + home_path: string; + data_dir: string; + redo_dir: string; + mysql_port: number; + rpc_port: number; + }; + more?: any; + }; + obproxyConfig: { + info: { + servers: string[]; + home_path: string; + listen_port: number; + prometheus_listen_port: number; + }; + more?: any; + }; +}; + +export type ResourceInfoPropType = { + userConfig?: { user: string; password: string; port: number }; + serviceConfig: { + admin_password: string; + home_path: string; + log_dir: string; + soft_dir: string; + ocp_site_url: string; + }; + resourcePlan: { + cluster: number; + tenant: number; + machine: number; + }; + memory_size: string; + tenantConfig: { + info: { + tenant_name: string; + password: string; + }; + resource: { cpu: number; memory: number }; + }; + monitorConfig: { + info: { + tenant_name: string; + password: string; + }; + resource: { cpu: number; memory: number }; + }; + ocpServer?: string[]; +}; diff --git a/web/src/component/OCPPreCheck/PreCheck/index.tsx b/web/src/component/OCPPreCheck/PreCheck/index.tsx new file mode 100644 index 0000000..c468fe8 --- /dev/null +++ b/web/src/component/OCPPreCheck/PreCheck/index.tsx @@ -0,0 +1,826 @@ +import { intl } from '@/utils/intl'; +import { useEffect, useState } from 'react'; +import { useModel } from 'umi'; +import { + Space, + Button, + Progress, + Timeline, + Checkbox, + Typography, + Tooltip, + Tag, + Spin, + message, + Empty, +} from 'antd'; +import { ProCard } from '@ant-design/pro-components'; +import { + CloseOutlined, + QuestionCircleFilled, + ReadFilled, + CheckCircleFilled, + CloseCircleFilled, +} from '@ant-design/icons'; +import * as OCP from '@/services/ocp_installer_backend/OCP'; +import customRequest from '@/utils/useRequest'; +import { useRequest } from 'ahooks'; +import { + deployAndStartADeployment, + createDeploymentConfig, +} from '@/services/ob-deploy-web/Deployments'; +import { handleQuit, getErrorInfo, errorHandler } from '@/utils'; +import CustomFooter from '../../CustomFooter'; +import ExitBtn from '@/component/ExitBtn'; +import NP from 'number-precision'; +import { getLocale } from 'umi'; +import ZhStyles from '@/pages/Obdeploy/indexZh.less'; +import EnStyles from '@/pages/Obdeploy/indexEn.less'; + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; + +const { Text } = Typography; + +const statusColorConfig = { + PASSED: 'green', + PENDING: 'gray', + FAILED: 'red', +}; + +let timerScroll: NodeJS.Timer; +let timerFailed: NodeJS.Timer; +const initDuration = 3; +let durationScroll = initDuration; +let durationFailed = initDuration; + +const errCodeUrl = 'https://www.oceanbase.com/product/ob-deployer/error-codes'; +interface PreCheckProps { + isNewDB: boolean; +} + +// result: RUNNING | FALIED | SUCCESSFUL +// status: RUNNING | FINISHED +export default function PreCheck({ + current, + setCurrent, + isNewDB, +}: PreCheckProps & API.StepProp) { + const { + setCheckOK, + handleQuitProgress, + getInfoByName, + setConfigData, + setErrorVisible, + setErrorsList, + errorsList, + ocpConfigData, + } = useModel('global'); + const { setInstallTaskId } = useModel('ocpInstallData'); + + const { connectId } = useModel('ocpInstallData'); + const oceanbase = ocpConfigData?.components?.oceanbase; + const name = ocpConfigData?.components?.oceanbase?.appname; + const [statusData, setStatusData] = useState({}); + const [failedList, setFailedList] = useState([]); + const [showFailedList, setShowFailedList] = useState([]); + const [hasAuto, setHasAuto] = useState(false); + const [hasManual, setHasManual] = useState(false); + const [onlyManual, setOnlyManual] = useState(false); + const [checkFinished, setCheckFinished] = useState(false); + const [isScroll, setIsScroll] = useState(false); + const [isScrollFailed, setIsScrollFailed] = useState(false); + const [loading, setLoading] = useState(false); + const [checkStatus, setCheckStatus] = useState(true); + const [currentPage, setCurrentPage] = useState(true); + const [firstErrorTimestamp, setFirstErrorTimestamp] = useState(); + const { + data: precheckOcpDatas, + run: precheckOcp, + refresh, + loading: ocpPrecheckLoading, + } = useRequest(OCP.precheckOcp, { + manual: true, + onSuccess: (res: any) => { + if (res?.success) { + const { data } = res; + let timer: NodeJS.Timer; + data.finished = + data?.task_info?.info.filter( + (item) => item.result === 'SUCCESSFUL' || item.result === 'FAILED', + ).length || 0; + data.total = data?.precheck_result?.length || 0; + data.all_passed = data.task_info.result === 'SUCCESSFUL'; + setStatusData(data || {}); + if (data?.task_info?.status === 'RUNNING') { + timer = setTimeout(() => { + refresh(); + }, 2000); + } + if ( + data?.task_info?.result === 'FAILED' && + data?.precheck_result.find((item: any) => item.result === 'RUNNING') + ) { + const newFailedList = + data?.precheck_result?.filter( + (item: any) => item.result === 'FAILED', + ) || []; + setShowFailedList(newFailedList); + setFailedList(newFailedList); + let errorInfo: API.ErrorInfo = { + title: intl.formatMessage({ + id: 'OBD.pages.components.PreCheckStatus.RequestError', + defaultMessage: '请求错误', + }), + desc: data?.message, + }; + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + setCheckStatus(false); + setCheckFinished(true); + } else { + if (data.all_passed) { + setFailedList([]); + setShowFailedList([]); + } else { + const newFailedList = + data?.precheck_result?.filter( + (item: any) => item.result === 'FAILED', + ) || []; + newFailedList.forEach((item: any) => { + if (item.recoverable) { + setHasAuto(true); + } else { + setHasManual(true); + } + }); + setFailedList(newFailedList); + setShowFailedList(newFailedList); + } + // const isFinished = !!data?.total && data?.finished === data?.total; + const isFinished = data.task_info.status === 'FINISHED'; + setCheckFinished(isFinished); + if (isFinished) { + clearTimeout(timer); + } + if (!isScroll && !isFinished) { + setTimeout(() => { + const timelineContainer = + document.getElementById('timeline-container'); + const runningItemDom = document.getElementById( + 'running-timeline-item', + ); + if (timelineContainer) { + timelineContainer.scrollTop = NP.minus( + NP.strip(runningItemDom?.offsetTop), + 150, + ); + } + }, 10); + } + + if (!isScrollFailed && !isFinished && failedList) { + setTimeout(() => { + const failedContainer = + document.getElementById('failed-container'); + if (failedContainer) { + failedContainer.scrollTop = NP.strip( + failedContainer?.scrollHeight, + ); + } + }, 10); + } + setCheckStatus(true); + } + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }); + + // 发起OCP的预检查 + const { + run: precheckOcpDeployment, + refresh: rePrecheckOcpDeployment, + loading: preCheckLoading, + } = useRequest(OCP.precheckOcpDeployment, { + manual: true, + onSuccess: (res: any) => { + if (res.success) { + precheckOcp({ + id: connectId, + task_id: res.data?.id, + }); + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }); + + const { run: handleInstallConfirm } = customRequest( + deployAndStartADeployment, + { + onError: (e: any) => { + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }, + ); + + const handelCheck = async () => { + setLoading(true); + try { + if (connectId) { + await precheckOcpDeployment({ id: connectId }); + } + } catch { + setLoading(false); + } + }; + + const { run: handleCreateConfig, loading: createLoading } = useRequest( + createDeploymentConfig, + { + manual: true, + onSuccess: ({ success }: API.OBResponse) => { + if (success) { + handelCheck(); + } + setLoading(false); + }, + onError: (e: any) => { + setCheckStatus(false); + if (loading) { + setLoading(false); + } + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }, + ); + + const handleRetryCheck = (newConfigData?: any) => { + setStatusData({}); + setFailedList([]); + setShowFailedList([]); + setCheckFinished(false); + let params = { ...ocpConfigData }; + if (newConfigData) { + params = { ...newConfigData }; + } + precheckOcpDeployment({ id: connectId }); + }; + + const { run: handleRecover, loading: recoverLoading } = useRequest( + OCP.recoverOcpDeployment, + { + manual: true, + onSuccess: async ({ success }) => { + if (success) { + message.success( + intl.formatMessage({ + id: 'OBD.OCPPreCheck.PreCheck.AutomaticRepairSucceeded', + defaultMessage: '自动修复成功', + }), + ); + try { + rePrecheckOcpDeployment(); + } catch (e: any) { + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + } + } + }, + onError: (e: any) => { + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }, + ); + + const prevStep = () => { + setCheckOK(false); + setCurrent(current - 1); + setCurrentPage(false); + setErrorVisible(false); + setErrorsList([]); + window.scrollTo(0, 0); + }; + + const { run: installOcp, loading: precheckLoading } = useRequest( + OCP.installOcp, + { + manual: true, + onSuccess: ({ data, success }) => { + if (success) { + setInstallTaskId(data?.id); + setCurrent(5); + setCurrent(current + 1); + setCurrentPage(false); + setErrorVisible(false); + setErrorsList([]); + } + }, + onError: (e: any) => { + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }, + ); + + const handleInstall = async () => { + installOcp({ + id: connectId, + }); + }; + + const handleScrollTimeline = () => { + if (!checkFinished) { + setIsScroll(true); + clearInterval(timerScroll); + durationScroll = initDuration; + timerScroll = setInterval(() => { + if (durationScroll === 0) { + clearInterval(timerScroll); + setIsScroll(false); + durationScroll = initDuration; + } else { + durationScroll -= 1; + } + }, 1000); + } + }; + + const handleScrollFailed = () => { + if (!checkFinished) { + setIsScrollFailed(true); + clearInterval(timerFailed); + durationFailed = initDuration; + timerFailed = setInterval(() => { + if (durationFailed === 0) { + clearInterval(timerFailed); + setIsScrollFailed(false); + durationFailed = initDuration; + } else { + durationFailed -= 1; + } + }, 1000); + } + }; + + const handleAutoRepair = () => { + setHasAuto(false); + handleRecover({ id: connectId }); + }; + + useEffect(() => { + if (onlyManual) { + const newShowFailedList = failedList.filter((item) => !item.recoverable); + setShowFailedList(newShowFailedList); + } else { + setShowFailedList(failedList); + } + }, [onlyManual]); + + useEffect(() => { + precheckOcpDeployment({ id: connectId }); + const timelineContainer = document.getElementById('timeline-container'); + timelineContainer.onmousewheel = handleScrollTimeline; // ie , chrome + timelineContainer?.addEventListener('DOMMouseScroll', handleScrollTimeline); // firefox + return () => { + timelineContainer.onmousewheel = () => {}; + timelineContainer?.removeEventListener( + 'DOMMouseScroll', + handleScrollTimeline, + ); + }; + }, []); + + useEffect(() => { + const addEventFailedContainer = () => { + const failedContainer = document.getElementById('failed-container'); + if (failedList?.length && failedContainer) { + if (!failedContainer.onmousewheel) { + failedContainer.onmousewheel = handleScrollFailed; // ie , chrome + failedContainer?.addEventListener( + 'DOMMouseScroll', + handleScrollFailed, + ); + // firefox + } + } else { + setTimeout(() => { + addEventFailedContainer(); + }, 3000); + } + }; + + addEventFailedContainer(); + return () => { + const failedContainer = document.getElementById('failed-container'); + if (failedContainer) { + failedContainer.onmousewheel = () => {}; + failedContainer?.removeEventListener( + 'DOMMouseScroll', + handleScrollFailed, + ); + } + }; + }, [failedList]); + + let progressStatus = 'active'; + if (statusData?.task_info?.status === 'FAILED') { + progressStatus = 'exception'; + } else if (checkFinished) { + if (statusData.all_passed) { + progressStatus = 'success'; + } else { + progressStatus = 'exception'; + } + } + + const shape = ( +
    +
    +
    +
    +
    +
    + ); + + const checkItemLength = `${statusData?.finished || 0}/${ + statusData?.total || 0 + }`; + const failedItemLength = failedList?.length; + + return ( + + + handleRetryCheck()} + data-aspm-click="ca54438.da43444" + data-aspm-desc={intl.formatMessage({ + id: 'OBD.OCPPreCheck.PreCheck.PreCheckResultReCheck', + defaultMessage: '预检查结果-重新检查', + })} + data-aspm-param={``} + data-aspm-expo + > + {intl.formatMessage({ + id: 'OBD.OCPPreCheck.PreCheck.ReCheck', + defaultMessage: '重新检查', + })} + + } + headStyle={{ paddingLeft: '16px', paddingRight: '16px' }} + > + + + {loading ? null : ( + <> + + + + {statusData?.precheck_result?.map( + (item: API.PreCheckInfo, index: number) => { + //根据索引找到对应项 + const task_info_item = + statusData?.task_info?.info[index - 1]; + return ( + + ) : ( + + ) + ) : null + } + > + {item?.name} {item?.server} + + ); + }, + )} + + + )} + + + {hasManual ? ( + setOnlyManual(e.target.checked)} + disabled={!checkFinished || statusData?.all_passed} + > + {intl.formatMessage({ + id: 'OBD.pages.components.PreCheckStatus.OnlyManualFixes', + defaultMessage: '只看手动修复项', + })} + + ) : null} + + + } + > + {showFailedList?.length ? ( +
    + {showFailedList?.map((item, index) => { + let reason = ''; + if (item?.advisement) { + const index = item?.advisement.indexOf(':'); + reason = item?.advisement.substring( + index, + item?.advisement.length, + ); + } + return ( + + + + + + {item.name} + + + + + {intl.formatMessage({ + id: 'OBD.pages.components.PreCheckStatus.Reason', + defaultMessage: '原因:', + })} + + ERR-{item.code} + {' '} + {reason} + + + + + + {intl.formatMessage({ + id: 'OBD.pages.components.PreCheckStatus.Suggestions', + defaultMessage: '建议:', + })} + {item.recoverable ? ( + + {intl.formatMessage({ + id: 'OBD.pages.components.PreCheckStatus.AutomaticRepair', + defaultMessage: '自动修复', + })} + + ) : ( + + {intl.formatMessage({ + id: 'OBD.pages.components.PreCheckStatus.ManualRepair', + defaultMessage: '手动修复', + })} + + )}{' '} + {item.advisement} + +
    + + {intl.formatMessage({ + id: 'OBD.pages.components.PreCheckStatus.LearnMore', + defaultMessage: '了解更多方案', + })} + +
    +
    + ); + })} + {!checkFinished ? ( +
    {shape}
    + ) : null} +
    + ) : checkFinished ? ( + + {intl.formatMessage({ + id: 'OBD.pages.components.PreCheckStatus.GreatNoFailedItems', + defaultMessage: '太棒了!无失败项', + })} + + } + /> + ) : ( +
    + {shape} +
    + {intl.formatMessage({ + id: 'OBD.pages.components.PreCheckStatus.NoFailedItemsFoundYet', + defaultMessage: '暂未发现失败项', + })} +
    +
    + )} + + + + {' '} + + + {!statusData?.all_passed ? ( + + + + ) : ( + + )} + + + ); +} diff --git a/web/src/component/OCPPreCheck/helper.ts b/web/src/component/OCPPreCheck/helper.ts new file mode 100644 index 0000000..2b6582f --- /dev/null +++ b/web/src/component/OCPPreCheck/helper.ts @@ -0,0 +1,60 @@ +import _ from 'lodash'; + +export const formatPreCheckData = (configData: any) => { + let _configData = _.cloneDeep(configData); + let { memory_size } = _configData.components.ocpserver; + _configData.components.oceanbase.mode = 'PRODUCTION'; + if (typeof memory_size === 'number') { + _configData.components.ocpserver.memory_size = memory_size + 'G'; + } + if ( + _configData.components.oceanbase && + _configData.components.oceanbase.topology + ) { + let {parameters,topology} = _configData.components.oceanbase + for (let item of topology) { + delete item.id; + } + for(let idx = 0;idx { + return { + key: parameter.key, + value: parameter.value, + adaptive: parameter.adaptive, + }; + }); + } + if ( + (key === 'oceanbase' || key === 'obproxy') && + item.home_path && + !item.home_path.split('/').includes(key) + ) { + item.home_path += `/${key}`; + } + if ( + key === 'ocpserver' && + !item.home_path.split('/').includes('ocpserver') + ) { + item.home_path += '/ocp'; + } + } + + if (location.hash.split('/').pop() !== 'install') { + return { + ..._configData, + auth: _configData.auth, + components: { + ocpserver: _configData.components.ocpserver, + }, + }; + } + return _configData; +}; diff --git a/web/src/component/OCPPreCheck/index.less b/web/src/component/OCPPreCheck/index.less new file mode 100644 index 0000000..a31f13b --- /dev/null +++ b/web/src/component/OCPPreCheck/index.less @@ -0,0 +1,16 @@ +@smallSpace: 8px; +.checkInfoSpace { + width: 100%; + :global { + .ant-col { + padding-right: 0 !important; + padding-left: 0 !important; + } + .ant-col.ant-col-12:nth-child(2n + 1) { + padding-right: @smallSpace !important; + } + .ant-col.ant-col-12:nth-child(2n) { + padding-left: @smallSpace !important; + } + } +} diff --git a/web/src/component/OCPPreCheck/index.tsx b/web/src/component/OCPPreCheck/index.tsx new file mode 100644 index 0000000..dff9a07 --- /dev/null +++ b/web/src/component/OCPPreCheck/index.tsx @@ -0,0 +1,19 @@ +import { useState } from 'react'; + +import CheckInfo from './CheckInfo'; +import PreCheck from './PreCheck'; +import { getTailPath } from '@/utils/helper'; + +export default function OCPPreCheck(prop: API.StepProp) { + const [preCheckVisible, setPreCheckVisible] = useState(false); + const isNewDB = getTailPath() === 'install' + return ( + <> + {!preCheckVisible ? ( + + ) : ( + + )} + + ); +} diff --git a/web/src/component/PageCard/index.less b/web/src/component/PageCard/index.less new file mode 100644 index 0000000..40fb3ce --- /dev/null +++ b/web/src/component/PageCard/index.less @@ -0,0 +1,7 @@ +.card { + display: flex; + align-items: center; + justify-content: center; + min-height: 100%; + padding: 24px 64px; +} diff --git a/web/src/component/PageCard/index.tsx b/web/src/component/PageCard/index.tsx new file mode 100644 index 0000000..db3ba9a --- /dev/null +++ b/web/src/component/PageCard/index.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { Card, Spin } from '@oceanbase/design'; +import styles from './index.less'; + +export interface TaskSuccessProps { + children: React.ReactNode; + loading?: boolean; + style?: React.CSSProperties; + className?: string; +} + +const PageCard: React.FC = ({ + children, + loading = false, + className, + ...restProps +}) => ( + + {children} + +); + +export default PageCard; diff --git a/web/src/component/PageLoading/index.tsx b/web/src/component/PageLoading/index.tsx new file mode 100644 index 0000000..3187020 --- /dev/null +++ b/web/src/component/PageLoading/index.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { Spin } from '@oceanbase/design'; +import type { SpinProps } from 'antd/es/spin'; + +const PageLoading: React.FC = props => ( +
    + +
    +); + +export default PageLoading; diff --git a/web/src/component/Password.tsx b/web/src/component/Password.tsx new file mode 100644 index 0000000..bd1d24b --- /dev/null +++ b/web/src/component/Password.tsx @@ -0,0 +1,43 @@ +import { intl } from '@/utils/intl'; +import React from 'react'; +import { Password } from '@oceanbase/ui'; +import type { PasswordProps } from '@oceanbase/ui/es/Password'; + +const OCPPassword: React.FC = (props) => { + // 特殊字符支持 ~!@#%^&*_\-+=`|(){}[]:;',.?/ + const ocpPasswordRules = [ + { + validate: (val?: string) => val?.length >= 8 && val?.length <= 32, + message: intl.formatMessage({ + id: 'OBD.src.component.Password.ToCharactersInLength', + defaultMessage: '长度为 8~32 个字符', + }), + }, + + { + validate: (val?: string) => + /^[0-9a-zA-Z~!@#%^&*_\-+=|(){}\[\]:;,.?/]+$/.test(val), + message: intl.formatMessage({ + id: 'OBD.src.component.Password.CanOnlyContainLettersNumbers', + defaultMessage: + '只能包含字母、数字和特殊字符(~!@#%^&*_-+=|(){}[]:;,.?/)', + }), + }, + + { + validate: (val?: string) => + /^(?=(.*[a-z]){2,})(?=(.*[A-Z]){2,})(?=(.*\d){2,})(?=(.*[~!@#%^&*_\-+=|(){}\[\]:;,.?/]){2,})[A-Za-z\d~!@#%^&*_\-+=|(){}\[\]:;,.?/]{2,}$/.test( + val, + ), + + message: intl.formatMessage({ + id: 'OBD.src.component.Password.AtLeastUppercaseAndLowercase', + defaultMessage: '大小写字母、数字和特殊字符都至少包含 2 个', + }), + }, + ]; + + return ; +}; + +export default OCPPassword; diff --git a/web/src/component/PasswordCard/index.less b/web/src/component/PasswordCard/index.less new file mode 100644 index 0000000..c144c1a --- /dev/null +++ b/web/src/component/PasswordCard/index.less @@ -0,0 +1,9 @@ +.passwordCardContainer { + .pwdIcon { + position: absolute; + top: 2px; + right: 0; + color: #8592ad; + font-size: 17px; + } +} diff --git a/web/src/component/PasswordCard/index.tsx b/web/src/component/PasswordCard/index.tsx new file mode 100644 index 0000000..b15f234 --- /dev/null +++ b/web/src/component/PasswordCard/index.tsx @@ -0,0 +1,51 @@ +import { intl } from '@/utils/intl'; +import { useState } from 'react'; +import { ProCard } from '@ant-design/pro-components'; +import { Tooltip } from 'antd'; +import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'; + +import styles from './index.less'; + +export default function PasswordCard({ password }: { password: string }) { + const [showPwd, setShowPwd] = useState(false); + return ( + + {password ? ( +
    + {showPwd ? ( +
    + +
    + {password} +
    +
    + setShowPwd(false)} + /> +
    + ) : ( +
    + {password.replace(/./g, '*')} + setShowPwd(true)} + /> +
    + )} +
    + ) : ( + '-' + )} +
    + ); +} diff --git a/web/src/component/Result/index.less b/web/src/component/Result/index.less new file mode 100644 index 0000000..ee900be --- /dev/null +++ b/web/src/component/Result/index.less @@ -0,0 +1,5 @@ +.container { + .detail { + background-color: #fafafa; + } +} diff --git a/web/src/component/Result/index.tsx b/web/src/component/Result/index.tsx new file mode 100644 index 0000000..c4cac07 --- /dev/null +++ b/web/src/component/Result/index.tsx @@ -0,0 +1,72 @@ +import { intl } from '@/utils/intl'; +import { history } from 'umi'; +import React from 'react'; +import { Button, Result, Space } from '@oceanbase/design'; +import type { ResultProps } from 'antd/es/result'; +import { PageContainer } from '@oceanbase/ui'; + +import PageCard from '@/component/PageCard'; +import styles from './index.less'; + +export interface SuccessProps extends ResultProps { + iconUrl?: string; + taskId?: number; + children?: React.ReactNode; + style?: React.CSSProperties; + className?: string; +} + +const Success: React.FC = ({ + iconUrl = '/assets/icon/success.svg', + taskId, + children, + className, + style, + ...restProps +}) => { + return ( + + + } + extra={ + + + {taskId && ( + + )} + + } + {...restProps} + > + {children} + + + + ); +}; + +export default Success; diff --git a/web/src/component/SliderAndInputNumber/index.less b/web/src/component/SliderAndInputNumber/index.less new file mode 100644 index 0000000..f410ec3 --- /dev/null +++ b/web/src/component/SliderAndInputNumber/index.less @@ -0,0 +1,18 @@ +.SliderAndInputNumber { + :global { + .ant-slider { + margin: 0 5px; + .ant-slider-rail { + background-color: #E2E8F3; + } + } + } + .marks { + color: #5C6B8A; + display: flex; + margin: 0 5px; + flex-direction: row; + align-items: center; + justify-content: space-between; + } +} \ No newline at end of file diff --git a/web/src/component/SliderAndInputNumber/index.tsx b/web/src/component/SliderAndInputNumber/index.tsx new file mode 100644 index 0000000..10691a0 --- /dev/null +++ b/web/src/component/SliderAndInputNumber/index.tsx @@ -0,0 +1,67 @@ +import React, { useState, useEffect } from 'react'; +import { InputNumber, Slider, Row, Col } from '@oceanbase/design'; + +import styles from './index.less'; + +export interface SliderAndInputNumberProps { + max: number; + min: number; + value?: number; + addonAfter?: string; + onChange?: (value: number) => void; +} + +const SliderAndInputNumber: React.FC = ({ + max, + min, + value, + addonAfter = 'GiB', + onChange, +}) => { + const [currentValue, setCurrentValue] = useState(value || 0); + + useEffect(() => { + if (value) { + setCurrentValue(value); + } + }, [value]); + + const onHandleChange = (val: number) => { + setCurrentValue(val); + if (onChange) { + onChange(val); + } + }; + + return ( + +
    + +
    +
    {min}
    +
    {max}
    +
    + +
    + + + + ); +}; + +export default SliderAndInputNumber; diff --git a/web/src/component/Steps/index.tsx b/web/src/component/Steps/index.tsx new file mode 100644 index 0000000..efcb445 --- /dev/null +++ b/web/src/component/Steps/index.tsx @@ -0,0 +1,101 @@ +import { intl } from '@/utils/intl'; +import { Space } from 'antd'; +import { ClockCircleOutlined, CheckCircleOutlined } from '@ant-design/icons'; +import { getLocale } from 'umi'; +import EnStyles from '../../pages/Obdeploy/indexEn.less'; +import ZhStyles from '../../pages/Obdeploy/indexZh.less'; + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; +import { useEffect, useState } from 'react'; + +interface StepsProps { + stepsItems: { + title: string; + key: number; + }[]; + currentStep: number; + showStepsKeys: number[]; +} + +export default function Steps({ + currentStep, + showStepsKeys, + stepsItems, +}: StepsProps) { + const [showBorder, setShowBorder] = useState(false); + const getIcon = (key: number) => { + return currentStep > key ? ( + + ) : ( + + ); + }; + + const handleScroll = () => { + if (document.documentElement.scrollTop > 0) { + setShowBorder(true); + } else { + setShowBorder(false); + } + }; + + const getZhGap = () => { + if (showStepsKeys.length === 4) { + return 150; + } + return 100; + }; + const getEnGap = () => { + if (showStepsKeys.length === 4) { + return 60; + } + return 0; + }; + + useEffect(() => { + document.addEventListener('scroll', handleScroll); + }, []); + + return ( +
    + {showStepsKeys.includes(currentStep) ? ( +
    +
    +
    +
    +
    + + {stepsItems.map((item) => ( + + {getIcon(item.key)} + item.key ? styles.stepAlreadyTitle : ''}`} + > + {item.title} + + + ))} + +
    +
    + ) : null} +
    + ); +} diff --git a/web/src/constant/configuration.ts b/web/src/constant/configuration.ts new file mode 100644 index 0000000..1e12c76 --- /dev/null +++ b/web/src/constant/configuration.ts @@ -0,0 +1,136 @@ +import { intl } from '@/utils/intl'; +export const NEW_METADB_OCP_INSTALL = [ + { + title: intl.formatMessage({ + id: 'OBD.src.constant.configuration.DeploymentConfiguration', + defaultMessage: '部署配置', + }), + key: 1, + }, + { + title: intl.formatMessage({ + id: 'OBD.src.constant.configuration.MetadbConfiguration', + defaultMessage: 'MetaDB 配置', + }), + key: 2, + }, + { + title: intl.formatMessage({ + id: 'OBD.src.constant.configuration.OcpConfiguration', + defaultMessage: 'OCP 配置', + }), + key: 3, + }, + { + title: intl.formatMessage({ + id: 'OBD.src.constant.configuration.PreCheck', + defaultMessage: '预检查', + }), + key: 4, + }, + { + title: intl.formatMessage({ + id: 'OBD.src.constant.configuration.Deployment', + defaultMessage: '部署', + }), + key: 5, + }, +]; + +export const METADB_OCP_INSTALL = [ + { + title: intl.formatMessage({ + id: 'OBD.src.constant.configuration.DeploymentConfiguration', + defaultMessage: '部署配置', + }), + key: 1, + }, + { + title: intl.formatMessage({ + id: 'OBD.src.constant.configuration.ObClusterConnectionConfiguration', + defaultMessage: 'OB集群 连接配置', + }), + key: 2, + }, + { + title: intl.formatMessage({ + id: 'OBD.src.constant.configuration.OcpConfiguration', + defaultMessage: 'OCP 配置', + }), + key: 3, + }, + { + title: intl.formatMessage({ + id: 'OBD.src.constant.configuration.PreCheck', + defaultMessage: '预检查', + }), + key: 4, + }, + { + title: intl.formatMessage({ + id: 'OBD.src.constant.configuration.Deployment', + defaultMessage: '部署', + }), + key: 5, + }, +]; + +export const STEPS_KEYS_INSTALL = [1, 2, 3, 4, 5]; +export const STEPS_KEYS_UPDATE = [1, 2, 3, 4]; +export const METADB_OCP_UPDATE = [ + { + title: intl.formatMessage({ + id: 'OBD.src.constant.configuration.DeploymentConfiguration', + defaultMessage: '部署配置', + }), + key: 1, + }, + { + title: intl.formatMessage({ + id: 'OBD.src.constant.configuration.ConnectivityTest', + defaultMessage: '联通性测试', + }), + key: 2, + }, + { + title: intl.formatMessage({ + id: 'OBD.src.constant.configuration.EnvironmentPreCheck', + defaultMessage: '环境预检查', + }), + key: 3, + }, + { + title: intl.formatMessage({ + id: 'OBD.src.constant.configuration.OcpUpgrade', + defaultMessage: 'OCP升级', + }), + key: 4, + }, +]; + +// ocp install +export const CONFIG_KEYS = { + oceanbase: ['cpu_count', 'memory_limit', 'data_file', 'log_file'], + obproxy: ['cpu_count', 'memory_limit', 'data_file', 'log_file'], + // obagent: ['home_path', 'monagent_http_port', 'mgragent_http_port'], + // ocpexpress: ['home_path', 'port'], +}; +export const showConfigKeys = { + oceanbase: [ + 'home_path', + 'mode', + 'root_password', + 'data_dir', + 'redo_dir', + 'mysql_port', + 'rpc_port', + ], + + obproxy: ['home_path', 'listen_port', 'prometheus_listen_port'], + obagent: ['home_path', 'monagent_http_port', 'mgragent_http_port'], + ocpexpress: ['home_path', 'port'], +}; + +export const ocpAddonAfter = '/ocp'; +export const obproxyAddonAfter = '/obproxy'; +export const oceanbaseAddonAfter = '/oceanbase'; diff --git a/web/src/constant/datetime.ts b/web/src/constant/datetime.ts new file mode 100644 index 0000000..0a409fb --- /dev/null +++ b/web/src/constant/datetime.ts @@ -0,0 +1,58 @@ +import moment from 'moment'; + +const localeData = moment.localeData(); + +export const FOREVER_TIME = '2099-12-31T00:00:00.000Z'; + +/* 年 */ +export const YEAR_FORMAT = 'YYYY'; + +export const YEAR_FORMAT_DISPLAY = localeData.longDateFormat('year'); + +/* 月 */ +export const MONTH_FORMAT = 'YYYY-MM'; + +export const MONTH_FORMAT_DISPLAY = localeData.longDateFormat('month'); + +/* 日期 */ +export const DATE_FORMAT = 'YYYY-MM-DD'; + +export const DATE_FORMAT_DISPLAY = localeData.longDateFormat('date'); + +export const DATE_FORMAT_WITHOUT_YEAR_DISPLAY = localeData.longDateFormat('dateWithoutYear'); + +/* 日期 + 时间 */ + +// RFC3339 的日期时间格式 +export const RFC3339_DATE_TIME_FORMAT = 'YYYY-MM-DDTHH:mm:ssZ'; + +// 日期时间格式 +export const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'; + +// 没有秒数据的日期时间格式 +export const DATE_TIME_FORMAT_WITHOUT_SECOND = 'YYYY-MM-DD HH:mm'; + +export const DATE_TIME_FORMAT_DISPLAY = localeData.longDateFormat('datetime'); + +export const DATE_TIME_FORMAT_WITH_SSS_DISPLAY = localeData.longDateFormat('datetimeWithSSS'); + +export const DATE_TIME_FORMAT_WITHOUT_SECOND_DISPLAY = + localeData.longDateFormat('datetimeWithoutSecond'); + +export const DATE_TIME_FORMAT_WITHOUT_YEAR_AND_SECOND_DISPLAY = localeData.longDateFormat( + 'datetimeWithoutYearAndSecond' +); + +/* 时间 */ + +// RFC3339 的时间格式 +export const RFC3339_TIME_FORMAT = 'HH:mm:ssZ'; + +// 时间格式 +export const TIME_FORMAT = 'HH:mm:ss'; + +// 带毫秒的时间格式 +export const TIME_FORMAT_WITH_SSS = 'HH:mm:ss.SSS'; + +// 不带秒信息的时间格式 +export const TIME_FORMAT_WITHOUT_SECOND = 'HH:mm'; diff --git a/web/src/constant/docs.ts b/web/src/constant/docs.ts new file mode 100644 index 0000000..7440516 --- /dev/null +++ b/web/src/constant/docs.ts @@ -0,0 +1,19 @@ +import { getLocale } from 'umi'; + +const docsMap = { + 'zh-CN': 'https://www.oceanbase.com/docs', + 'en-US': 'https://en.oceanbase.com/docs', +}; +// 文档首页路径 +export const DOCS_LINK = `/communityDocs/${docsMap[getLocale()]}/index.html`; +// 部署向导帮助文档 +export const DOCS_PRODUCTION = + 'https://www.oceanbase.com/docs/community-obd-cn-1000000000314362'; +// SOP文档 +export const DOCS_SOP = 'https://ask.oceanbase.com/t/topic/35605473'; +// 用户帮助文档 +const DOCS_USER_CN = + 'https://www.oceanbase.com/docs/common-ocp-1000000000368844'; +const DOCS_USER_EN = + 'https://en.oceanbase.com/docs/common-ocp-10000000001064778'; +export const DOCS_USER = getLocale() === 'zh-CN' ? DOCS_USER_CN : DOCS_USER_EN; diff --git a/web/src/constant/envPresCheck.ts b/web/src/constant/envPresCheck.ts new file mode 100644 index 0000000..31db43d --- /dev/null +++ b/web/src/constant/envPresCheck.ts @@ -0,0 +1,174 @@ +export const ERROR_CODE_LIST = [ + { + value: '1000', + label: 'Configuration conflict x.x.x.x: xxx port is used for x.x.x.x', + }, + { + value: '1001', + label: 'x.x.x.x:xxx port is already used', + }, + { + value: '1002', + label: 'Fail to init x.x.x.x path', + }, + { + value: '1003', + label: 'fail to clean x.x.x.x:xxx', + }, + { + value: '1004', + label: 'Configuration conflict x.x.x.x: xxx is used for x.x.x.x', + }, + { + value: '1005', + label: 'Some of the servers in the cluster have been stopped', + }, + { + value: '1006', + label: 'Failed to connect to xxx', + }, + { + value: '1007', + label: '(x.x.x.x) xxx must not be less than xxx (Current value: xxx)', + }, + { + value: '1008', + label: '(x.x.x.x) failed to get fs.aio-max-nr and fs.aio-nr', + }, + { + value: '1009', + label: 'x.x.x.x xxx need config: xxx', + }, + { + value: '1010', + label: 'x.x.x.x No such net interface: xxx', + }, + { + value: '1011', + label: + '(x.x.x.x) Insufficient AIO remaining (Avail: xxx, Need: xxx), The recommended value of fs.aio-max-nr is 1048576', + }, + { + value: '1012', + label: 'xxx', + }, + { + value: '1013', + label: 'xxx@x.x.x.x connect failed: xxx', + }, + { + value: '2000', + label: 'x.x.x.x not enough memory', + }, + { + value: '2001', + label: 'server can not migrate in', + }, + { + value: '2002', + label: 'failed to start x.x.x.x observer', + }, + { + value: '2003', + label: + 'not enough disk space for clog. Use redo_dir to set other disk for clog, or reduce the value of datafile_size', + }, + { + value: '2004', + label: 'Invalid: xxx is not a single server configuration item', + }, + { + value: '2005', + label: 'Failed to register cluster. xxx may have been registered in xxx', + }, + { + value: '2006', + label: 'x.x.x.x has more than one network interface. Please set devname for x.x.x.x', + }, + { + value: '2007', + label: 'x.x.x.x xxx fail to ping x.x.x.x. Please check configuration devname', + }, + { + value: '2008', + label: 'Cluster clocks are out of sync', + }, + { + value: '2009', + label: 'x.x.x.x: when production_mode is True, xxx can not be less then xxx', + }, + { + value: '2010', + label: + 'x.x.x.x: system_memory too large. system_memory must be less than memory_limit/memory_limit_percentage', + }, + { + value: '2011', + label: + "x.x.x.x: fail to get memory info.\nPlease configure 'memory_limit' manually in configuration file", + }, + { + value: '3000', + label: 'parse cmd failed', + }, + { + value: '3001', + label: 'xxx.sql not found', + }, + { + value: '3002', + label: 'Failed to load data', + }, + { + value: '3003', + label: 'Failed to run TPC-C benchmark', + }, + { + value: '4000', + label: 'Fail to reload x.x.x.x', + }, + { + value: '4001', + label: 'Fail to send config file to x.x.x.x', + }, + { + value: '4100', + label: 'x.x.x.x need config "rs_list" or "obproxy_config_server_url"', + }, + { + value: '4101', + label: 'failed to start x.x.x.x obproxy: xxx', + }, + { + value: '4200', + label: "x.x.x.x grafana admin password should not be 'admin'", + }, + { + value: '4201', + label: 'x.x.x.x grafana admin password length should not be less than 5', + }, + { + value: '4300', + label: 'x.x.x.x: failed to query java version, you may not have java installed', + }, + { + value: '4301', + label: 'x.x.x.x: ocp-express need java with version xxx', + }, + { + value: '4302', + label: 'x.x.x.x not enough memory. (Free: xxx, Need: xxx)', + }, + { + value: '4303', + label: 'x.x.x.x xxx not enough disk space. (Avail: xxx, Need: xxx)', + }, + { + value: '4304', + label: 'OCP express xxx needs to use xxx with version xxx or above', + }, + { + value: '4305', + label: 'There is not enough xxx for ocp meta tenant', + }, +]; diff --git a/web/src/constant/index.ts b/web/src/constant/index.ts new file mode 100644 index 0000000..2bed93e --- /dev/null +++ b/web/src/constant/index.ts @@ -0,0 +1,398 @@ +import moment from 'moment'; +// import { +// getNameValidateMessage, +// getChineseNameValidateMessage, +// getUsernameValidateMessage, +// getDatabaseNameValidateMessage, +// getMySQLDbUserNameValidateMessage, +// getOracleDbUserNameValidateMessage, +// getSpaceValidateMessage, +// } from '@/constant/component'; +import { MICROSECOND } from '@/constant/must-ignore'; +import { intl } from '@/utils/intl'; +// import { showTotal } from '@/utils'; + +export const ALL = '__OCP_ALL_CONSTANT_VALUE__'; + +// 通配符 +export const WILDCARD = '*'; + +// OB 官网链接 +export const OB_SITE_LINK = 'https://www.oceanbase.com'; + +/* 正则表达式 */ + +// // 通用名称正则校验: 以英文字母开头、英文或数字结尾,可包含英文、数字和下划线,且长度为 2 ~ 32 +// export const NAME_REGEXP = /^[a-zA-Z]{1,1}[a-zA-Z0-9_]{0,30}[a-zA-Z0-9]{1,1}$/; +// export const NAME_RULE = { +// pattern: NAME_REGEXP, +// message: getNameValidateMessage(), +// }; + +// // 支持中文名称正则校验: 可包含中文、英文、数字、下划线、中横线,且长度为 2 ~ 32 +// export const CHINESE_NAME_REGEXP = /^[a-zA-Z0-9\-_\u4e00-\u9fa5]{2,32}$/; +// export const CHINESE_NAME_RULE = { +// pattern: CHINESE_NAME_REGEXP, +// message: getChineseNameValidateMessage(), +// }; + +// // 合法名称正则校验,不限制长度,可结合 getTextLength() 搭配使用 +// export const VALID_NAME_REGEXP = /^[a-zA-Z][a-zA-Z0-9_]*$/; +// export const VALID_NAME_RULE = { +// pattern: VALID_NAME_REGEXP, +// message: intl.formatMessage({ +// id: 'ocp-express.src.constant.ItMustStartWithA', +// defaultMessage: '以英文字母开头,可包含英文、数字和下划线', +// }), +// }; + +// // database 命名规则 +// export const DATABASE_NAME_RULE = { +// pattern: /^[a-z]{1,1}[a-z0-9_]{1,127}$/, +// message: getDatabaseNameValidateMessage(), +// }; + +// // MySQLdbuser 命名规则 +// export const DATABASE_USER_NAME_RULE = { +// pattern: /^[a-z]{1,1}[a-z0-9_]{1,63}$/, +// message: getMySQLDbUserNameValidateMessage(), +// }; + +// // Oracle dbuUser 命名规则 +// export const ORACLE_DATABASE_USER_NAME_RULE = { +// pattern: /^[a-zA-Z]{1,1}[a-zA-Z0-9_]{1,29}$/, +// message: getOracleDbUserNameValidateMessage(30), +// }; + +// // Oracle dbRole 命名规则 +// export const ORACLE_DATABASE_ROLE_NAME_RULE = { +// pattern: /^[a-zA-Z]{1,1}[a-zA-Z0-9_]{1,29}$/, +// message: getOracleDbUserNameValidateMessage(30), +// }; + +// // 用户名称正则校验: 以英文字母开头、英文或数字结尾,可包含英文、数字、点号、中划线和下划线,且长度为 4 ~ 48 +// export const USERNAME_REGEXP = /^[a-zA-Z]{1,1}[a-zA-Z0-9.\-_]{2,46}[a-zA-Z0-9]{1,1}$/; +// export const USERNAME_RULE = { +// pattern: USERNAME_REGEXP, +// message: getUsernameValidateMessage(), +// }; + +// // 特殊字符支持 ~!@#%^&*_\-+=|(){}[]:;,.?/ +// export const PASSWORD_REGEX = +// /^(?=(.*[a-z]){2,})(?=(.*[A-Z]){2,})(?=(.*\d){2,})(?=(.*[~!@#%^&*_\-+=|(){}\[\]:;,.?/]){2,})[A-Za-z\d~!@#%^&*_\-+=|(){}\[\]:;,.?/]{8,32}$/; + +// // 校验空格 +// export const SPACE_REGEX = /^[^\s]*$/; +// // export const SPACE_RULE = { +// // pattern: SPACE_REGEX, +// // message: getSpaceValidateMessage(), +// // }; + +// export const BOOLEAN_LIST = [ +// { +// label: intl.formatMessage({ id: 'ocp-express.src.constant.Is', defaultMessage: '是' }), +// value: true, +// }, + +// { +// label: intl.formatMessage({ id: 'ocp-express.src.constant.No', defaultMessage: '否' }), +// value: false, +// }, +// ]; + +export const SMLL_FORM_ITEM_LAYOUT = { + labelCol: { + span: 12, + }, + + wrapperCol: { + span: 12, + }, +}; + +export const FORM_ITEM_LAYOUT = { + labelCol: { + span: 4, + }, + + wrapperCol: { + span: 20, + }, +}; + +export const MODAL_FORM_ITEM_LAYOUT = { + labelCol: { + span: 24, + }, + + wrapperCol: { + span: 18, + }, +}; + +export const DRAWER_FORM_ITEM_LAYOUT = { + labelCol: { + span: 24, + }, + + wrapperCol: { + span: 12, + }, +}; + +export const MODAL_HORIZONTAL_FORM_ITEM_LAYOUT = { + labelCol: { + span: 6, + }, + + wrapperCol: { + span: 18, + }, +}; + +export const NEST_FORM_ITEM_LAYOUT = { + labelCol: { + span: 3, + }, + + wrapperCol: { + span: 21, + }, +}; + +export const FORM_ITEM_SMALL_LAYOUT = { + labelCol: { + span: 4, + }, + + wrapperCol: { + span: 10, + }, +}; + +export const TAIL_FORM_ITEM_LAYOUT = { + wrapperCol: { + span: 20, + offset: 4, + }, +}; + +export const MIDDLE_FORM_ITEM_LAYOUT = { + labelCol: { + span: 6, + }, + + wrapperCol: { + span: 18, + }, +}; + +export const MIDDLE_TAIL_FORM_ITEM_LAYOUT = { + wrapperCol: { + span: 18, + offset: 6, + }, +}; + +export const LARGE_FORM_ITEM_LAYOUT = { + labelCol: { + span: 8, + }, + + wrapperCol: { + span: 16, + }, +}; + +export const MAX_FORM_ITEM_LAYOUT = { + labelCol: { + span: 24, + }, + + wrapperCol: { + span: 24, + }, +}; + +export const LARGE_TAIL_FORM_ITEM_LAYOUT = { + wrapperCol: { + span: 16, + offset: 8, + }, +}; + +export const SUPERSIZE_FORM_ITEM_LAYOUT = { + labelCol: { + span: 10, + }, + + wrapperCol: { + span: 14, + }, +}; + +export const PAGE_FORM_ITEM_LAYOUT = { + labelCol: { + span: 4, + }, + + wrapperCol: { + span: 12, + }, +}; + +export const PAGR_TAIL_FORM_ITEM_LAYOUT = { + labelCol: { + span: 0, + }, + + wrapperCol: { + offset: 4, + span: 12, + }, +}; + +export const DEFAULT_LIST_DATA = { + page: { + totalElements: 0, + totalPages: 0, + number: 0, + size: 0, + }, + + contents: [], +}; + +export const PAGINATION_OPTION_10 = { + defaultPageSize: 10, + showSizeChanger: true, + pageSizeOptions: ['10', '20', '50', '100'], + // showTotal, +}; + +export const PAGINATION_OPTION_5 = { + defaultPageSize: 5, + showSizeChanger: true, + pageSizeOptions: ['5', '10', '20', '50'], + // showTotal, +}; + +export const EMAIL_DOMAIN_LIST = [ + 'aliyun.com', + '163.com', + '126.com', + 'foxmail.com', + 'gmail.com', + 'outlook.com', + 'msn.com', + 'sohu.com', + 'sina.com', + 'hotmail.com', + 'qq.com', +]; + +export function getRanges() { + const rangeList = [ + { + label: intl.formatMessage({ + id: 'ocp-express.src.constant.Minutes', + defaultMessage: '1 分钟', + }), + value: () => [moment().subtract(1, 'minute'), moment()], + }, + + { + label: intl.formatMessage({ + id: 'ocp-express.src.constant.Minutes.1', + defaultMessage: '5 分钟', + }), + value: () => [moment().subtract(5, 'minute'), moment()], + }, + + { + label: intl.formatMessage({ + id: 'ocp-express.src.constant.Minutes.2', + defaultMessage: '10 分钟', + }), + value: () => [moment().subtract(10, 'minute'), moment()], + }, + + { + label: intl.formatMessage({ + id: 'ocp-express.src.constant.Minutes.3', + defaultMessage: '20 分钟', + }), + value: () => [moment().subtract(20, 'minute'), moment()], + }, + + { + label: intl.formatMessage({ + id: 'ocp-express.src.constant.HalfAnHour', + defaultMessage: '半小时', + }), + value: () => [moment().subtract(30, 'minute'), moment()], + }, + + { + label: intl.formatMessage({ + id: 'ocp-express.src.constant.AnHour', + defaultMessage: '一小时', + }), + value: () => [moment().subtract(60, 'minute'), moment()], + }, + ]; + + const ranges = {}; + rangeList.forEach((item) => { + ranges[item.label] = (item.value && item.value()) || []; + }); + return ranges; +} + +// OCP 实时监控的刷新频率,单位为 s +export const FREQUENCY = 5; + +export const TIME_UNIT_LIST = [MICROSECOND, 'ms', 's', 'min']; +export const SIZE_UNIT_LIST = ['byte', 'KB', 'MB', 'GB', 'TB', 'PB']; + +// 提供给 Select 组件做分词使用,支持(逗号、空格、逗号 + 空格、换行符、逗号 + 换行符)等 5 种场景,因为 Select 组件默认支持换行符分隔,所以不显示定义 (换行符、逗号 + 换行符) +export const SELECT_TOKEN_SPEARATORS = [',', ', ', ' ']; + +export const OCP_UPGRADE_STATUS_LIST = [ + { + label: intl.formatMessage({ + id: 'OBD.src.constant.Checking', + defaultMessage: '检查中', + }), + + value: 'RUNNING', + badgeStatus: 'processing', + }, + { + label: intl.formatMessage({ + id: 'OBD.src.constant.Pass', + defaultMessage: '通过', + }), + + value: 'PASSED', + badgeStatus: 'success', + }, + { + label: intl.formatMessage({ + id: 'OBD.src.constant.Failed', + defaultMessage: '未通过', + }), + + value: 'FAILED', + badgeStatus: 'error', + }, + { + label: intl.formatMessage({ + id: 'OBD.src.constant.Ignored', + defaultMessage: '已忽略', + }), + + value: 'IGNORED', + badgeStatus: 'ignored', + }, +]; diff --git a/web/src/constant/must-ignore.ts b/web/src/constant/must-ignore.ts new file mode 100644 index 0000000..8a86492 --- /dev/null +++ b/web/src/constant/must-ignore.ts @@ -0,0 +1,18 @@ +import { intl } from '@/utils/intl'; +export const LOCALE_LIST = [ + { + label: 'English', + value: 'en-US', + }, + { + label: intl.formatMessage({ + id: 'OBD.src.constant.must-ignore.SimplifiedChinese', + defaultMessage: '简体中文', + }), + value: 'zh-CN', + }, +]; + +// μs 会被 must 视别为中文字符 +export const MICROSECOND = 'μs'; +export type MICROSECOND_TYPE = 'μs'; diff --git a/web/src/i18n/strings/en-US.json b/web/src/i18n/strings/en-US.json index ec0d287..adae0c5 100644 --- a/web/src/i18n/strings/en-US.json +++ b/web/src/i18n/strings/en-US.json @@ -286,5 +286,605 @@ "OBD.pages.components.NodeConfig.NodeConfigurationPreviousStep": "Node Configuration-Previous Step", "OBD.pages.components.NodeConfig.AreYouSureYouWant": "Are you sure to delete the configuration of this Zone?", "OBD.pages.components.ClusterConfig.PortObproxyOfExporterIs": "Used for Prometheus to pull OBProxy monitoring data.", - "OBD.pages.components.InstallConfig.OptionalComponents": "Optional components" + "OBD.pages.components.InstallConfig.OptionalComponents": "Optional components", + "OBD.pages.Guide.OceanbaseAndSupportingTools": "OceanBase and supporting tools", + "OBD.pages.Guide.DistributedDatabasesAndVariousTools": "Distributed databases and various tools to facilitate customer management, operation and maintenance", + "OBD.pages.Guide.OceanbaseCloudPlatformFullLifecycle": "OceanBase cloud platform: full lifecycle management of OB clusters", + "OBD.pages.Guide.OceanbaseDeveloperCenterManageDatabases": "OceanBase Developer Center: manage databases and tables", + "OBD.pages.Guide.OceanbaseDataMigrationFastData": "OceanBase data migration: fast data migration", + "OBD.pages.Guide.TheProductIsUnderConstruction": "The product is under construction.", + "OBD.pages.Guide.SelectAnInstallationProduct": "Select an installation product", + "OBD.pages.Guide.HelpDocument": "Help document", + "OBD.pages.Guide.WelcomeToTheOceanbaseDeployment": "Welcome to the OceanBase Deployment Wizard", + "OBD.pages.Guide.WizardSelectDeploymentTool": "Wizard-select deployment tool", + "OBD.pages.Guide.Ok": "OK", + "OBD.Obdeploy.ClusterConfig.ConfigTable.ParameterValue": "Parameter value", + "OBD.pages.Obdeploy.InstallConfig.ItStartsWithALetter": "It starts with a letter, ends with a number, and can contain English, numbers, and underscores. The length is 2 to 32.", + "OBD.pages.Obdeploy.InstallConfig.PreviousStep": "Previous step", + "OBD.OcpInstaller.Configuration.MetadbConnectionFailedPleaseCheck": "MetaDB connection failed. Please check the connection configuration.", + "OBD.OcpInstaller.Configuration.IKnow": "I know", + "OBD.OcpInstaller.Error.403.SorryYouAreNotAuthorized": "Sorry, you are not authorized to access this page.", + "OBD.OcpInstaller.Error.403.ReturnToHomePage": "Return to Home Page", + "OBD.OcpInstaller.Error.404.SorryThePageYouVisited": "Sorry, the page you visited does not exist.", + "OBD.OcpInstaller.Error.404.ReturnToHomePage": "Return to Home Page", + "OBD.OcpInstaller.Index.LifecycleManagementOM": "Lifecycle management (O & M)", + "OBD.OcpInstaller.Index.OcpImplementsUnifiedManagementOf": "OCP implements unified management of OceanBase resources, and implements full lifecycle management of resource creation, backup and recovery, monitoring and alerting, inspection, autonomy, upgrade, and deletion.", + "OBD.OcpInstaller.Index.MonitoringAlarm": "Monitoring Alarm", + "OBD.OcpInstaller.Index.OcpMonitorsOceanbaseFromDifferent": "OCP monitors OceanBase from different dimensions such as hosts, clusters, and tenants, and provides various alert methods such as DingTalk, WeChat, and email to ensure cluster security.", + "OBD.OcpInstaller.Index.BackupAndRecovery": "Backup and Recovery", + "OBD.OcpInstaller.Index.OcpProvidesBackupAndRecovery": "OCP provides backup and recovery capabilities for OceanBase clusters and tenants. It supports automatic backup of full, incremental, and log files to storage types such as NAS and OSS, and supports one-click recovery operations.", + "OBD.OcpInstaller.Index.DiagnosticOptimization": "Diagnostic optimization", + "OBD.OcpInstaller.Index.OcpProvidesClosedLoopDiagnostics": "OCP provides closed-loop diagnostics for SQL from perception, root cause analysis, and execution recommendations. OCP also provides diagnostic capabilities from the dimensions of Cluster Replication, session, deadlock, and capacity.", + "OBD.OcpInstaller.Index.UpgradeWelcomePage": "Upgrade welcome page", + "OBD.OcpInstaller.Index.WelcomeToTheOcpUpgrade": "Welcome to the OCP Upgrade Wizard", + "OBD.OcpInstaller.Index.StartUpgradingToV": "Start upgrading to V 2.3.2", + "OBD.OcpInstaller.Index.InstallTheWelcomePage": "Install the welcome page", + "OBD.OcpInstaller.Index.WelcomeToTheOcpDeployment": "Welcome to the OCP Deployment Wizard", + "OBD.OcpInstaller.Index.SelectAMetadbConfigurationMethod": "Select a MetaDB configuration method for OCP", + "OBD.OcpInstaller.Index.MetadbIsAnImportantPart": "MetaDB is an important part of OCP. MetaDB provides the underlying storage capability for OCP's metadata management and monitoring data. OCP-Server provides you with OceanBase database lifecycle management services by calling MetaDB data.", + "OBD.OcpInstaller.Index.CreateANewOceanbaseDatabase": "Create a new OceanBase database", + "OBD.OcpInstaller.Index.MetadbAsOcp": "MetaDB as OCP", + "OBD.OcpInstaller.Index.Recommend": "Recommend", + "OBD.OcpInstaller.Index.UseAnExistingOceanbaseDatabase": "Use an existing OceanBase database", + "OBD.OcpInstaller.Index.PreviousStep": "Previous step", + "OBD.OcpInstaller.Index.Ok": "OK", + "OBD.Component.ModifyResourcePoolModal.NoResourcesFound": "No resources found", + "OBD.Component.ModifyResourcePoolModal.SystemPreOccupation": "System pre-occupation", + "OBD.Component.ModifyResourcePoolModal.OcpServiceReservation": "OCP service Reservation", + "OBD.Component.ModifyResourcePoolModal.CommonTenantReservation": "Common tenant Reservation", + "OBD.Component.ModifyResourcePoolModal.ResourceAllocation": "Resource allocation", + "OBD.Component.ModifyResourcePoolModal.BasedOnTheMinimumAvailable": "Based on the minimum available resources in the current environment, we recommend that you allocate the following resources for MetaDB:", + "OBD.Component.ModifyResourcePoolModal.DataFile": "Data File", + "OBD.Component.ModifyResourcePoolModal.TheDataFileSpaceIs": "The data file space is insufficient. By default, the data file size is three times that of memory_limit.", + "OBD.Component.ModifyResourcePoolModal.LogFile": "Log File", + "OBD.Component.ModifyResourcePoolModal.TheLogFileHasInsufficient": "The log file has insufficient space. By default, the log file size is three times that of memory_limit.", + "OBD.Install.Component.SystemConfig.InvalidIpAddress": "Invalid IP address", + "OBD.Install.Component.SystemConfig.InstallAndDeployMetadbConfiguration": "Install and deploy MetaDB configuration page", + "OBD.Install.Component.SystemConfig.SystemConfiguration": "System Configuration", + "OBD.Install.Component.SystemConfig.ToAvoidOperatingSystemUser": "To avoid operating system user conflicts, configure independent operating system users for MetaDB and OCP", + "OBD.Install.Component.SystemConfig.SelectHost": "Select host", + "OBD.Install.Component.SystemConfig.EnterAnIpAddress": "Enter an IP address", + "OBD.Install.Component.SystemConfig.PleaseEnter": "Please enter", + "OBD.Install.Component.SystemConfig.HostUser": "Host user", + "OBD.Install.Component.SystemConfig.EnterAHostUser": "Enter a host User", + "OBD.Install.Component.SystemConfig.UserPassword": "User password", + "OBD.Install.Component.SystemConfig.IfYouHaveSetPassword": "If you have set password-free, ignore this option.", + "OBD.Install.Component.SystemConfig.MetadbConfiguration": "MetaDB configuration", + "OBD.Install.Component.SystemConfig.ClusterName": "Cluster name", + "OBD.Install.Component.SystemConfig.EnterAClusterName": "Enter a cluster name", + "OBD.Install.Component.SystemConfig.RootSysPassword": "root @ sys password", + "OBD.Install.Component.SystemConfig.EnterOrRandomlyGenerateThe": "Enter or randomly generate the root @ sys password.", + "OBD.Install.Component.SystemConfig.SoftwarePath": "Software path", + "OBD.Install.Component.SystemConfig.EnterTheSoftwarePath": "Enter the software path", + "OBD.Install.Component.SystemConfig.DataPath": "Data path", + "OBD.Install.Component.SystemConfig.EnterADataPath": "Enter a data path", + "OBD.Install.Component.SystemConfig.LogPath": "Log path", + "OBD.Install.Component.SystemConfig.EnterALogPath": "Enter a log path", + "OBD.Install.Component.SystemConfig.SqlPort": "SQL Port", + "OBD.Install.Component.SystemConfig.TheSqlPortCannotBe": "The SQL Port cannot be the same as the RPC port.", + "OBD.Install.Component.SystemConfig.RpcPort": "rpc Port", + "OBD.Install.Component.SystemConfig.TheRpcPortCannotBe": "The RPC Port cannot be the same as the SQL port.", + "OBD.Install.Component.SystemConfig.NicName": "Nic name", + "OBD.Install.Component.SystemConfig.AutomaticConfiguration": "Automatic configuration", + "OBD.Install.Component.SystemConfig.ManualConfiguration": "Manual configuration", + "OBD.Install.Component.SystemConfig.EnterANicName": "Enter a nic name", + "OBD.Install.Component.SystemConfig.AMaximumOfCharactersCan": "A maximum of 13 characters can be entered.", + "OBD.Install.Component.SystemConfig.EnterTheNameOfThe": "Enter the name of the NIC device bound to OBServer.", + "OBD.OcpInstaller.Install.CreateANewMetadbMetadb": "Create a new MetaDB. MetaDB and OCP-Server use the same host deployment service. OCP-Server will access local MetaDB for better service reliability.", + "OBD.Layout.BasicLayout.InstallationDeploymentAndUpgradeSystem": "Installation, deployment, and upgrade system information", + "OBD.Layout.BasicLayout.OcpUpgradeWizardVersionNumber": "OCP Upgrade Wizard (version number: 4.0)", + "OBD.Layout.BasicLayout.OcpDeploymentWizardVersionNumber": "OCP Deployment Wizard (version number: 4.0)", + "OBD.Layout.BasicLayout.VisitTheOfficialWebsite": "Visit the official website", + "OBD.Layout.BasicLayout.HelpCenter": "Help Center", + "OBD.OcpInstaller.Layout.OceanbaseCloudPlatform": "OceanBase cloud platform", + "OBD.OcpInstaller.Quit.TheUpgradeProgramHasExited": "The upgrade program has exited.", + "OBD.OcpInstaller.Quit.TheDeploymentInstallerHasExited": "The deployment installer has exited!", + "OBD.OcpInstaller.Quit.TheUpgradeProgramHasQuit": "The upgrade program has quit. To enable the upgrade program again, run it in the system.", + "OBD.OcpInstaller.Quit.ToEnableTheDeploymentProgram": "To enable the deployment program again, run", + "OBD.OcpInstaller.Quit.ExecuteOcpN": "Execute ocp_N", + "OBD.Component.ConnectionInfo.ComponentName": "Component name", + "OBD.Component.ConnectionInfo.NodeIp": "Node IP", + "OBD.Component.ConnectionInfo.TheInstallerAutomaticallyObtainsMetadb": "The installer automatically obtains MetaDB configuration information based on the current host OCP environment. Check whether the MetaDB configuration information is correct. OCP will perform the upgrade program based on the following information.", + "OBD.Component.ConnectionInfo.ConnectionInformation": "Connection information", + "OBD.Component.ConnectionInfo.AccessAddress": "Access address", + "OBD.Component.ConnectionInfo.EnterAnAccessAddress": "Enter an access address", + "OBD.Component.ConnectionInfo.EnterADatabaseAccessIp": "Enter a database access IP address", + "OBD.Component.ConnectionInfo.AccessPort": "Access Port", + "OBD.Component.ConnectionInfo.EnterAnAccessPort": "Enter an access port", + "OBD.Component.ConnectionInfo.EnterTheDatabaseConnectionPort": "Enter the database connection port", + "OBD.Component.ConnectionInfo.DatabaseName": "Database name", + "OBD.Component.ConnectionInfo.EnterADatabaseName": "Enter a database name", + "OBD.Component.ConnectionInfo.AccessAccount": "Access account", + "OBD.Component.ConnectionInfo.EnterAnAccessAccount": "Enter an access account", + "OBD.Component.ConnectionInfo.AccessPassword": "Access password", + "OBD.Component.ConnectionInfo.EnterAnAccessPassword": "Enter an access password", + "OBD.Component.ConnectionInfo.PleaseEnter": "Please enter", + "OBD.Component.ConnectionInfo.Verification": "Verification", + "OBD.Component.ConnectionInfo.TheCurrentVerificationFailedPlease": "The current verification failed. Please fill in the error parameter again.", + "OBD.Component.ConnectionInfo.TheVerificationIsSuccessfulPlease": "The verification is successful. Please enter the following parameters.", + "OBD.Component.ConnectionInfo.OperatingSystemUsers": "Operating system users", + "OBD.Component.ConnectionInfo.Username": "Username", + "OBD.Component.ConnectionInfo.EnterAUsername": "Enter a username", + "OBD.Component.ConnectionInfo.PleaseProvideTheUserName": "Please provide the user name to automatically configure the platform-specific operating system user.", + "OBD.Component.ConnectionInfo.Password": "Password", + "OBD.Component.ConnectionInfo.EnterAPassword": "Enter a password", + "OBD.Component.ConnectionInfo.TheVerificationIsSuccessfulProceed": "The verification is successful. Proceed to the next step.", + "OBD.Component.ConnectionInfo.TheCurrentVerificationFailedPlease.1": "The current verification failed. Please enter it again.", + "OBD.Component.UpdatePreCheck.CheckItems": "Check items", + "OBD.Component.UpdatePreCheck.CheckStatus": "Check status", + "OBD.Component.UpdatePreCheck.Impact": "Impact", + "OBD.Component.UpdatePreCheck.UpgradeEnvironmentPreCheckPage": "Upgrade environment Pre-Check page", + "OBD.Component.UpdatePreCheck.BasedOnTheMetadbConfiguration": "Based on the MetaDB configuration information, OCP configuration information is successfully obtained. To ensure the consistency of management functions, the upgrade program upgrades the platform management service (OCP Server) and all host proxy services (OCP Agent) it manages, check and confirm the following configuration information, and then start the pre-check", + "OBD.Component.UpdatePreCheck.InstallationConfiguration": "Installation configuration", + "OBD.Component.UpdatePreCheck.ClusterName": "Cluster name", + "OBD.Component.UpdatePreCheck.UpgradeType": "Upgrade Type", + "OBD.Component.UpdatePreCheck.UpgradeAll": "Upgrade all", + "OBD.Component.UpdatePreCheck.UpgradeConfigurationInformation": "Upgrade configuration information", + "OBD.Component.UpdatePreCheck.PreUpgradeVersion": "Pre-upgrade version:", + "OBD.Component.UpdatePreCheck.UpgradedVersion": "Upgraded version:", + "OBD.Component.UpdatePreCheck.ComponentName": "Component name", + "OBD.Component.UpdatePreCheck.NodeIp": "Node IP", + "OBD.Component.UpdatePreCheck.AreYouSureYouWant": "Are you sure you want to ignore all failed checks?", + "OBD.Component.UpdatePreCheck.UpgradeIgnoresAllFailedItems": "Upgrade ignores all failed items", + "OBD.Component.UpdatePreCheck.IgnoreAllFailedItems": "Ignore all failed items", + "OBD.Component.UpdatePreCheck.PreCheckIsInProgress": "Pre-check is in progress, and re-check is not supported.", + "OBD.Component.UpdatePreCheck.UpgradeAndReCheck": "Upgrade and re-check", + "OBD.Component.UpdatePreCheck.ReCheck": "Re-check", + "OBD.OcpInstaller.Update.UnableToObtainOcpConfiguration": "Unable to obtain OCP configuration information. Check whether the connection is OCP MetaBase configuration.", + "OBD.OcpInstaller.Update.IKnow": "I know", + "OBD.OcpInstaller.Update.TheCurrentVersionCannotBe": "The current version cannot be upgraded to the Target version.", + "OBD.OcpInstaller.Update.TheCurrentVersionOfOcp": "The current version of OCP is V 3.0.0. Currently, you cannot directly upgrade to V 4.1.0. You can use OCP.\nAccess address", + "OBD.OcpInstaller.Update.ViewVersionDetailsForMore": "View version details\nFor more information about the upgrade path of the OCP version, see", + "OBD.OcpInstaller.Update.VersionReleaseRecord": "Version release record", + "OBD.OcpInstaller.Update.InThePreCheckProcess": "In the pre-check process, the previous step is not supported.", + "OBD.OcpInstaller.Update.PreviousStep": "Previous step", + "OBD.OcpInstaller.Update.InThePreCheckProcess.1": "In the pre-check process, the next step is not supported.", + "OBD.OcpInstaller.Update.PreCheck": "Pre-Check", + "OBD.OcpInstaller.Update.NextStep": "Next Step", + "OBD.OcpInstaller.Update.UpgradeAgain": "Upgrade Again", + "OBD.OcpInstaller.Welcome.WelcomeToTheOcpUpgrade": "Welcome to the OCP Upgrade Wizard", + "OBD.OcpInstaller.Welcome.StartUpgrade": "Start upgrade", + "OBD.pages.constants.OcpParameterName": "OCP parameter name", + "OBD.src.utils.SelectTheCorrectOcpNode": "Select the correct OCP node", + "OBD.src.utils.EnterAPassword": "Enter a password", + "OBD.src.utils.ToCharactersInLength": "8 to 32 characters in length", + "OBD.src.utils.CanOnlyContainLettersNumbers": "Can only contain letters, numbers, and special characters (~! @ **** & *_-+ = |(){}[]:;,.? /'$\"<>)", + "OBD.src.utils.AtLeastUppercaseAndLowercase": "At least 2 uppercase and lowercase letters, numbers, and special characters", + "OBD.src.component.Access.NoOperationPermissionIsAvailable": "No operation permission is available. Please contact the administrator to activate the permission.", + "OBD.component.AobException.ReturnToHomePage": "Return to Home Page", + "OBD.component.ConnectConfig.MetadbConnectionFailedPleaseCheck": "MetaDB connection failed. Please check the connection configuration.", + "OBD.component.ConnectConfig.IKnow": "I know", + "OBD.component.ConnectConfig.ConnectionInformation": "Connection information", + "OBD.component.ConnectConfig.HostIp": "Host IP", + "OBD.component.ConnectConfig.EnterTheHostIpAddress": "Enter the host IP address.", + "OBD.component.ConnectConfig.TheHostIpAddressFormat": "The host IP address format is incorrect.", + "OBD.component.ConnectConfig.EnterADatabaseAccessIp": "Enter a database access IP address", + "OBD.component.ConnectConfig.AccessPort": "Access Port", + "OBD.component.ConnectConfig.EnterAnAccessPort": "Enter an access port", + "OBD.component.ConnectConfig.EnterTheDatabaseConnectionPort": "Enter the database connection port", + "OBD.component.ConnectConfig.AccessAccount": "Access account", + "OBD.component.ConnectConfig.EnterAnAccessAccount": "Enter an access account", + "OBD.component.ConnectConfig.AccessPassword": "Access password", + "OBD.component.ConnectConfig.OcpPlatformAdministratorAccountPassword": "OCP platform administrator account password", + "OBD.component.ConnectConfig.EnterAnAccessPassword": "Enter an access password", + "OBD.component.ConnectConfig.PleaseEnter": "Please enter", + "OBD.component.ConnectConfig.PreviousStep": "Previous step", + "OBD.component.ConnectConfig.NextStep": "Next Step", + "OBD.component.DeployConfig.EnterpriseLevelDataManagementPlatform": "Enterprise-level data management platform with OceanBase as the core to realize OceanBase lifecycle O & M Management", + "OBD.component.DeployConfig.FinancialLevelDistributedDatabasesAre": "Financial-level distributed databases are characterized by strong data consistency, high scalability, high cost performance, stability and reliability.", + "OBD.component.DeployConfig.OceanbaseADedicatedDatabaseProxy": "OceanBase a dedicated database proxy server to forward user SQL requests to the best target OBServer", + "OBD.component.DeployConfig.ProductName": "Product Name", + "OBD.component.DeployConfig.Version": "Version", + "OBD.component.DeployConfig.CommunityEdition": "Community Edition", + "OBD.component.DeployConfig.CommercialEdition": "Commercial Edition", + "OBD.component.DeployConfig.Description": "Description", + "OBD.component.DeployConfig.LearnMore": "Learn More", + "OBD.component.DeployConfig.ItStartsWithALetter": "It starts with a letter, ends with a number, and can contain English, numbers, and underscores. The length is 2 to 32.", + "OBD.component.DeployConfig.TheDeploymentNameWithValue": "The deployment name with {value} does not exist.", + "OBD.component.DeployConfig.ADeploymentNameWithValue": "A deployment name with {value} already exists. Please specify a new name.", + "OBD.component.DeployConfig.BasicConfiguration": "Basic configuration", + "OBD.component.DeployConfig.DeploymentConfiguration": "Deployment configuration", + "OBD.component.DeployConfig.ClusterName": "Cluster name", + "OBD.component.DeployConfig.PleaseEnter": "Please enter", + "OBD.component.DeployConfig.EnterAClusterName": "Enter a cluster name", + "OBD.component.DeployConfig.VersionSelection": "Version selection", + "OBD.component.DeployConfig.EstimatedInstallationRequirements": "Estimated installation requirements", + "OBD.component.DeployConfig.MbSpace": "MB space", + "OBD.component.DeployConfig.DeploymentConfigurationPreviousStep": "Deployment configuration-previous step", + "OBD.component.DeployConfig.PreviousStep": "Previous step", + "OBD.component.DeployConfig.DeploymentConfigurationNextStep": "Deployment configuration-Next Step", + "OBD.component.DeployConfig.NextStep": "Next Step", + "OBD.component.EnvPreCheck.CheckFailuredItem.OnlyManualFixes": "Only manual fixes", + "OBD.component.EnvPreCheck.CheckFailuredItem.AutomaticRepair": "Automatic Repair", + "OBD.component.EnvPreCheck.CheckFailuredItem.NoFailedItemsFoundYet": "No failed items found yet", + "OBD.component.EnvPreCheck.CheckFailuredItem.GreatCheckAllSuccessful": "Great! Check all successful!", + "OBD.component.EnvPreCheck.CheckFailuredItem.Reason": "Reason:", + "OBD.component.EnvPreCheck.CheckFailuredItem.Suggestions": "Suggestions:", + "OBD.component.EnvPreCheck.CheckFailuredItem.ManualRepair": "Manual repair", + "OBD.component.EnvPreCheck.CheckFailuredItem.LearnMore": "Learn More", + "OBD.component.EnvPreCheck.CheckItem.CheckItemPassedcountTotal": "Check item {passedCount}/{total}", + "OBD.component.EnvPreCheck.CheckItem.ReCheck": "Re-check", + "OBD.component.EnvPreCheck.CheckCompleted": "Check completed", + "OBD.component.EnvPreCheck.Checking": "Checking", + "OBD.component.EnvPreCheck.VerifyingThatYourEnvironmentMeets": "Verifying that your environment meets all the minimum requirements for installing and configuring MetaDB and OCP.", + "OBD.component.EnvPreCheck.InstallAndDeployOcpEnvironment": "Install and deploy OCP environment Pre-Check page", + "OBD.component.EnvPreCheck.InstallAndDeployMetadbEnvironment": "Install and deploy MetaDB environment Pre-Check page", + "OBD.src.component.ErrorBoundary.PageExecutionError": "Page execution error", + "OBD.src.component.ErrorBoundary.ReturnToHomePage": "Return to Home Page", + "OBD.src.component.ExitBtn.DeploymentConfigurationExit": "Deployment configuration-exit", + "OBD.src.component.ExitBtn.ExitTheOcpUpgradeProgram": "Exit the OCP upgrade program", + "OBD.src.component.ExitBtn.ExitTheOcpDeploymentInstaller": "Exit the OCP deployment installer", + "OBD.src.component.ExitBtn.AfterExitingTheUpgradeWill": "After exiting, the upgrade will be terminated. Proceed with caution.", + "OBD.src.component.ExitBtn.AfterExitingTheDeploymentAnd": "After exiting, the deployment and installation will be terminated. Proceed with caution.", + "OBD.src.component.ExitBtn.Exit": "Exit", + "OBD.component.InsstallResult.ComponentName": "Component name", + "OBD.component.InsstallResult.NodeIp": "Node IP", + "OBD.component.InsstallResult.UpgradeSuccessful": "Upgrade successful", + "OBD.component.InsstallResult.OcpUpgradedSuccessfully": "OCP upgraded successfully", + "OBD.component.InsstallResult.InstallationAndDeploymentNoMetadb": "Installation and deployment no MetaDB deployment succeeded", + "OBD.component.InsstallResult.OcpDeployedSuccessfully": "OCP deployed successfully", + "OBD.component.InsstallResult.MetadbIsDeployedSuccessfully": "MetaDB is deployed successfully.", + "OBD.component.InsstallResult.InstallationAndDeploymentMetadbDeployment": "Installation and deployment MetaDB deployment succeeded", + "OBD.component.InsstallResult.MetadbDeployedSuccessfully": "MetaDB deployed successfully", + "OBD.component.InsstallResult.UpgradeFailed": "Upgrade failed", + "OBD.component.InsstallResult.OcpUpgradeFailed": "OCP upgrade failed", + "OBD.component.InsstallResult.InstallationAndDeploymentNoMetadb.1": "Installation and deployment no MetaDB deployment failed", + "OBD.component.InsstallResult.OcpDeploymentFailed": "OCP deployment failed", + "OBD.component.InsstallResult.FailedToInstallAndDeploy": "Failed to install and deploy MetaDB deployment", + "OBD.component.InsstallResult.FailedToInstallAndDeploy.1": "Failed to install and deploy MetaDB deployment", + "OBD.component.InsstallResult.MetadbDeploymentFailed": "MetaDB deployment failed", + "OBD.component.InsstallResult.PleaseCheckTheLogInformation": "Please check the log information to obtain the cause of the failure and contact the technical support staff to handle it.", + "OBD.component.InsstallResult.UpgradeReport": "Upgrade report", + "OBD.component.InsstallResult.ThereAreHostsThatHave": "· There are hosts that have not been upgraded to OCP Agent. We recommend that you use OCP\nThe host management module of the platform installs the new version OCP Agent.\nHost not upgraded:", + "OBD.component.InsstallResult.PreUpgradeVersion": "Pre-upgrade version:", + "OBD.component.InsstallResult.UpgradedVersion": "Upgraded version:", + "OBD.component.InsstallResult.Click": "Click", + "OBD.component.InsstallResult.OcpReleaseRecords": "OCP release records", + "OBD.component.InsstallResult.LearnMoreAboutTheNew": "Learn more about the new version", + "OBD.component.InsstallResult.AccessAddressAndAccountSecret": "Access address and account secret information", + "OBD.component.InsstallResult.PleaseKeepTheFollowingAccess": "Please keep the following access address and account secret information properly and update OCP in time.\nInitial password. For more information, visit", + "OBD.component.InsstallResult.OceanbaseDocumentCenter": "OceanBase Document Center", + "OBD.component.InsstallResult.CopyInformation": "Copy Information", + "OBD.component.InsstallResult.AccessAddress": "Access address", + "OBD.component.InsstallResult.AdministratorAccount": "Administrator account", + "OBD.component.InsstallResult.InitialPassword": "Initial password", + "OBD.component.InstallProcess.Upgraded": "Upgraded", + "OBD.component.InstallProcess.Deploying": "Deploying", + "OBD.component.InstallProcess.Deploying.1": "Deploying", + "OBD.component.InstallProcess.UpgradeLogs": "Upgrade logs", + "OBD.component.InstallProcess.DeploymentLogs": "Deployment logs", + "OBD.component.InstallProcessNew.Upgrading": "Upgrading...", + "OBD.component.InstallResult.ComponentName": "Component name", + "OBD.component.InstallResult.NodeIp": "Node IP", + "OBD.component.InstallResult.UpgradeSuccessful": "Upgrade successful", + "OBD.component.InstallResult.OcpUpgradedSuccessfully": "OCP upgraded successfully", + "OBD.component.InstallResult.InstallationAndDeploymentNoMetadb": "Installation and deployment no MetaDB deployment succeeded", + "OBD.component.InstallResult.OcpDeployedSuccessfully": "OCP deployed successfully", + "OBD.component.InstallResult.MetadbIsDeployedSuccessfully": "MetaDB is deployed successfully.", + "OBD.component.InstallResult.UpgradeFailed": "Upgrade failed", + "OBD.component.InstallResult.OcpUpgradeFailed": "OCP upgrade failed", + "OBD.component.InstallResult.InstallationAndDeploymentNoMetadb.1": "Installation and deployment no MetaDB deployment failed", + "OBD.component.InstallResult.OcpDeploymentFailed": "OCP deployment failed", + "OBD.component.InstallResult.FailedToInstallAndDeploy": "Failed to install and deploy MetaDB deployment", + "OBD.component.InstallResult.PleaseCheckTheLogInformation": "Please check the log information to obtain the cause of the failure and contact the technical support staff to handle it.", + "OBD.component.InstallResult.UpgradeReport": "Upgrade report", + "OBD.component.InstallResult.ThereAreHostsThatHave": "· There are hosts that have not been upgraded to OCP Agent. We recommend that you use OCP\nThe host management module of the platform installs the new version OCP Agent.\nHost not upgraded:", + "OBD.component.InstallResult.PreUpgradeVersion": "Pre-upgrade version:", + "OBD.component.InstallResult.UpgradedVersion": "Upgraded version:", + "OBD.component.InstallResult.Click": "Click", + "OBD.component.InstallResult.OcpReleaseRecords": "OCP release records", + "OBD.component.InstallResult.LearnMoreAboutTheNew": "Learn more about the new version", + "OBD.component.InstallResult.AccessAddressAndAccountSecret": "Access address and account secret information", + "OBD.component.InstallResult.PleaseKeepTheFollowingAccess": "Please keep the following access address and account secret information properly and update OCP in time.\nInitial password. For more information, visit", + "OBD.component.InstallResult.OceanbaseDocumentCenter": "OceanBase Document Center", + "OBD.component.InstallResult.CopyInformation": "Copy Information", + "OBD.component.InstallResult.AccessAddress": "Access address", + "OBD.component.InstallResult.AdministratorAccount": "Administrator account", + "OBD.component.InstallResult.InitialPassword": "Initial password", + "OBD.component.InstallResult.UpgradeLogs": "Upgrade logs", + "OBD.component.InstallResult.DeploymentLogs": "Deployment logs", + "OBD.component.InstallResult.ExitTheInstaller": "Exit the installer", + "OBD.component.InstallResult.DoYouWantToExit": "Do you want to exit the page?", + "OBD.component.InstallResult.BeforeExitingMakeSureThat": "Before exiting, make sure that the access address and account secret information have been copied.", + "OBD.component.InstallResult.Exit": "Exit", + "OBD.component.InstallResult.Complete": "Complete", + "OBD.component.InstallResult.PreviousStep": "Previous step", + "OBD.component.InstallResult.PleaseConfirmWhetherTheInstallation": "Please confirm whether the installation failure reason has been located and fix the problem?", + "OBD.component.InstallResult.ReinstallationWillFirstCleanUp": "Reinstallation will first clean up the failed OCP installation environment.", + "OBD.component.InstallResult.Ok": "OK", + "OBD.component.InstallResult.Cancel": "Cancel", + "OBD.component.InstallResult.Redeploy": "Redeploy", + "OBD.component.MetaDBConfig.ClusterConfig.ThePortNumberCanOnly": "The port number can only range from 1024 to 65535.", + "OBD.component.MetaDBConfig.ClusterConfig.ClusterConfiguration": "Cluster configuration", + "OBD.component.MetaDBConfig.ClusterConfig.RootSysPassword": "root @ sys password", + "OBD.component.MetaDBConfig.ClusterConfig.PleaseEnter": "Please enter", + "OBD.component.MetaDBConfig.ClusterConfig.RandomlyGenerated": "Randomly generated", + "OBD.component.MetaDBConfig.ClusterConfig.SoftwareInstallationPath": "Software Installation Path", + "OBD.component.MetaDBConfig.ClusterConfig.DataPath": "Data path", + "OBD.component.MetaDBConfig.ClusterConfig.LogPath": "Log path", + "OBD.component.MetaDBConfig.ClusterConfig.SqlPort": "SQL Port", + "OBD.component.MetaDBConfig.ClusterConfig.RpcPort": "rpc Port", + "OBD.component.MetaDBConfig.ClusterConfig.MoreConfigurations": "More configurations", + "OBD.component.MetaDBConfig.ConfigTable.ClusterParameterName": "Cluster parameter name", + "OBD.component.MetaDBConfig.ConfigTable.ParameterValue": "Parameter value", + "OBD.component.MetaDBConfig.ConfigTable.Introduction": "Introduction", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.ItStartsWithALetter": "It starts with a letter and ends with a number. It can contain numbers and underscores and can be 2 to 32 characters in length.", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.ZoneNameAlreadyOccupied": "Zone name already occupied", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.EnterTheCorrectIpAddress": "Enter the correct IP address.", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.SelectTheCorrectObproxyNode": "Select the correct OBProxy node", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.ZoneName": "Zone name", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.AZoneThatRepresentsA": "A zone that represents a group of nodes with similar hardware availability in a cluster, usually in the same rack, data center, or region.", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.ThisItemIsRequired": "This item is required", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.ObserverNodes": "OBServer nodes", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.TheNodeWhereDatabaseService": "The node where Database Service (OBServer) resides, including SQL engine, transaction engine, and storage engine, and serves multiple data partitions.", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.RootserverNodes": "RootServer nodes", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.TheNodeWhereTheMaster": "The node where the Master Control Service (RootService) is located is used to perform cluster management, server management, and automatic load balancing.", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.ThisOptionIsRequired": "This option is required.", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.SelectTheCorrectRootserverNode": "Select the correct RootServer node", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.PleaseSelect": "Please select", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.DatabaseNodeConfiguration": "Database node configuration", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.AddZone": "Add Zone", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.KeepAtLeastOneZone": "Keep at least one zone", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.AreYouSureYouWant": "Are you sure you want to delete the configuration of this Zone?", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.DoNotEnterDuplicateNodes": "Do not enter duplicate nodes", + "OBD.component.MetaDBConfig.NodeConfig.OcpNodeConfiguration": "OCP node configuration", + "OBD.component.MetaDBConfig.NodeConfig.PleaseEnter": "Please enter", + "OBD.component.MetaDBConfig.NodeConfig.SelectHost": "Select host", + "OBD.component.MetaDBConfig.OBProxyConfig.ThePortNumberCanOnly": "The port number can only range from 1024 to 65535.", + "OBD.component.MetaDBConfig.OBProxyConfig.ObproxyConfiguration": "OBProxy configuration", + "OBD.component.MetaDBConfig.OBProxyConfig.PleaseEnter": "Please enter", + "OBD.component.MetaDBConfig.OBProxyConfig.ObproxyNodes": "OBProxy nodes", + "OBD.component.MetaDBConfig.OBProxyConfig.SqlPort": "SQL Port", + "OBD.component.MetaDBConfig.OBProxyConfig.PortExporter": "Port Exporter", + "OBD.component.MetaDBConfig.OBProxyConfig.SoftwarePath": "Software path", + "OBD.component.MetaDBConfig.OBProxyConfig.MoreConfigurations": "More configurations", + "OBD.component.MetaDBConfig.UserConfig.DeployUserConfiguration": "Deploy user configuration", + "OBD.component.MetaDBConfig.UserConfig.Username": "Username", + "OBD.component.MetaDBConfig.UserConfig.EnterAUsername": "Enter a username", + "OBD.component.MetaDBConfig.UserConfig.ItStartsWithALetter": "It starts with a letter and can contain English, numbers, underscores, and hyphens, and cannot exceed 32 digits.", + "OBD.component.MetaDBConfig.UserConfig.PleaseProvideTheHostUser": "Please provide the host user name to automatically configure the platform-specific operating system user.", + "OBD.component.MetaDBConfig.UserConfig.ViewHelpDocuments": "View help documents", + "OBD.component.MetaDBConfig.UserConfig.PasswordOptional": "Password (optional)", + "OBD.component.MetaDBConfig.UserConfig.IfYouHaveConfiguredPassword": "If you have configured password-free logon, you do not need to enter the password again.", + "OBD.component.MetaDBConfig.UserConfig.SshPort": "SSH Port", + "OBD.component.MetaDBConfig.UserConfig.PleaseEnter": "Please enter", + "OBD.component.MetaDBConfig.UserConfig.UseTheRunningUser": "Use the running user", + "OBD.component.MetaDBConfig.UserConfig.RunningUsername": "Running username", + "OBD.component.MetaDBConfig.UserConfig.EnterARunningUsername": "Enter a running username", + "OBD.component.MetaDBConfig.MetadbConfigurationPreviousStep": "MetaDB configuration-previous step", + "OBD.component.MetaDBConfig.PreviousStep": "Previous step", + "OBD.component.MetaDBConfig.MetadbConfigurationNext": "MetaDB configuration-Next", + "OBD.component.MetaDBConfig.NextStep": "Next Step", + "OBD.component.ModifyOCPResourcePoolModal.OcpServerMemory": "OCP-Server memory", + "OBD.component.ModifyOCPResourcePoolModal.OcpTenantMemory": "OCP tenant memory", + "OBD.component.ModifyOCPResourcePoolModal.MetadataTenantMemory": "Metadata tenant memory", + "OBD.component.ModifyOCPResourcePoolModal.MonitorDataTenantMemory": "Monitor data tenant memory", + "OBD.component.ModifyOCPResourcePoolModal.OtherUsedMemory": "Other used memory", + "OBD.component.ModifyOCPResourcePoolModal.RemainingMemory": "Remaining memory", + "OBD.component.ModifyOCPResourcePoolModal.ResourceAllocation": "Resource allocation", + "OBD.component.ModifyOCPResourcePoolModal.AccordingToTheResourcesOf": "According to the resources of the current host environment, allocate resources for OCP-related services as follows", + "OBD.component.ModifyOCPResourcePoolModal.MemoryAllocationMapGib": "Memory allocation map (GiB)", + "OBD.component.ModifyOCPResourcePoolModal.Memory": "Memory", + "OBD.component.ModifyOCPResourcePoolModal.OcpTenant": "OCP tenant", + "OBD.component.ModifyOCPResourcePoolModal.MetadataTenant": "Metadata tenant", + "OBD.component.ModifyOCPResourcePoolModal.MonitorDataTenants": "Monitor data tenants", + "OBD.component.MyDrawer.Cancel": "Cancel", + "OBD.component.MyDrawer.Ok": "OK", + "OBD.src.component.MyDropdown.All": "All", + "OBD.src.component.MyInput.PleaseEnter": "Please enter", + "OBD.src.component.MySelect.PleaseSelect": "Please select", + "OBD.component.NoAuth.NoPermissionToView": "No permission to view", + "OBD.component.NoAuth.ContactTheAdministratorToActivate": "Contact the administrator to activate permissions", + "OBD.component.OCPConfig.ThePasswordsEnteredTwiceAre": "The passwords entered twice are inconsistent. Please enter them again.", + "OBD.component.OCPConfig.InvalidIpAddress": "Invalid IP address", + "OBD.component.OCPConfig.SystemConfiguration": "System Configuration", + "OBD.component.OCPConfig.SelectHost": "Select host", + "OBD.component.OCPConfig.EnterAnIpAddress": "Enter an IP address", + "OBD.component.OCPConfig.PleaseEnter": "Please enter", + "OBD.component.OCPConfig.HostUser": "Host user", + "OBD.component.OCPConfig.PleaseProvideUsersOnThe": "Please provide users on the operating system for automatic configuration of the installer.", + "OBD.component.OCPConfig.EnterAnAdministratorAccount": "Enter an administrator account", + "OBD.component.OCPConfig.UserPassword": "User password", + "OBD.component.OCPConfig.IfYouHaveSetPassword": "If you have set password-free, ignore this option.", + "OBD.component.OCPConfig.OcpServiceConfiguration": "OCP service configuration", + "OBD.component.OCPConfig.ServiceConfiguration": "Service configuration", + "OBD.component.OCPConfig.ClusterName": "Cluster name", + "OBD.component.OCPConfig.EnterAClusterName": "Enter a cluster name", + "OBD.component.OCPConfig.AdminPassword": "Admin password", + "OBD.component.OCPConfig.OcpPlatformAdministratorAccountPassword": "OCP platform administrator account password", + "OBD.component.OCPConfig.EnterAPassword": "Enter a password", + "OBD.component.OCPConfig.SoftwarePath": "Software path", + "OBD.component.OCPConfig.EnterTheSoftwarePath": "Enter the software path", + "OBD.component.OCPConfig.ServicePort": "Service Port", + "OBD.component.OCPConfig.EnterAServicePort": "Enter a service port", + "OBD.component.OCPConfig.PortOcpagent": "Port ocpagent", + "OBD.component.OCPConfig.EnterPortOcpagent": "Enter Port ocpagent", + "OBD.component.OCPConfig.OcpagentMonitoringPort": "ocpagent monitoring port", + "OBD.component.OCPConfig.EnterOcpagentMonitoringPort": "Enter ocpagent monitoring port", + "OBD.component.OCPConfig.MetadataTenantConfiguration": "Metadata tenant configuration", + "OBD.component.OCPConfig.TenantName": "Tenant name", + "OBD.component.OCPConfig.EnterATenantName": "Enter a tenant name", + "OBD.component.OCPConfig.Password": "Password", + "OBD.component.OCPConfig.ConfirmPassword": "Confirm password", + "OBD.component.OCPConfig.PleaseEnterANewPassword": "Please enter a new password again", + "OBD.component.OCPConfig.MonitorDataTenantConfiguration": "Monitor data tenant configuration", + "OBD.component.OCPConfigNew.ResourcePlan.CopiedSuccessfully": "Copied successfully", + "OBD.component.OCPConfigNew.ResourcePlan.TheCurrentBrowserDoesNot": "The current browser does not support copying text.", + "OBD.component.OCPConfigNew.ResourcePlan.ResourcePlanning": "Resource Planning", + "OBD.component.OCPConfigNew.ResourcePlan.TheOcpServiceRunsWith": "The OCP service runs with computing and storage resources. You need to plan resources based on the size of objects to be managed, including OCP service, MetaDB, and MonitorDB.", + "OBD.component.OCPConfigNew.ResourcePlan.YouAreExpectedToNeed": "You are expected to need to manage:", + "OBD.component.OCPConfigNew.ResourcePlan.Host": "Host", + "OBD.component.OCPConfigNew.ResourcePlan.PleaseEnter": "Please enter", + "OBD.component.OCPConfigNew.ResourcePlan.Less": "Less", + "OBD.component.OCPConfigNew.ResourcePlan.Table": "Table", + "OBD.component.OCPConfigNew.ResourcePlan.ResourceConfiguration": "Resource configuration", + "OBD.component.OCPConfigNew.ResourcePlan.Memory": "Memory", + "OBD.component.OCPConfigNew.ResourcePlan.MetadataTenantConfiguration": "Metadata tenant configuration", + "OBD.component.OCPConfigNew.ResourcePlan.TenantName": "Tenant name", + "OBD.component.OCPConfigNew.ResourcePlan.EnterATenantName": "Enter a tenant name", + "OBD.component.OCPConfigNew.ResourcePlan.Password": "Password", + "OBD.component.OCPConfigNew.ResourcePlan.EnterAPassword": "Enter a password", + "OBD.component.OCPConfigNew.ResourcePlan.RandomlyGenerated": "Randomly generated", + "OBD.component.OCPConfigNew.ResourcePlan.PleaseRememberThePasswordOr": "Please remember the password, or", + "OBD.component.OCPConfigNew.ResourcePlan.CopyPassword": "Copy password", + "OBD.component.OCPConfigNew.ResourcePlan.AndKeepItProperly": "And keep it properly", + "OBD.component.OCPConfigNew.ResourcePlan.MonitorDataTenantConfiguration": "Monitor data tenant configuration", + "OBD.component.OCPConfigNew.ServiceConfig.WeRecommendThatYouUse": "We recommend that you use the server load balancer address as a portal for external access to OCP websites to achieve high availability of OCP services. If not, you can choose to use the node IP address + Port of OCP to set it. Please log on to OCP later and go to System Management-> system parameter change ocp.site.url (restart takes effect)", + "OBD.component.OCPConfigNew.ServiceConfig.CopiedSuccessfully": "Copied successfully", + "OBD.component.OCPConfigNew.ServiceConfig.TheCurrentBrowserDoesNot": "The current browser does not support text copying.", + "OBD.component.OCPConfigNew.ServiceConfig.ThePortNumberCanOnly": "The port number can only range from 1024 to 65535.", + "OBD.component.OCPConfigNew.ServiceConfig.ServiceConfiguration": "Service configuration", + "OBD.component.OCPConfigNew.ServiceConfig.EnterAPassword": "Enter a password", + "OBD.component.OCPConfigNew.ServiceConfig.AdminPassword": "Admin password", + "OBD.component.OCPConfigNew.ServiceConfig.ThePasswordMustBeTo": "The password must be 8 to 32 characters in length and can contain at least 2 large, lowercase letters, numbers, and special characters, the supported special characters are ~! @ >>>& *_\\-+ = |(){}[] :>:;,.?/", + "OBD.component.OCPConfigNew.ServiceConfig.RandomlyGenerated": "Randomly generated", + "OBD.component.OCPConfigNew.ServiceConfig.CopyPassword": "Copy password", + "OBD.component.OCPConfigNew.ServiceConfig.KeepThePasswordInMind": "Keep the password in mind, or copy the password and keep it properly.", + "OBD.component.OCPConfigNew.ServiceConfig.SoftwarePath": "Software path", + "OBD.component.OCPConfigNew.ServiceConfig.EnterTheSoftwarePath": "Enter the software path", + "OBD.component.OCPConfigNew.ServiceConfig.LogPath": "Log path", + "OBD.component.OCPConfigNew.ServiceConfig.EnterALogPath": "Enter a log path", + "OBD.component.OCPConfigNew.ServiceConfig.PackagePath": "Package path", + "OBD.component.OCPConfigNew.ServiceConfig.EnterThePackagePath": "Enter the package path", + "OBD.component.OCPConfigNew.ServiceConfig.AddressForExternalAccessTo": "Address for external access to OCP website: it must start with http/https, include VIP address/domain name/Port URL, and end without slash/", + "OBD.component.OCPConfigNew.ServiceConfig.EnterOcpSiteUrl": "Enter ocp.site.url", + "OBD.component.OCPConfigNew.ServiceConfig.TheCurrentVerificationIsSuccessful": "The current verification is successful. Proceed to the next step.", + "OBD.component.OCPConfigNew.ServiceConfig.TheCurrentVerificationFailedPlease": "The current verification failed. Please enter it again.", + "OBD.component.OCPConfigNew.ServiceConfig.Verification": "Verification", + "OBD.component.OCPConfigNew.ServiceConfig.ServicePort": "Service Port", + "OBD.component.OCPConfigNew.ServiceConfig.PleaseEnter": "Please enter", + "OBD.component.OCPConfigNew.OcpConfigurationPreviousStep": "ocp configuration-previous step", + "OBD.component.OCPConfigNew.PreviousStep": "Previous step", + "OBD.component.OCPConfigNew.OcpConfigurationNextStep": "ocp configuration-Next Step", + "OBD.component.OCPConfigNew.NextStep": "Next Step", + "OBD.OCPPreCheck.CheckInfo.BasicInfo.InstallationConfiguration": "Installation configuration", + "OBD.OCPPreCheck.CheckInfo.BasicInfo.ClusterName": "Cluster name", + "OBD.OCPPreCheck.CheckInfo.BasicInfo.InstallationType": "Installation type", + "OBD.OCPPreCheck.CheckInfo.BasicInfo.ProductVersion": "Product Version", + "OBD.OCPPreCheck.CheckInfo.BasicInfo.Product": "Product", + "OBD.OCPPreCheck.CheckInfo.BasicInfo.CommunityEdition": "Community Edition", + "OBD.OCPPreCheck.CheckInfo.BasicInfo.CommercialEdition": "Commercial Edition", + "OBD.OCPPreCheck.CheckInfo.BasicInfo.Version": "Version", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.ClusterConfiguration": "Cluster configuration", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.RootSysPassword": "root @ sys password", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.SoftwarePath": "Software path", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.DataPath": "Data path", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.LogPath": "Log path", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.MysqlPort": "mysql Port", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.RpcPort": "rpc Port", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.ObproxyConfiguration": "OBProxy configuration", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.ObproxyNodes": "OBProxy nodes", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.SqlPort": "SQL Port", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.PortExporter": "Port Exporter", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.ParameterValue": "Parameter value", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.AutomaticAllocation": "Automatic allocation", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.Introduction": "Introduction", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.ZoneName": "Zone name", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.ObServerNodes": "OB Server nodes", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.RootServerNodes": "Root Server nodes", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.DeployUserConfiguration": "Deploy user configuration", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.Username": "Username", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.Password": "Password", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.SshPort": "SSH Port", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.OcpNodeConfiguration": "OCP node configuration", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.DatabaseNodeConfiguration": "Database node configuration", + "OBD.OCPPreCheck.CheckInfo.ConnectInfo.ConnectionInformation": "Connection information", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.AdminPassword": "Admin password", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.SoftwarePath": "Software path", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.LogPath": "Log path", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.PackagePath": "Package path", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.DeployUserConfiguration": "Deploy user configuration", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.Username": "Username", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.Password": "Password", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.SshPort": "SSH Port", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.OcpDeploymentSelection": "OCP deployment selection", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.ServiceConfiguration": "Service configuration", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.ResourcePlanning": "Resource Planning", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.ManageTheNumberOfHosts": "Manage the number of hosts", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.ResourceConfiguration": "Resource configuration", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.Memory": "Memory", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.MetadataTenantConfiguration": "Metadata tenant configuration", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.TenantName": "Tenant name", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.MonitorDataTenantConfiguration": "Monitor data tenant configuration", + "OBD.OCPPreCheck.CheckInfo.InstallAll": "Install all", + "OBD.OCPPreCheck.CheckInfo.HostIp": "Host IP", + "OBD.OCPPreCheck.CheckInfo.AccessPort": "Access Port", + "OBD.OCPPreCheck.CheckInfo.AccessAccount": "Access account", + "OBD.OCPPreCheck.CheckInfo.Password": "Password", + "OBD.OCPPreCheck.CheckInfo.TheOcpInstallationInformationConfiguration": "The OCP installation information configuration has been completed. Check and confirm the following configuration information, and then start the pre-check.", + "OBD.OCPPreCheck.CheckInfo.PreCheckPreviousStep": "Pre-Check-previous step", + "OBD.OCPPreCheck.CheckInfo.PreviousStep": "Previous step", + "OBD.OCPPreCheck.CheckInfo.PreCheck": "Pre-Check", + "OBD.OCPPreCheck.CheckInfo.PreCheck.1": "Pre-Check", + "OBD.OCPPreCheck.PreCheck.AutomaticRepairSucceeded": "Automatic repair succeeded", + "OBD.OCPPreCheck.PreCheck.PreCheckResultReCheck": "Pre-check result-re-check", + "OBD.OCPPreCheck.PreCheck.ReCheck": "Re-check", + "OBD.OCPPreCheck.PreCheck.PreCheckResultAutomaticRepair": "Pre-check result-automatic repair", + "OBD.OCPPreCheck.PreCheck.AutomaticRepair": "Automatic Repair", + "OBD.OCPPreCheck.PreCheck.PreCheckResultsPreviousStep": "Pre-check results-previous step", + "OBD.OCPPreCheck.PreCheck.PreviousStep": "Previous step", + "OBD.OCPPreCheck.PreCheck.PreCheckFailedDeploymentGreyed": "Pre-Check failed-deployment greyed", + "OBD.OCPPreCheck.PreCheck.NextStep": "Next Step", + "OBD.OCPPreCheck.PreCheck.PreCheckSuccessfulDeployment": "Pre-Check successful-deployment", + "OBD.src.component.Password.ToCharactersInLength": "8 to 32 characters in length", + "OBD.src.component.Password.CanOnlyContainLettersNumbers": "Can only contain letters, numbers, and special characters ._+@#$%", + "OBD.src.component.Password.AtLeastUppercaseAndLowercase": "At least 2 uppercase and lowercase letters, numbers, and special characters", + "OBD.component.Result.Return": "Return", + "OBD.component.Result.ViewTaskDetails": "View task details", + "OBD.src.constant.configuration.DeploymentConfiguration": "Deployment configuration", + "OBD.src.constant.configuration.MetadbConfiguration": "MetaDB configuration", + "OBD.src.constant.configuration.OcpConfiguration": "OCP configuration", + "OBD.src.constant.configuration.PreCheck": "Pre-Check", + "OBD.src.constant.configuration.Deployment": "Deployment", + "OBD.src.constant.configuration.ObClusterConnectionConfiguration": "OB cluster connection configuration", + "OBD.src.constant.configuration.ConnectivityTest": "Connectivity Test", + "OBD.src.constant.configuration.EnvironmentPreCheck": "Environment pre-check", + "OBD.src.constant.configuration.OcpUpgrade": "OCP upgrade", + "OBD.src.constant.Checking": "Checking", + "OBD.src.constant.Pass": "Pass", + "OBD.src.constant.Failed": "Failed", + "OBD.src.constant.Ignored": "Ignored", + "OBD.src.constant.must-ignore.SimplifiedChinese": "Simplified Chinese", + "OBD.Component.ConnectionInfo.EnterAnAccount": "Enter an account", + "OBD.component.CustomPasswordInput.PasswordSettingsDoNotMeet": "Password settings do not meet the requirements.", + "OBD.component.CustomPasswordInput.CopiedSuccessfully": "Copied successfully", + "OBD.component.CustomPasswordInput.TheCurrentBrowserDoesNot": "The current browser does not support text copying.", + "OBD.component.CustomPasswordInput.KeepThePasswordInMind": "Keep the password in mind, or copy the password and keep it properly.", + "OBD.component.CustomPasswordInput.PleaseRememberThePasswordOr": "Please remember the password, or", + "OBD.component.CustomPasswordInput.CopyPassword": "Copy password", + "OBD.component.CustomPasswordInput.AndKeepItProperly": "And keep it properly", + "OBD.component.CustomPasswordInput.EnterAPassword": "Enter a password", + "OBD.component.CustomPasswordInput.RandomlyGenerated": "Randomly generated", + "OBD.component.DeployConfig.ItStartsWithALetter.1": "It starts with a letter, ends with a number, and can contain English, numbers, hyphens, and underscores. The length is 2 to 32.", + "OBD.src.component.ExitBtn.ExitTheOceanbaseDeploymentWizard": "Exit the OceanBase Deployment Wizard", + "OBD.component.MetaDBConfig.UserConfig.TheUserWhoRunsThe": "The user who runs the service.", + "OBD.src.utils.CanOnlyContainLettersNumbers.1": "Can only contain letters, numbers, and special characters._+ @$$%", + "OBD.component.OCPConfigNew.ServiceConfig.ThePasswordMustBeTo.1": "The password must be 8 to 32 characters in length and can contain at least 2 large, lowercase letters, numbers, and special characters, the supported special characters are._+ @ ##%", + "OBD.component.DeployConfig.UnableToObtainTheInstallation": "Unable to obtain the installation package. Please check the installation program configuration.", + "OBD.component.InstallResult.WeRecommendThatYouInstall": "We recommend that you install the new version OCP Agent in the host management module of the OCP platform for hosts that have not been upgraded to OCP Agent.", + "OBD.component.OCPConfigNew.ServiceConfig.ThePasswordMustBeTo.2": "The password must be 8 to 32 characters in length and can contain at least 2 large, lowercase letters, numbers, and special characters, the supported special characters are ~!@#%^&*_-+=`|(){}[]:;',.?/", + "OBD.src.utils.CanOnlyContainLettersNumbers.2": "Can only contain letters, numbers, and special characters ~!@#%^&*_-+=`|(){}[]:;',.?/", + "OBD.component.MetaDBConfig.UserConfig.OperatingSystemUsersRunningOcp": "Operating system users running OCP services", + "OBD.pages.Obdeploy.InstallConfig.OcpExpressOnlySupportsAnd": "OCP Express only supports 4.0 and later versions OceanBase Database.", + "OBD.pages.Obdeploy.InstallConfig.UnableToObtainTheInstallation": "Unable to obtain the installation package. Please check the installation program configuration.", + "OBD.component.MetaDBConfig.ClusterConfig.SqlPort.1": "SQL Port", + "OBD.component.MetaDBConfig.ClusterConfig.RpcPort.1": "RPC Port", + "OBD.component.PasswordCard.Password": "Password", + "OBD.component.InputPort.PleaseEnter": "Please enter", + "OBD.component.InputPort.ThePortNumberCanOnly": "The port number can only range from 1024 to 65535.", + "OBD.Component.ConnectionInfo.PasswordOptional": "Password (optional)", + "OBD.Component.ConnectionInfo.IfYouHaveConfiguredPassword": "If you have configured password-free logon, you do not need to enter the password again.", + "OBD.component.CustomPasswordInput.TheLengthShouldBeTo": "The length should be 8 to 32 characters.", + "OBD.component.CustomPasswordInput.CanOnlyContainLettersNumbers": "Can only contain letters, numbers, and special characters ~! @ **** & *_-+ = '|(){}[]:;',.?/", + "OBD.component.CustomPasswordInput.AtLeastUppercaseAndLowercase": "At least 2 uppercase and lowercase letters, numbers, and special characters", + "OBD.src.utils.TheLengthShouldBeTo": "The length should be 8 to 32 characters.", + "OBD.component.InsstallResult.ThereAreHostsThatHave.1": "· There are hosts that have not been upgraded to OCP Agent. We recommend that you use OCP\nThe host management module of the platform installs the new version OCP Agent.", + "OBD.component.InsstallResult.HostNotUpgraded": "Host not upgraded:", + "OBD.Component.ConnectionInfo.SshPort": "SSH Port", + "OBD.Component.UpdatePreCheck.MetadbSharesMetaTenantResources": "MetaDB shares Meta tenant resources with MonitorDB, which may cause OCP running exceptions. We strongly recommend that you create Monitor tenants, clean up MetaDB data, and migrate MonitorDB data. For more information, see 《", + "OBD.component.DeployConfig.IfTheCurrentEnvironmentCannot": "If the current environment cannot access the Internet properly, we recommend that you use OceanBase.\nInstall and deploy offline installer.", + "OBD.component.DeployConfig.GoToDownloadOfflineInstallation": "Go to download offline installation", + "OBD.component.DeployConfig.HowToEnableOnlineImage": "How to enable online image repository", + "OBD.component.OCPConfigNew.ResourcePlan.OcpApplicationMemory": "OCP application memory", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.OcpApplicationMemory": "OCP application memory" } diff --git a/web/src/i18n/strings/zh-CN.json b/web/src/i18n/strings/zh-CN.json index 1e58025..4a2716c 100644 --- a/web/src/i18n/strings/zh-CN.json +++ b/web/src/i18n/strings/zh-CN.json @@ -286,5 +286,605 @@ "OBD.pages.components.NodeConfig.AreYouSureYouWant": "确定删除该条 Zone 的相关配置吗?", "OBD.pages.components.ClusterConfig.PortObproxyOfExporterIs": "OBProxy 的 Exporter 端口,用于 Prometheus 拉取 OBProxy 监控数据。", "OBD.pages.components.InstallProcess.Deploying": "部署中...", - "OBD.pages.components.InstallConfig.OptionalComponents": "可选组件" + "OBD.pages.components.InstallConfig.OptionalComponents": "可选组件", + "OBD.pages.Guide.OceanbaseAndSupportingTools": "OceanBase 及配套工具", + "OBD.pages.Guide.DistributedDatabasesAndVariousTools": "分布式数据库以及各类工具,方便客户管理、运维和使用", + "OBD.pages.Guide.OceanbaseCloudPlatformFullLifecycle": "OceanBase 云平台:对 OB 集群进行全生命周期管理", + "OBD.pages.Guide.OceanbaseDeveloperCenterManageDatabases": "OceanBase 开发者中心:对数据库&表进行管理", + "OBD.pages.Guide.OceanbaseDataMigrationFastData": "OceanBase 数据迁移:对数据进行快速迁移", + "OBD.pages.Guide.TheProductIsUnderConstruction": "产品正在建设中", + "OBD.pages.Guide.SelectAnInstallationProduct": "请选择安装产品", + "OBD.pages.Guide.HelpDocument": "帮助文档", + "OBD.pages.Guide.WelcomeToTheOceanbaseDeployment": "欢迎使用 OceanBase 部署向导", + "OBD.pages.Guide.WizardSelectDeploymentTool": "向导-选择部署工具", + "OBD.pages.Guide.Ok": "确定", + "OBD.Obdeploy.ClusterConfig.ConfigTable.ParameterValue": "参数值", + "OBD.pages.Obdeploy.InstallConfig.ItStartsWithALetter": "以英文字母开头、英文或数字结尾,可包含英文、数字和下划线,且长度为 2 ~ 32", + "OBD.pages.Obdeploy.InstallConfig.PreviousStep": "上一步", + "OBD.OcpInstaller.Configuration.MetadbConnectionFailedPleaseCheck": "MetaDB 连接失败,请检查连接配置", + "OBD.OcpInstaller.Configuration.IKnow": "我知道了", + "OBD.OcpInstaller.Error.403.SorryYouAreNotAuthorized": "抱歉,你无权访问此页面", + "OBD.OcpInstaller.Error.403.ReturnToHomePage": "返回首页", + "OBD.OcpInstaller.Error.404.SorryThePageYouVisited": "抱歉,你访问的页面不存在", + "OBD.OcpInstaller.Error.404.ReturnToHomePage": "返回首页", + "OBD.OcpInstaller.Index.LifecycleManagementOM": "全生命周期管理(运维管控)", + "OBD.OcpInstaller.Index.OcpImplementsUnifiedManagementOf": "OCP 实现对 OceanBase 资源的统一管理,实现了对资源的创建、备份恢复、监控告警、巡检、自治、升级、删除等全生命周期管理。", + "OBD.OcpInstaller.Index.MonitoringAlarm": "监控告警", + "OBD.OcpInstaller.Index.OcpMonitorsOceanbaseFromDifferent": "OCP 支持从主机、集群、租户等不同维度对 OceanBase 进行监控,并且提供包括钉钉、微信、邮件等多种不同的告警方式,保障集群安全 。", + "OBD.OcpInstaller.Index.BackupAndRecovery": "备份恢复", + "OBD.OcpInstaller.Index.OcpProvidesBackupAndRecovery": "OCP 提供对 OceanBase 集群、租户的备份恢复能力,支持自动将全量、增量、日志备份到NAS、OSS等存储类型,支持一键恢复操作。", + "OBD.OcpInstaller.Index.DiagnosticOptimization": "诊断优化", + "OBD.OcpInstaller.Index.OcpProvidesClosedLoopDiagnostics": "OCP 针对 SQL 提供从感知、根因分析、执行建议的闭环诊断能力。OCP 同时还实现了从集群复制、会话、死锁、容量等维度的诊断能力。", + "OBD.OcpInstaller.Index.UpgradeWelcomePage": "升级欢迎页", + "OBD.OcpInstaller.Index.WelcomeToTheOcpUpgrade": "欢迎使用 OCP 升级向导", + "OBD.OcpInstaller.Index.StartUpgradingToV": "开始升级至 V 4.0.3", + "OBD.OcpInstaller.Index.InstallTheWelcomePage": "安装欢迎页", + "OBD.OcpInstaller.Index.WelcomeToTheOcpDeployment": "欢迎使用 OCP 部署向导", + "OBD.OcpInstaller.Index.SelectAMetadbConfigurationMethod": "请为 OCP 选择一个 MetaDB 的配置方式", + "OBD.OcpInstaller.Index.MetadbIsAnImportantPart": "MetaDB 是 OCP 重要组成部分,MetaDB 为 OCP 的管理元信息及监控数据提供底层存储能力,OCP-Server 通过调用 MetaDB 数据为您提供 OceanBase 数据库全生命周期管理服务。", + "OBD.OcpInstaller.Index.CreateANewOceanbaseDatabase": "创建全新的 OceanBase 数据库", + "OBD.OcpInstaller.Index.MetadbAsOcp": "作为 OCP 的 MetaDB", + "OBD.OcpInstaller.Index.Recommend": "推荐", + "OBD.OcpInstaller.Index.UseAnExistingOceanbaseDatabase": "使用已有的 OceanBase 数据库", + "OBD.OcpInstaller.Index.PreviousStep": "上一步", + "OBD.OcpInstaller.Index.Ok": "确定", + "OBD.Component.ModifyResourcePoolModal.NoResourcesFound": "未查询到资源", + "OBD.Component.ModifyResourcePoolModal.SystemPreOccupation": "系统预占用", + "OBD.Component.ModifyResourcePoolModal.OcpServiceReservation": "OCP 服务预留", + "OBD.Component.ModifyResourcePoolModal.CommonTenantReservation": "普通租户预留", + "OBD.Component.ModifyResourcePoolModal.ResourceAllocation": "资源分配", + "OBD.Component.ModifyResourcePoolModal.BasedOnTheMinimumAvailable": "根据当前环境最小可用资源计算,建议为 MetaDB 分配的资源如下:", + "OBD.Component.ModifyResourcePoolModal.DataFile": "数据文件", + "OBD.Component.ModifyResourcePoolModal.TheDataFileSpaceIs": "数据文件空间不足,数据文件大小默认为 memory_limit 的 3 倍", + "OBD.Component.ModifyResourcePoolModal.LogFile": "日志文件", + "OBD.Component.ModifyResourcePoolModal.TheLogFileHasInsufficient": "日志文件空间不足,日志文件大小默认为 memory_limit 的 3 倍", + "OBD.Install.Component.SystemConfig.InvalidIpAddress": "IP 地址不合法", + "OBD.Install.Component.SystemConfig.InstallAndDeployMetadbConfiguration": "安装部署MetaDB配置页", + "OBD.Install.Component.SystemConfig.SystemConfiguration": "系统配置", + "OBD.Install.Component.SystemConfig.ToAvoidOperatingSystemUser": "为了避免操作系统用户冲突,请为 MetaDB 及 OCP 配置独立的操作系统用户", + "OBD.Install.Component.SystemConfig.SelectHost": "选择主机", + "OBD.Install.Component.SystemConfig.EnterAnIpAddress": "请输入 IP 地址", + "OBD.Install.Component.SystemConfig.PleaseEnter": "请输入", + "OBD.Install.Component.SystemConfig.HostUser": "主机用户", + "OBD.Install.Component.SystemConfig.EnterAHostUser": "请输入主机用户", + "OBD.Install.Component.SystemConfig.UserPassword": "用户密码", + "OBD.Install.Component.SystemConfig.IfYouHaveSetPassword": "如果您已设置免密,请忽略本选项", + "OBD.Install.Component.SystemConfig.MetadbConfiguration": "MetaDB 配置", + "OBD.Install.Component.SystemConfig.ClusterName": "集群名称", + "OBD.Install.Component.SystemConfig.EnterAClusterName": "请输入集群名称", + "OBD.Install.Component.SystemConfig.RootSysPassword": "root@sys 密码", + "OBD.Install.Component.SystemConfig.EnterOrRandomlyGenerateThe": "请输入或随机生成 root@sys 密码", + "OBD.Install.Component.SystemConfig.SoftwarePath": "软件路径", + "OBD.Install.Component.SystemConfig.EnterTheSoftwarePath": "请输入软件路径", + "OBD.Install.Component.SystemConfig.DataPath": "数据路径", + "OBD.Install.Component.SystemConfig.EnterADataPath": "请输入数据路径", + "OBD.Install.Component.SystemConfig.LogPath": "日志路径", + "OBD.Install.Component.SystemConfig.EnterALogPath": "请输入日志路径", + "OBD.Install.Component.SystemConfig.SqlPort": "sql 端口", + "OBD.Install.Component.SystemConfig.TheSqlPortCannotBe": "SQL 端口不可与 RPC 端口相同", + "OBD.Install.Component.SystemConfig.RpcPort": "rpc 端口", + "OBD.Install.Component.SystemConfig.TheRpcPortCannotBe": "RPC 端口不可与 SQL 端口相同", + "OBD.Install.Component.SystemConfig.NicName": "网卡名称", + "OBD.Install.Component.SystemConfig.AutomaticConfiguration": "自动配置", + "OBD.Install.Component.SystemConfig.ManualConfiguration": "手动配置", + "OBD.Install.Component.SystemConfig.EnterANicName": "请输入网卡名称", + "OBD.Install.Component.SystemConfig.AMaximumOfCharactersCan": "最长可输入13个字符", + "OBD.Install.Component.SystemConfig.EnterTheNameOfThe": "请输入OBServer 绑定的网卡设备名", + "OBD.OcpInstaller.Install.CreateANewMetadbMetadb": "创建全新的 MetaDB,MetaDB 与 OCP-Server 将使用相同的主机部署服务。OCP-Server 将访问本地 MetaDB 以获得更好的服务可靠性。", + "OBD.Layout.BasicLayout.InstallationDeploymentAndUpgradeSystem": "安装部署升级系统信息", + "OBD.Layout.BasicLayout.OcpUpgradeWizardVersionNumber": "OCP 升级向导(版本号: 4.0.3)", + "OBD.Layout.BasicLayout.OcpDeploymentWizardVersionNumber": "OCP 部署向导(版本号: 4.0.3)", + "OBD.Layout.BasicLayout.VisitTheOfficialWebsite": "访问官网", + "OBD.Layout.BasicLayout.HelpCenter": "帮助中心", + "OBD.OcpInstaller.Layout.OceanbaseCloudPlatform": "OceanBase 云平台", + "OBD.OcpInstaller.Quit.TheUpgradeProgramHasExited": "升级程序已退出", + "OBD.OcpInstaller.Quit.TheDeploymentInstallerHasExited": "部署安装程序已经退出!", + "OBD.OcpInstaller.Quit.TheUpgradeProgramHasQuit": "升级程序已退出 如需再次启用升级程序,请在系统中执行", + "OBD.OcpInstaller.Quit.ToEnableTheDeploymentProgram": "如需再次启用部署程序,请在系统中执行", + "OBD.OcpInstaller.Quit.ExecuteOcpN": "执行ocp_N", + "OBD.Component.ConnectionInfo.ComponentName": "组件名称", + "OBD.Component.ConnectionInfo.NodeIp": "节点 IP", + "OBD.Component.ConnectionInfo.TheInstallerAutomaticallyObtainsMetadb": "安装程序根据当前主机 OCP 环境自动获取 MetaDB 配置信息,请检查 MetaDB 配置信息是否正确,OCP 将根据以下信息执行升级程序", + "OBD.Component.ConnectionInfo.ConnectionInformation": "连接信息", + "OBD.Component.ConnectionInfo.AccessAddress": "访问地址", + "OBD.Component.ConnectionInfo.EnterAnAccessAddress": "请输入访问地址", + "OBD.Component.ConnectionInfo.EnterADatabaseAccessIp": "请输入数据库访问 IP 地址", + "OBD.Component.ConnectionInfo.AccessPort": "访问端口", + "OBD.Component.ConnectionInfo.EnterAnAccessPort": "请输入访问端口", + "OBD.Component.ConnectionInfo.EnterTheDatabaseConnectionPort": "请输入数据库连接访问端口", + "OBD.Component.ConnectionInfo.DatabaseName": "数据库名", + "OBD.Component.ConnectionInfo.EnterADatabaseName": "请输入数据库名", + "OBD.Component.ConnectionInfo.AccessAccount": "访问账号", + "OBD.Component.ConnectionInfo.EnterAnAccessAccount": "请输入访问账号", + "OBD.Component.ConnectionInfo.AccessPassword": "访问密码", + "OBD.Component.ConnectionInfo.EnterAnAccessPassword": "请输入访问密码", + "OBD.Component.ConnectionInfo.PleaseEnter": "请输入", + "OBD.Component.ConnectionInfo.Verification": "验 证", + "OBD.Component.ConnectionInfo.TheCurrentVerificationFailedPlease": "当前验证失败,请重新填写错误参数", + "OBD.Component.ConnectionInfo.TheVerificationIsSuccessfulPlease": "当前验证成功,请填写下方参数", + "OBD.Component.ConnectionInfo.OperatingSystemUsers": "操作系统用户", + "OBD.Component.ConnectionInfo.Username": "用户名", + "OBD.Component.ConnectionInfo.EnterAUsername": "请输入用户名", + "OBD.Component.ConnectionInfo.PleaseProvideTheUserName": "请提供用户名用以自动化配置平台专用操作系统用户", + "OBD.Component.ConnectionInfo.Password": "密码", + "OBD.Component.ConnectionInfo.EnterAPassword": "请输入密码", + "OBD.Component.ConnectionInfo.TheVerificationIsSuccessfulProceed": "当前验证成功,请进行下一步", + "OBD.Component.ConnectionInfo.TheCurrentVerificationFailedPlease.1": "当前验证失败,请重新输入", + "OBD.Component.UpdatePreCheck.CheckItems": "检查项", + "OBD.Component.UpdatePreCheck.CheckStatus": "检查状态", + "OBD.Component.UpdatePreCheck.Impact": "影响", + "OBD.Component.UpdatePreCheck.UpgradeEnvironmentPreCheckPage": "升级环境预检查页", + "OBD.Component.UpdatePreCheck.BasedOnTheMetadbConfiguration": "根据 MetaDB 配置信息,成功获取 OCP 相关配置信息,为保证管理功能一致性,升级程序将升级平台管理服务(OCP Server) 及其管理的所有主机代理服务(OCP Agent),请检查并确认以下配置信息,确定后开始预检查", + "OBD.Component.UpdatePreCheck.InstallationConfiguration": "安装配置", + "OBD.Component.UpdatePreCheck.ClusterName": "集群名称", + "OBD.Component.UpdatePreCheck.UpgradeType": "升级类型", + "OBD.Component.UpdatePreCheck.UpgradeAll": "全部升级", + "OBD.Component.UpdatePreCheck.UpgradeConfigurationInformation": "升级配置信息", + "OBD.Component.UpdatePreCheck.PreUpgradeVersion": "升级前版本:", + "OBD.Component.UpdatePreCheck.UpgradedVersion": "升级后版本:", + "OBD.Component.UpdatePreCheck.ComponentName": "组件名称", + "OBD.Component.UpdatePreCheck.NodeIp": "节点 IP", + "OBD.Component.UpdatePreCheck.AreYouSureYouWant": "确认要忽略所有未通过的检查项吗?", + "OBD.Component.UpdatePreCheck.UpgradeIgnoresAllFailedItems": "升级忽略全部未通过项", + "OBD.Component.UpdatePreCheck.IgnoreAllFailedItems": "忽略全部未通过项", + "OBD.Component.UpdatePreCheck.PreCheckIsInProgress": "预检查进行中,暂不支持重新检查", + "OBD.Component.UpdatePreCheck.UpgradeAndReCheck": "升级重新检查", + "OBD.Component.UpdatePreCheck.ReCheck": "重新检查", + "OBD.OcpInstaller.Update.UnableToObtainOcpConfiguration": "无法获取 OCP 配置信息,请检查连接是否为 OCP 元信息数据库配置", + "OBD.OcpInstaller.Update.IKnow": "我知道了", + "OBD.OcpInstaller.Update.TheCurrentVersionCannotBe": "当前版本不可升级到目标版本", + "OBD.OcpInstaller.Update.TheCurrentVersionOfOcp": "当前 OCP 版本为 V 3.0.0,暂不直接支持升级到 V 4.1.0 您可通过 OCP\n 访问地址", + "OBD.OcpInstaller.Update.ViewVersionDetailsForMore": "查看版本详细信息\n 了解更多 OCP 版本升级路径信息,请查看", + "OBD.OcpInstaller.Update.VersionReleaseRecord": "版本发布记录", + "OBD.OcpInstaller.Update.InThePreCheckProcess": "预检查中,暂不支持进入上一步", + "OBD.OcpInstaller.Update.PreviousStep": "上一步", + "OBD.OcpInstaller.Update.InThePreCheckProcess.1": "预检查中,暂不支持进入下一步", + "OBD.OcpInstaller.Update.PreCheck": "预检查", + "OBD.OcpInstaller.Update.NextStep": "下一步", + "OBD.OcpInstaller.Update.UpgradeAgain": "重新升级", + "OBD.OcpInstaller.Welcome.WelcomeToTheOcpUpgrade": "欢迎您使用 OCP 升级向导", + "OBD.OcpInstaller.Welcome.StartUpgrade": "开始升级", + "OBD.pages.constants.OcpParameterName": "OCP 参数名称", + "OBD.src.utils.SelectTheCorrectOcpNode": "请选择正确的 OCP 节点", + "OBD.src.utils.EnterAPassword": "请输入密码", + "OBD.src.utils.ToCharactersInLength": "长度为 8~32 个字符", + "OBD.src.utils.CanOnlyContainLettersNumbers": "只能包含字母、数字和特殊字符(~!@#%^&*_-+=|(){}[]:;,.?/`$\"<>)", + "OBD.src.utils.AtLeastUppercaseAndLowercase": "大小写字母、数字和特殊字符都至少包含 2 个", + "OBD.src.component.Access.NoOperationPermissionIsAvailable": "暂无操作权限,请联系管理员开通权限", + "OBD.component.AobException.ReturnToHomePage": "返回首页", + "OBD.component.ConnectConfig.MetadbConnectionFailedPleaseCheck": "MetaDB 连接失败,请检查连接配置", + "OBD.component.ConnectConfig.IKnow": "我知道了", + "OBD.component.ConnectConfig.ConnectionInformation": "连接信息", + "OBD.component.ConnectConfig.HostIp": "主机 IP", + "OBD.component.ConnectConfig.EnterTheHostIpAddress": "请输入主机 IP", + "OBD.component.ConnectConfig.TheHostIpAddressFormat": "主机IP格式不正确", + "OBD.component.ConnectConfig.EnterADatabaseAccessIp": "请输入数据库访问 IP 地址", + "OBD.component.ConnectConfig.AccessPort": "访问端口", + "OBD.component.ConnectConfig.EnterAnAccessPort": "请输入访问端口", + "OBD.component.ConnectConfig.EnterTheDatabaseConnectionPort": "请输入数据库连接访问端口", + "OBD.component.ConnectConfig.AccessAccount": "访问账号", + "OBD.component.ConnectConfig.EnterAnAccessAccount": "请输入访问账号", + "OBD.component.ConnectConfig.AccessPassword": "访问密码", + "OBD.component.ConnectConfig.OcpPlatformAdministratorAccountPassword": "OCP 平台管理员账号密码", + "OBD.component.ConnectConfig.EnterAnAccessPassword": "请输入访问密码", + "OBD.component.ConnectConfig.PleaseEnter": "请输入", + "OBD.component.ConnectConfig.PreviousStep": "上一步", + "OBD.component.ConnectConfig.NextStep": "下一步", + "OBD.component.DeployConfig.EnterpriseLevelDataManagementPlatform": "以 OceanBase 为核心的企业级数据管理平台,实现 OceanBase 全生命周期运维管理", + "OBD.component.DeployConfig.FinancialLevelDistributedDatabasesAre": "金融级分布式数据库,具备数据强一致,高扩展、高性价比稳定可靠等特征", + "OBD.component.DeployConfig.OceanbaseADedicatedDatabaseProxy": "OceanBase 数据库专用代理服务器,可将用户的 SQL 请求转发至最佳目标 OBServer", + "OBD.component.DeployConfig.ProductName": "产品名称", + "OBD.component.DeployConfig.Version": "版本", + "OBD.component.DeployConfig.CommunityEdition": "社区版", + "OBD.component.DeployConfig.CommercialEdition": "商业版", + "OBD.component.DeployConfig.Description": "描述", + "OBD.component.DeployConfig.LearnMore": "了解更多", + "OBD.component.DeployConfig.ItStartsWithALetter": "以英文字母开头、英文或数字结尾,可包含英文、数字和下划线,且长度为 2 ~ 32", + "OBD.component.DeployConfig.TheDeploymentNameWithValue": "不存在为 {{value}} 的部署名称", + "OBD.component.DeployConfig.ADeploymentNameWithValue": "已存在为 {{value}} 的部署名称,请指定新名称", + "OBD.component.DeployConfig.BasicConfiguration": "基础配置", + "OBD.component.DeployConfig.DeploymentConfiguration": "部署配置", + "OBD.component.DeployConfig.ClusterName": "集群名称", + "OBD.component.DeployConfig.PleaseEnter": "请输入", + "OBD.component.DeployConfig.EnterAClusterName": "请输入集群名称", + "OBD.component.DeployConfig.VersionSelection": "版本选择", + "OBD.component.DeployConfig.EstimatedInstallationRequirements": "预计安装需要", + "OBD.component.DeployConfig.MbSpace": "MB空间", + "OBD.component.DeployConfig.DeploymentConfigurationPreviousStep": "部署配置-上一步", + "OBD.component.DeployConfig.PreviousStep": "上一步", + "OBD.component.DeployConfig.DeploymentConfigurationNextStep": "部署配置-下一步", + "OBD.component.DeployConfig.NextStep": "下一步", + "OBD.component.EnvPreCheck.CheckFailuredItem.OnlyManualFixes": "只看手动修复项", + "OBD.component.EnvPreCheck.CheckFailuredItem.AutomaticRepair": "自动修复", + "OBD.component.EnvPreCheck.CheckFailuredItem.NoFailedItemsFoundYet": "暂未发现失败项", + "OBD.component.EnvPreCheck.CheckFailuredItem.GreatCheckAllSuccessful": "太棒了!检查全部成功!", + "OBD.component.EnvPreCheck.CheckFailuredItem.Reason": "原因:", + "OBD.component.EnvPreCheck.CheckFailuredItem.Suggestions": "建议:", + "OBD.component.EnvPreCheck.CheckFailuredItem.ManualRepair": "手动修复", + "OBD.component.EnvPreCheck.CheckFailuredItem.LearnMore": "了解更多方案", + "OBD.component.EnvPreCheck.CheckItem.CheckItemPassedcountTotal": "检查项 {{passedCount}}/{{total}}", + "OBD.component.EnvPreCheck.CheckItem.ReCheck": "重新检查", + "OBD.component.EnvPreCheck.CheckCompleted": "检查完成", + "OBD.component.EnvPreCheck.Checking": "检查中", + "OBD.component.EnvPreCheck.VerifyingThatYourEnvironmentMeets": "正在验证您的环境是否满足安装和配置 MetaDB 及 OCP 的所有最低要求。", + "OBD.component.EnvPreCheck.InstallAndDeployOcpEnvironment": "安装部署OCP环境预检查页", + "OBD.component.EnvPreCheck.InstallAndDeployMetadbEnvironment": "安装部署MetaDB环境预检查页", + "OBD.src.component.ErrorBoundary.PageExecutionError": "页面执行出错", + "OBD.src.component.ErrorBoundary.ReturnToHomePage": "返回首页", + "OBD.src.component.ExitBtn.DeploymentConfigurationExit": "部署配置-退出", + "OBD.src.component.ExitBtn.ExitTheOcpUpgradeProgram": "退出 OCP 升级程序", + "OBD.src.component.ExitBtn.ExitTheOcpDeploymentInstaller": "退出 OCP 部署安装程序", + "OBD.src.component.ExitBtn.AfterExitingTheUpgradeWill": "退出后,升级工作将被终止,请谨慎操作", + "OBD.src.component.ExitBtn.AfterExitingTheDeploymentAnd": "退出后,部署安装工作将被终止,请谨慎操作。", + "OBD.src.component.ExitBtn.Exit": "退出", + "OBD.component.InsstallResult.ComponentName": "组件名称", + "OBD.component.InsstallResult.NodeIp": "节点 IP", + "OBD.component.InsstallResult.UpgradeSuccessful": "升级成功", + "OBD.component.InsstallResult.OcpUpgradedSuccessfully": "OCP 升级成功", + "OBD.component.InsstallResult.InstallationAndDeploymentNoMetadb": "安装部署无MetaDB部署成功", + "OBD.component.InsstallResult.OcpDeployedSuccessfully": "OCP 部署成功", + "OBD.component.InsstallResult.MetadbIsDeployedSuccessfully": "安装部署有MetaDB部署成功", + "OBD.component.InsstallResult.InstallationAndDeploymentMetadbDeployment": "安装部署MetaDB部署成功", + "OBD.component.InsstallResult.MetadbDeployedSuccessfully": "MetaDB 部署成功", + "OBD.component.InsstallResult.UpgradeFailed": "升级失败", + "OBD.component.InsstallResult.OcpUpgradeFailed": "OCP 升级失败", + "OBD.component.InsstallResult.InstallationAndDeploymentNoMetadb.1": "安装部署无MetaDB部署失败", + "OBD.component.InsstallResult.OcpDeploymentFailed": "OCP 部署失败", + "OBD.component.InsstallResult.FailedToInstallAndDeploy": "安装部署有MetaDB部署失败", + "OBD.component.InsstallResult.FailedToInstallAndDeploy.1": "安装部署MetaDB部署失败", + "OBD.component.InsstallResult.MetadbDeploymentFailed": "MetaDB 部署失败", + "OBD.component.InsstallResult.PleaseCheckTheLogInformation": "请查看日志信息获取失败原因,联系技术支持同学处理", + "OBD.component.InsstallResult.UpgradeReport": "升级报告", + "OBD.component.InsstallResult.ThereAreHostsThatHave": "·存在未升级 OCP Agent 的主机,建议您在 OCP\n 平台「主机管理」模块安装新版本 OCP Agent。\n 未升级主机:", + "OBD.component.InsstallResult.PreUpgradeVersion": "升级前版本:", + "OBD.component.InsstallResult.UpgradedVersion": "升级后版本:", + "OBD.component.InsstallResult.Click": "点击", + "OBD.component.InsstallResult.OcpReleaseRecords": "OCP 发布记录", + "OBD.component.InsstallResult.LearnMoreAboutTheNew": "了解新版本更多信息", + "OBD.component.InsstallResult.AccessAddressAndAccountSecret": "访问地址及账密信息", + "OBD.component.InsstallResult.PleaseKeepTheFollowingAccess": "请妥善保存以下访问地址及账密信息,及时更新 OCP\n 初始密码,如需了解更多,请访问", + "OBD.component.InsstallResult.OceanbaseDocumentCenter": "OceanBase 文档中心", + "OBD.component.InsstallResult.CopyInformation": "复制信息", + "OBD.component.InsstallResult.AccessAddress": "访问地址", + "OBD.component.InsstallResult.AdministratorAccount": "管理员账号", + "OBD.component.InsstallResult.InitialPassword": "初始密码", + "OBD.component.InstallProcess.Upgraded": "升级中", + "OBD.component.InstallProcess.Deploying": "部署中", + "OBD.component.InstallProcess.Deploying.1": "正在部署", + "OBD.component.InstallProcess.UpgradeLogs": "升级日志", + "OBD.component.InstallProcess.DeploymentLogs": "部署日志", + "OBD.component.InstallProcessNew.Upgrading": "升级中...", + "OBD.component.InstallResult.ComponentName": "组件名称", + "OBD.component.InstallResult.NodeIp": "节点 IP", + "OBD.component.InstallResult.UpgradeSuccessful": "升级成功", + "OBD.component.InstallResult.OcpUpgradedSuccessfully": "OCP 升级成功", + "OBD.component.InstallResult.InstallationAndDeploymentNoMetadb": "安装部署无MetaDB部署成功", + "OBD.component.InstallResult.OcpDeployedSuccessfully": "OCP 部署成功", + "OBD.component.InstallResult.MetadbIsDeployedSuccessfully": "安装部署有MetaDB部署成功", + "OBD.component.InstallResult.UpgradeFailed": "升级失败", + "OBD.component.InstallResult.OcpUpgradeFailed": "OCP 升级失败", + "OBD.component.InstallResult.InstallationAndDeploymentNoMetadb.1": "安装部署无MetaDB部署失败", + "OBD.component.InstallResult.OcpDeploymentFailed": "OCP 部署失败", + "OBD.component.InstallResult.FailedToInstallAndDeploy": "安装部署有MetaDB部署失败", + "OBD.component.InstallResult.PleaseCheckTheLogInformation": "请查看日志信息获取失败原因,联系技术支持同学处理", + "OBD.component.InstallResult.UpgradeReport": "升级报告", + "OBD.component.InstallResult.ThereAreHostsThatHave": "·存在未升级 OCP Agent 的主机,建议您在 OCP\n 平台「主机管理」模块安装新版本 OCP Agent。\n 未升级主机:", + "OBD.component.InstallResult.PreUpgradeVersion": "升级前版本:", + "OBD.component.InstallResult.UpgradedVersion": "升级后版本:", + "OBD.component.InstallResult.Click": "点击", + "OBD.component.InstallResult.OcpReleaseRecords": "OCP 发布记录", + "OBD.component.InstallResult.LearnMoreAboutTheNew": "了解新版本更多信息", + "OBD.component.InstallResult.AccessAddressAndAccountSecret": "访问地址及账密信息", + "OBD.component.InstallResult.PleaseKeepTheFollowingAccess": "请妥善保存以下访问地址及账密信息,及时更新 OCP\n 初始密码,如需了解更多,请访问", + "OBD.component.InstallResult.OceanbaseDocumentCenter": "OceanBase 文档中心", + "OBD.component.InstallResult.CopyInformation": "复制信息", + "OBD.component.InstallResult.AccessAddress": "访问地址", + "OBD.component.InstallResult.AdministratorAccount": "管理员账号", + "OBD.component.InstallResult.InitialPassword": "初始密码", + "OBD.component.InstallResult.UpgradeLogs": "升级日志", + "OBD.component.InstallResult.DeploymentLogs": "部署日志", + "OBD.component.InstallResult.ExitTheInstaller": "退出安装程序", + "OBD.component.InstallResult.DoYouWantToExit": "是否要退出页面?", + "OBD.component.InstallResult.BeforeExitingMakeSureThat": "退出前,请确保已复制访问地址及账密信息", + "OBD.component.InstallResult.Exit": "退出", + "OBD.component.InstallResult.Complete": "完成", + "OBD.component.InstallResult.PreviousStep": "上一步", + "OBD.component.InstallResult.PleaseConfirmWhetherTheInstallation": "请确认是否已定位安装失败原因并修复问题?", + "OBD.component.InstallResult.ReinstallationWillFirstCleanUp": "重新安装将先清理失败的 OCP 安装环境", + "OBD.component.InstallResult.Ok": "确定", + "OBD.component.InstallResult.Cancel": "取消", + "OBD.component.InstallResult.Redeploy": "重新部署", + "OBD.component.MetaDBConfig.ClusterConfig.ThePortNumberCanOnly": "端口号只支持 1024~65535 范围", + "OBD.component.MetaDBConfig.ClusterConfig.ClusterConfiguration": "集群配置", + "OBD.component.MetaDBConfig.ClusterConfig.RootSysPassword": "root@sys 密码", + "OBD.component.MetaDBConfig.ClusterConfig.PleaseEnter": "请输入", + "OBD.component.MetaDBConfig.ClusterConfig.RandomlyGenerated": "随机生成", + "OBD.component.MetaDBConfig.ClusterConfig.SoftwareInstallationPath": "软件安装路径", + "OBD.component.MetaDBConfig.ClusterConfig.DataPath": "数据路径", + "OBD.component.MetaDBConfig.ClusterConfig.LogPath": "日志路径", + "OBD.component.MetaDBConfig.ClusterConfig.SqlPort": "sql 端口", + "OBD.component.MetaDBConfig.ClusterConfig.RpcPort": "rpc 端口", + "OBD.component.MetaDBConfig.ClusterConfig.MoreConfigurations": "更多配置", + "OBD.component.MetaDBConfig.ConfigTable.ClusterParameterName": "集群参数名称", + "OBD.component.MetaDBConfig.ConfigTable.ParameterValue": "参数值", + "OBD.component.MetaDBConfig.ConfigTable.Introduction": "介绍", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.ItStartsWithALetter": "以英文字母开头,英文或数字结尾,可包含英文数字和下划线且长度在 2-32 个字符之间", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.ZoneNameAlreadyOccupied": "Zone 名称已被占用", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.EnterTheCorrectIpAddress": "请输入正确的 IP 地址", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.SelectTheCorrectObproxyNode": "请选择正确的 OBProxy 节点", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.ZoneName": "Zone 名称", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.AZoneThatRepresentsA": "可用区,表示集群内具有相似硬件可用性的一组节点,通常为同一个机架、机房或地域。", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.ThisItemIsRequired": "此项是必填项", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.ObserverNodes": "OBServer 节点", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.TheNodeWhereDatabaseService": "数据库服务(OBServer)所在节点,包含 SQL 引擎、事务引擎和存储引擎,并服务多个数据分区。", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.RootserverNodes": "RootServer 节点", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.TheNodeWhereTheMaster": "总控服务(RootService)所在节点,用于执行集群管理、服务器管理、自动负载均衡等操作。", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.ThisOptionIsRequired": "此项是必选项", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.SelectTheCorrectRootserverNode": "请选择正确的 RootServer 节点", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.PleaseSelect": "请选择", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.DatabaseNodeConfiguration": "数据库节点配置", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.AddZone": "新增 Zone", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.KeepAtLeastOneZone": "至少保留一个 zone", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.AreYouSureYouWant": "确定删除该条 Zone 的相关配置吗?", + "OBD.component.MetaDBConfig.DataBaseNodeConfig.DoNotEnterDuplicateNodes": "禁止输入重复节点", + "OBD.component.MetaDBConfig.NodeConfig.OcpNodeConfiguration": "OCP 节点配置", + "OBD.component.MetaDBConfig.NodeConfig.PleaseEnter": "请输入", + "OBD.component.MetaDBConfig.NodeConfig.SelectHost": "选择主机", + "OBD.component.MetaDBConfig.OBProxyConfig.ThePortNumberCanOnly": "端口号只支持 1024~65535 范围", + "OBD.component.MetaDBConfig.OBProxyConfig.ObproxyConfiguration": "OBProxy 配置", + "OBD.component.MetaDBConfig.OBProxyConfig.PleaseEnter": "请输入", + "OBD.component.MetaDBConfig.OBProxyConfig.ObproxyNodes": "OBProxy 节点", + "OBD.component.MetaDBConfig.OBProxyConfig.SqlPort": "SQL 端口", + "OBD.component.MetaDBConfig.OBProxyConfig.PortExporter": "Exporter 端口", + "OBD.component.MetaDBConfig.OBProxyConfig.SoftwarePath": "软件路径", + "OBD.component.MetaDBConfig.OBProxyConfig.MoreConfigurations": "更多配置", + "OBD.component.MetaDBConfig.UserConfig.DeployUserConfiguration": "部署用户配置", + "OBD.component.MetaDBConfig.UserConfig.Username": "用户名", + "OBD.component.MetaDBConfig.UserConfig.EnterAUsername": "请输入用户名", + "OBD.component.MetaDBConfig.UserConfig.ItStartsWithALetter": "以英文字母开头,可包含英文、数字、下划线和连字符,且不超过32位", + "OBD.component.MetaDBConfig.UserConfig.PleaseProvideTheHostUser": "请提供主机用户名用以自动化配置平台专用操作系统用户", + "OBD.component.MetaDBConfig.UserConfig.ViewHelpDocuments": "查看帮助文档", + "OBD.component.MetaDBConfig.UserConfig.PasswordOptional": "密码(可选)", + "OBD.component.MetaDBConfig.UserConfig.IfYouHaveConfiguredPassword": "如已配置免密登录,则无需再次输入密码", + "OBD.component.MetaDBConfig.UserConfig.SshPort": "SSH端口", + "OBD.component.MetaDBConfig.UserConfig.PleaseEnter": "请输入", + "OBD.component.MetaDBConfig.UserConfig.UseTheRunningUser": "使用运行用户", + "OBD.component.MetaDBConfig.UserConfig.RunningUsername": "运行用户名", + "OBD.component.MetaDBConfig.UserConfig.EnterARunningUsername": "请输入运行用户名", + "OBD.component.MetaDBConfig.MetadbConfigurationPreviousStep": "MetaDB配置-上一步", + "OBD.component.MetaDBConfig.PreviousStep": "上一步", + "OBD.component.MetaDBConfig.MetadbConfigurationNext": "MetaDB配置-下一步", + "OBD.component.MetaDBConfig.NextStep": "下一步", + "OBD.component.ModifyOCPResourcePoolModal.OcpServerMemory": "OCP-Server 内存", + "OBD.component.ModifyOCPResourcePoolModal.OcpTenantMemory": "OCP 租户内存", + "OBD.component.ModifyOCPResourcePoolModal.MetadataTenantMemory": "元信息租户 内存", + "OBD.component.ModifyOCPResourcePoolModal.MonitorDataTenantMemory": "监控数据租户内存", + "OBD.component.ModifyOCPResourcePoolModal.OtherUsedMemory": "其他已使用内存", + "OBD.component.ModifyOCPResourcePoolModal.RemainingMemory": "剩余内存", + "OBD.component.ModifyOCPResourcePoolModal.ResourceAllocation": "资源分配", + "OBD.component.ModifyOCPResourcePoolModal.AccordingToTheResourcesOf": "根据当前主机环境的资源情况,为 OCP 相关服务分配资源如下", + "OBD.component.ModifyOCPResourcePoolModal.MemoryAllocationMapGib": "内存分配图(GiB)", + "OBD.component.ModifyOCPResourcePoolModal.Memory": "内存", + "OBD.component.ModifyOCPResourcePoolModal.OcpTenant": "OCP 租户", + "OBD.component.ModifyOCPResourcePoolModal.MetadataTenant": "元信息租户", + "OBD.component.ModifyOCPResourcePoolModal.MonitorDataTenants": "监控数据租户", + "OBD.component.MyDrawer.Cancel": "取消", + "OBD.component.MyDrawer.Ok": "确定", + "OBD.src.component.MyDropdown.All": "全部", + "OBD.src.component.MyInput.PleaseEnter": "请输入", + "OBD.src.component.MySelect.PleaseSelect": "请选择", + "OBD.component.NoAuth.NoPermissionToView": "暂无权限查看", + "OBD.component.NoAuth.ContactTheAdministratorToActivate": "请联系管理员开通权限", + "OBD.component.OCPConfig.ThePasswordsEnteredTwiceAre": "两次输入的密码不一致,请重新输入", + "OBD.component.OCPConfig.InvalidIpAddress": "IP 地址不合法", + "OBD.component.OCPConfig.SystemConfiguration": "系统配置", + "OBD.component.OCPConfig.SelectHost": "选择主机", + "OBD.component.OCPConfig.EnterAnIpAddress": "请输入 IP 地址", + "OBD.component.OCPConfig.PleaseEnter": "请输入", + "OBD.component.OCPConfig.HostUser": "主机用户", + "OBD.component.OCPConfig.PleaseProvideUsersOnThe": "请提供操作系统上用户以便安装程序进行自动化配置", + "OBD.component.OCPConfig.EnterAnAdministratorAccount": "请输入管理员账号", + "OBD.component.OCPConfig.UserPassword": "用户密码", + "OBD.component.OCPConfig.IfYouHaveSetPassword": "如果您已设置免密,请忽略本选项", + "OBD.component.OCPConfig.OcpServiceConfiguration": "OCP 服务配置", + "OBD.component.OCPConfig.ServiceConfiguration": "服务配置", + "OBD.component.OCPConfig.ClusterName": "集群名称", + "OBD.component.OCPConfig.EnterAClusterName": "请输入集群名称", + "OBD.component.OCPConfig.AdminPassword": "Admin 密码", + "OBD.component.OCPConfig.OcpPlatformAdministratorAccountPassword": "OCP 平台管理员账号密码", + "OBD.component.OCPConfig.EnterAPassword": "请输入密码", + "OBD.component.OCPConfig.SoftwarePath": "软件路径", + "OBD.component.OCPConfig.EnterTheSoftwarePath": "请输入软件路径", + "OBD.component.OCPConfig.ServicePort": "服务端口", + "OBD.component.OCPConfig.EnterAServicePort": "请输入服务端口", + "OBD.component.OCPConfig.PortOcpagent": "ocpagent 端口", + "OBD.component.OCPConfig.EnterPortOcpagent": "请输入 ocpagent 端口", + "OBD.component.OCPConfig.OcpagentMonitoringPort": "ocpagent 监控端口", + "OBD.component.OCPConfig.EnterOcpagentMonitoringPort": "请输入 ocpagent 监控端口", + "OBD.component.OCPConfig.MetadataTenantConfiguration": "元信息租户配置", + "OBD.component.OCPConfig.TenantName": "租户名称", + "OBD.component.OCPConfig.EnterATenantName": "请输入租户名称", + "OBD.component.OCPConfig.Password": "密码", + "OBD.component.OCPConfig.ConfirmPassword": "确认密码", + "OBD.component.OCPConfig.PleaseEnterANewPassword": "请再次输入新密码", + "OBD.component.OCPConfig.MonitorDataTenantConfiguration": "监控数据租户配置", + "OBD.component.OCPConfigNew.ResourcePlan.CopiedSuccessfully": "复制成功", + "OBD.component.OCPConfigNew.ResourcePlan.TheCurrentBrowserDoesNot": "当前浏览器不支持复制文本", + "OBD.component.OCPConfigNew.ResourcePlan.ResourcePlanning": "资源规划", + "OBD.component.OCPConfigNew.ResourcePlan.TheOcpServiceRunsWith": "OCP 服务在运行过程中会有计算和存储资源开销,您需要根据待管理的对象规模进行资源规划,包括 OCP 服务、MetaDB 和 MonitorDB。", + "OBD.component.OCPConfigNew.ResourcePlan.YouAreExpectedToNeed": "您预计需要管理:", + "OBD.component.OCPConfigNew.ResourcePlan.Host": "主机", + "OBD.component.OCPConfigNew.ResourcePlan.PleaseEnter": "请输入", + "OBD.component.OCPConfigNew.ResourcePlan.Less": "小于", + "OBD.component.OCPConfigNew.ResourcePlan.Table": "台", + "OBD.component.OCPConfigNew.ResourcePlan.ResourceConfiguration": "资源配置", + "OBD.component.OCPConfigNew.ResourcePlan.Memory": "内存", + "OBD.component.OCPConfigNew.ResourcePlan.MetadataTenantConfiguration": "元信息租户配置", + "OBD.component.OCPConfigNew.ResourcePlan.TenantName": "租户名称", + "OBD.component.OCPConfigNew.ResourcePlan.EnterATenantName": "请输入租户名称", + "OBD.component.OCPConfigNew.ResourcePlan.Password": "密码", + "OBD.component.OCPConfigNew.ResourcePlan.EnterAPassword": "请输入密码", + "OBD.component.OCPConfigNew.ResourcePlan.RandomlyGenerated": "随机生成", + "OBD.component.OCPConfigNew.ResourcePlan.PleaseRememberThePasswordOr": "请牢记密码,也可", + "OBD.component.OCPConfigNew.ResourcePlan.CopyPassword": "复制密码", + "OBD.component.OCPConfigNew.ResourcePlan.AndKeepItProperly": "并妥善保存", + "OBD.component.OCPConfigNew.ResourcePlan.MonitorDataTenantConfiguration": "监控数据租户配置", + "OBD.component.OCPConfigNew.ServiceConfig.WeRecommendThatYouUse": "建议使用负载均衡的地址作为外部访问 OCP 网站的入口, 实现 OCP 服务高可用。如无,您可选择使用 OCP 的节点 IP+端口进行设置,请后续登录 OCP 后进入系统管理->系统参数变更 ocp.site.url(重启生效)", + "OBD.component.OCPConfigNew.ServiceConfig.CopiedSuccessfully": "复制成功", + "OBD.component.OCPConfigNew.ServiceConfig.TheCurrentBrowserDoesNot": "当前浏览器不支持文本复制", + "OBD.component.OCPConfigNew.ServiceConfig.ThePortNumberCanOnly": "端口号只支持 1024~65535 范围", + "OBD.component.OCPConfigNew.ServiceConfig.ServiceConfiguration": "服务配置", + "OBD.component.OCPConfigNew.ServiceConfig.EnterAPassword": "请输入密码", + "OBD.component.OCPConfigNew.ServiceConfig.AdminPassword": "Admin 密码", + "OBD.component.OCPConfigNew.ServiceConfig.ThePasswordMustBeTo": "密码需满足:长度为 8~32 个字符,支持字母、数字和特殊字符,且至少包含大、小写字母、数字和特殊字符各 2 个,支持的特殊字符为 ~!@#%^&*_\\-+=|(){}[]:;,.?/", + "OBD.component.OCPConfigNew.ServiceConfig.RandomlyGenerated": "随机生成", + "OBD.component.OCPConfigNew.ServiceConfig.CopyPassword": "复制密码", + "OBD.component.OCPConfigNew.ServiceConfig.KeepThePasswordInMind": "请牢记密码,也可复制密码并妥善保存", + "OBD.component.OCPConfigNew.ServiceConfig.SoftwarePath": "软件路径", + "OBD.component.OCPConfigNew.ServiceConfig.EnterTheSoftwarePath": "请输入软件路径", + "OBD.component.OCPConfigNew.ServiceConfig.LogPath": "日志路径", + "OBD.component.OCPConfigNew.ServiceConfig.EnterALogPath": "请输入日志路径", + "OBD.component.OCPConfigNew.ServiceConfig.PackagePath": "软件包路径", + "OBD.component.OCPConfigNew.ServiceConfig.EnterThePackagePath": "请输入软件包路径", + "OBD.component.OCPConfigNew.ServiceConfig.AddressForExternalAccessTo": "外部访问OCP网站的地址:要求以http/https开始,包含VIP地址/域名/端口的网址,且结尾不含斜杠 /", + "OBD.component.OCPConfigNew.ServiceConfig.EnterOcpSiteUrl": "请输入ocp.site.url", + "OBD.component.OCPConfigNew.ServiceConfig.TheCurrentVerificationIsSuccessful": "当前校验成功,请进行下一步", + "OBD.component.OCPConfigNew.ServiceConfig.TheCurrentVerificationFailedPlease": "当前校验失败,请重新输入", + "OBD.component.OCPConfigNew.ServiceConfig.Verification": "校 验", + "OBD.component.OCPConfigNew.ServiceConfig.ServicePort": "服务端口", + "OBD.component.OCPConfigNew.ServiceConfig.PleaseEnter": "请输入", + "OBD.component.OCPConfigNew.OcpConfigurationPreviousStep": "ocp配置-上一步", + "OBD.component.OCPConfigNew.PreviousStep": "上一步", + "OBD.component.OCPConfigNew.OcpConfigurationNextStep": "ocp配置-下一步", + "OBD.component.OCPConfigNew.NextStep": "下一步", + "OBD.OCPPreCheck.CheckInfo.BasicInfo.InstallationConfiguration": "安装配置", + "OBD.OCPPreCheck.CheckInfo.BasicInfo.ClusterName": "集群名称", + "OBD.OCPPreCheck.CheckInfo.BasicInfo.InstallationType": "安装类型", + "OBD.OCPPreCheck.CheckInfo.BasicInfo.ProductVersion": "产品版本", + "OBD.OCPPreCheck.CheckInfo.BasicInfo.Product": "产品", + "OBD.OCPPreCheck.CheckInfo.BasicInfo.CommunityEdition": "社区版", + "OBD.OCPPreCheck.CheckInfo.BasicInfo.CommercialEdition": "商业版", + "OBD.OCPPreCheck.CheckInfo.BasicInfo.Version": "版本", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.ClusterConfiguration": "集群配置", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.RootSysPassword": "root@sys 密码", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.SoftwarePath": "软件路径", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.DataPath": "数据路径", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.LogPath": "日志路径", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.MysqlPort": "mysql 端口", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.RpcPort": "rpc 端口", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.ObproxyConfiguration": "OBProxy 配置", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.ObproxyNodes": "OBProxy 节点", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.SqlPort": "SQL 端口", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.PortExporter": "Exporter 端口", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.ParameterValue": "参数值", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.AutomaticAllocation": "自动分配", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.Introduction": "介绍", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.ZoneName": "Zone 名称", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.ObServerNodes": "OB Server 节点", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.RootServerNodes": "Root Server 节点", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.DeployUserConfiguration": "部署用户配置", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.Username": "用户名", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.Password": "密码", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.SshPort": "SSH端口", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.OcpNodeConfiguration": "OCP 节点配置", + "OBD.OCPPreCheck.CheckInfo.ConfigInfo.DatabaseNodeConfiguration": "数据库节点配置", + "OBD.OCPPreCheck.CheckInfo.ConnectInfo.ConnectionInformation": "连接信息", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.AdminPassword": "Admin密码", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.SoftwarePath": "软件路径", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.LogPath": "日志路径", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.PackagePath": "软件包路径", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.DeployUserConfiguration": "部署用户配置", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.Username": "用户名", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.Password": "密码", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.SshPort": "SSH端口", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.OcpDeploymentSelection": "OCP 部署选择", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.ServiceConfiguration": "服务配置", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.ResourcePlanning": "资源规划", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.ManageTheNumberOfHosts": "管理主机数量", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.ResourceConfiguration": "资源配置", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.Memory": "内存", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.MetadataTenantConfiguration": "元信息租户配置", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.TenantName": "租户名称", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.MonitorDataTenantConfiguration": "监控数据租户配置", + "OBD.OCPPreCheck.CheckInfo.InstallAll": "全部安装", + "OBD.OCPPreCheck.CheckInfo.HostIp": "主机IP", + "OBD.OCPPreCheck.CheckInfo.AccessPort": "访问端口", + "OBD.OCPPreCheck.CheckInfo.AccessAccount": "访问账号", + "OBD.OCPPreCheck.CheckInfo.Password": "密码", + "OBD.OCPPreCheck.CheckInfo.TheOcpInstallationInformationConfiguration": "OCP 安装信息配置已完成,请检查并确认以下配置信息,确定后开始预检查。", + "OBD.OCPPreCheck.CheckInfo.PreCheckPreviousStep": "预检查-上一步", + "OBD.OCPPreCheck.CheckInfo.PreviousStep": "上一步", + "OBD.OCPPreCheck.CheckInfo.PreCheck": "预检查-预检查", + "OBD.OCPPreCheck.CheckInfo.PreCheck.1": "预检查", + "OBD.OCPPreCheck.PreCheck.AutomaticRepairSucceeded": "自动修复成功", + "OBD.OCPPreCheck.PreCheck.PreCheckResultReCheck": "预检查结果-重新检查", + "OBD.OCPPreCheck.PreCheck.ReCheck": "重新检查", + "OBD.OCPPreCheck.PreCheck.PreCheckResultAutomaticRepair": "预检查结果-自动修复", + "OBD.OCPPreCheck.PreCheck.AutomaticRepair": "自动修复", + "OBD.OCPPreCheck.PreCheck.PreCheckResultsPreviousStep": "预检查结果-上一步", + "OBD.OCPPreCheck.PreCheck.PreviousStep": "上一步", + "OBD.OCPPreCheck.PreCheck.PreCheckFailedDeploymentGreyed": "预检查失败-部署置灰", + "OBD.OCPPreCheck.PreCheck.NextStep": "下一步", + "OBD.OCPPreCheck.PreCheck.PreCheckSuccessfulDeployment": "预检查成功-部署", + "OBD.src.component.Password.ToCharactersInLength": "长度为 8~32 个字符", + "OBD.src.component.Password.CanOnlyContainLettersNumbers": "只能包含字母、数字和特殊字符._+@#$%", + "OBD.src.component.Password.AtLeastUppercaseAndLowercase": "大小写字母、数字和特殊字符都至少包含 2 个", + "OBD.component.Result.Return": "返回", + "OBD.component.Result.ViewTaskDetails": "查看任务详情", + "OBD.src.constant.configuration.DeploymentConfiguration": "部署配置", + "OBD.src.constant.configuration.MetadbConfiguration": "MetaDB 配置", + "OBD.src.constant.configuration.OcpConfiguration": "OCP 配置", + "OBD.src.constant.configuration.PreCheck": "预检查", + "OBD.src.constant.configuration.Deployment": "部署", + "OBD.src.constant.configuration.ObClusterConnectionConfiguration": "OB集群 连接配置", + "OBD.src.constant.configuration.ConnectivityTest": "联通性测试", + "OBD.src.constant.configuration.EnvironmentPreCheck": "环境预检查", + "OBD.src.constant.configuration.OcpUpgrade": "OCP升级", + "OBD.src.constant.Checking": "检查中", + "OBD.src.constant.Pass": "通过", + "OBD.src.constant.Failed": "未通过", + "OBD.src.constant.Ignored": "已忽略", + "OBD.src.constant.must-ignore.SimplifiedChinese": "简体中文", + "OBD.Component.ConnectionInfo.EnterAnAccount": "请输入账号", + "OBD.component.CustomPasswordInput.PasswordSettingsDoNotMeet": "密码设置不符合要求", + "OBD.component.CustomPasswordInput.CopiedSuccessfully": "复制成功", + "OBD.component.CustomPasswordInput.TheCurrentBrowserDoesNot": "当前浏览器不支持文本复制", + "OBD.component.CustomPasswordInput.KeepThePasswordInMind": "请牢记密码,也可复制密码并妥善保存", + "OBD.component.CustomPasswordInput.PleaseRememberThePasswordOr": "请牢记密码,也可", + "OBD.component.CustomPasswordInput.CopyPassword": "复制密码", + "OBD.component.CustomPasswordInput.AndKeepItProperly": "并妥善保存", + "OBD.component.CustomPasswordInput.EnterAPassword": "请输入密码", + "OBD.component.CustomPasswordInput.RandomlyGenerated": "随机生成", + "OBD.component.DeployConfig.ItStartsWithALetter.1": "以英文字母开头、英文或数字结尾,可包含英文、数字、连字符和下划线,且长度为 2 ~ 32", + "OBD.src.component.ExitBtn.ExitTheOceanbaseDeploymentWizard": "退出 OceanBase 部署向导", + "OBD.component.MetaDBConfig.UserConfig.TheUserWhoRunsThe": "运行服务的用户", + "OBD.src.utils.CanOnlyContainLettersNumbers.1": "只能包含字母、数字和特殊字符._+@#$%", + "OBD.component.OCPConfigNew.ServiceConfig.ThePasswordMustBeTo.1": "密码需满足:长度为 8~32 个字符,支持字母、数字和特殊字符,且至少包含大、小写字母、数字和特殊字符各 2 个,支持的特殊字符为._+@#$%", + "OBD.component.DeployConfig.UnableToObtainTheInstallation": "无法获取安装包,请检查安装程序配置。", + "OBD.component.InstallResult.WeRecommendThatYouInstall": "存在未升级 OCP Agent 的主机,建议您在 OCP 平台「主机管理」模块安装新版本 OCP Agent。", + "OBD.component.OCPConfigNew.ServiceConfig.ThePasswordMustBeTo.2": "密码需满足:长度为 8~32 个字符,支持字母、数字和特殊字符,且至少包含大、小写字母、数字和特殊字符各 2 个,支持的特殊字符为~!@#%^&*_-+=`|(){}[]:;',.?/", + "OBD.src.utils.CanOnlyContainLettersNumbers.2": "只能包含字母、数字和特殊字符~!@#%^&*_-+=`|(){}[]:;',.?/", + "OBD.component.MetaDBConfig.UserConfig.OperatingSystemUsersRunningOcp": "运行 OCP 服务的操作系统用户", + "OBD.pages.Obdeploy.InstallConfig.OcpExpressOnlySupportsAnd": "OCP Express 仅支持 4.0 及以上版本 OceanBase Database。", + "OBD.pages.Obdeploy.InstallConfig.UnableToObtainTheInstallation": "无法获取安装包,请检查安装程序配置。", + "OBD.component.MetaDBConfig.ClusterConfig.SqlPort.1": "SQL 端口", + "OBD.component.MetaDBConfig.ClusterConfig.RpcPort.1": "RPC 端口", + "OBD.component.PasswordCard.Password": "密码", + "OBD.component.InputPort.PleaseEnter": "请输入", + "OBD.component.InputPort.ThePortNumberCanOnly": "端口号只支持 1024~65535 范围", + "OBD.Component.ConnectionInfo.PasswordOptional": "密码(可选)", + "OBD.Component.ConnectionInfo.IfYouHaveConfiguredPassword": "如已配置免密登录,则无需再次输入密码", + "OBD.component.CustomPasswordInput.TheLengthShouldBeTo": "长度应为 8~32 个字符", + "OBD.component.CustomPasswordInput.CanOnlyContainLettersNumbers": "只能包含字母、数字和特殊字符~!@#%^&*_-+=`|(){}[]:;',.?/", + "OBD.component.CustomPasswordInput.AtLeastUppercaseAndLowercase": "大小写字母、数字和特殊字符都至少包含 2 个", + "OBD.src.utils.TheLengthShouldBeTo": "长度应为 8~32 个字符", + "OBD.component.InsstallResult.ThereAreHostsThatHave.1": "·存在未升级 OCP Agent 的主机,建议您在 OCP\n 平台「主机管理」模块安装新版本 OCP Agent。", + "OBD.component.InsstallResult.HostNotUpgraded": "未升级主机:", + "OBD.Component.ConnectionInfo.SshPort": "SSH端口", + "OBD.Component.UpdatePreCheck.MetadbSharesMetaTenantResources": "MetaDB与MonitorDB共享Meta租户资源,容易造成OCP运行异常,强烈建议您新建Monitor租户,并进行MetaDB数据清理和MonitorDB数据迁移,详情请参考《", + "OBD.component.DeployConfig.IfTheCurrentEnvironmentCannot": "如当前环境无法正常访问外网,建议使用 OceanBase\n 离线安装包进行安装部署。", + "OBD.component.DeployConfig.GoToDownloadOfflineInstallation": "前往下载离线安装", + "OBD.component.DeployConfig.HowToEnableOnlineImage": "如何启用在线镜像仓库", + "OBD.component.OCPConfigNew.ResourcePlan.OcpApplicationMemory": "OCP 应用内存", + "OBD.OCPPreCheck.CheckInfo.ResourceInfo.OcpApplicationMemory": "OCP 应用内存" } diff --git a/web/src/models/global.ts b/web/src/models/global.ts index 652b4cb..65f5722 100755 --- a/web/src/models/global.ts +++ b/web/src/models/global.ts @@ -1,32 +1,176 @@ -import { useState } from 'react'; +import { useRef, useState } from 'react'; import useRequest from '@/utils/useRequest'; import { exitProcess } from '@/services/ob-deploy-web/Common'; import { queryDeploymentConfig } from '@/services/ob-deploy-web/Deployments'; import { getErrorInfo } from '@/utils'; +//ocp reqestBody +// { +// "auth": { +// "user": "", +// "password": "string", +// "port": 22 +// }, +// "components": { +// "oceanbase": { +// "component": "string", +// "appname": "string", +// "version": "string", +// "release": "string", +// "package_hash": "", +// "mode": "DEMO", +// "root_password": "string", +// "mysql_port": 0, +// "rpc_port": 0, +// "home_path": "", +// "data_dir": "", +// "redo_dir": "", +// "parameters": [ +// { +// "key": "string", +// "value": "string", +// "adaptive": true +// } +// ], +// "topology": [ +// { +// "name": "string", +// "rootservice": "string", +// "servers": [ +// { +// "ip": "string", +// "parameters": {} +// } +// ] +// } +// ] +// }, +// "obproxy": { +// "component": "string", +// "version": "string", +// "package_hash": "", +// "release": "string", +// "cluster_name": "string", +// "home_path": "", +// "prometheus_listen_port": 0, +// "listen_port": 0, +// "parameters": [ +// { +// "key": "string", +// "value": "string", +// "adaptive": true +// } +// ], +// "servers": [ +// "string" +// ] +// }, +// "ocpserver": { +// "component": "ocp-server", +// "version": "string", +// "package_hash": "", +// "release": "string", +// "home_path": "", +// "port": 0, +// "admin_password": "string", +// "parameters": [ +// { +// "key": "string", +// "value": "string", +// "adaptive": true +// } +// ], +// "memory_size": "2G", +// "ocp_cpu": 0, +// "meta_tenant": { +// "name": { +// "tenant_name": "string", +// "user_name": "meta_user", +// "user_database": "meta_database" +// }, +// "password": "", +// "resource": { +// "cpu": 2, +// "memory": 4 +// } +// }, +// "monitor_tenant": { +// "name": { +// "tenant_name": "string", +// "user_name": "meta_user", +// "user_database": "meta_database" +// }, +// "password": "", +// "resource": { +// "cpu": 2, +// "memory": 4 +// } +// }, +// "manage_info": { +// "cluster": 0, +// "tenant": 0, +// "machine": 0 +// }, +// "servers": [ +// "string" +// ], +// "metadb": { +// "id": 1, +// "host": "string", +// "port": 0, +// "user": "string", +// "password": "string", +// "database": "oceanbase" +// } +// } +// }, +// "home_path": "", +// "launch_user": "string" +// } + export default () => { const initAppName = 'myoceanbase'; - const [selectedConfig,setSelectedConfig] = useState(['obproxy','ocp-express','obagent']); // 有ocpexpress必定有obagent - const [currentStep, setCurrentStep] = useState(0); + const [selectedConfig, setSelectedConfig] = useState([ + 'obproxy', + 'ocp-express', + 'obagent', + ]); // 有ocpexpress必定有obagent + const [currentStep, setCurrentStep] = useState(1); const [configData, setConfigData] = useState({}); + const [ocpConfigData, setOcpConfigData] = useState({}); const [currentType, setCurrentType] = useState('all'); const [checkOK, setCheckOK] = useState(false); const [installStatus, setInstallStatus] = useState('RUNNING'); const [lowVersion, setLowVersion] = useState(false); const [isFirstTime, setIsFirstTime] = useState(true); + const [ocpNewFirstTime, setOcpNewFirstTime] = useState(true); const [isDraft, setIsDraft] = useState(false); const [clusterMore, setClusterMore] = useState(false); + const [ocpClusterMore, setOcpClusterMore] = useState(false); const [nameIndex, setNameIndex] = useState(4); + const [ocpNameIndex, setOcpNameIndex] = useState(4); const [errorVisible, setErrorVisible] = useState(false); const [errorsList, setErrorsList] = useState([]); - + const [first, setFirst] = useState(true); + const [token, setToken] = useState(''); + const [selectCluster, setSelectCluster] = useState(); const [clusterMoreConfig, setClusterMoreConfig] = useState< API.NewParameterMeta[] >([]); + const [ocpClusterMoreConfig, setOcpClusterMoreConfig] = useState< + API.NewParameterMeta[] + >([]); + const [proxyMoreConfig, setProxyMoreConfig] = useState< + API.NewParameterMeta[] + >([]); const [componentsMore, setComponentsMore] = useState(false); const [componentsMoreConfig, setComponentsMoreConfig] = useState< API.NewParameterMeta[] >([]); + const [ocpCompMoreConfig, setOcpCompMoreConfig] = useState< + + API.NewParameterMeta[] + >([]); const [componentsVersionInfo, setComponentsVersionInfo] = useState({}); @@ -40,6 +184,7 @@ export default () => { const { run: getInfoByName } = useRequest(queryDeploymentConfig, { throwOnError: true, }); + const aliveTokenTimer = useRef(null) return { selectedConfig, @@ -49,6 +194,8 @@ export default () => { setCurrentStep, configData, setConfigData, + ocpConfigData, + setOcpConfigData, checkOK, setCheckOK, installStatus, @@ -57,25 +204,44 @@ export default () => { setLowVersion, isFirstTime, setIsFirstTime, + ocpNewFirstTime, + setOcpNewFirstTime, isDraft, setIsDraft, clusterMore, setClusterMore, + ocpClusterMore, + setOcpClusterMore, componentsMore, setComponentsMore, clusterMoreConfig, setClusterMoreConfig, + ocpClusterMoreConfig, + setOcpClusterMoreConfig, + proxyMoreConfig, + setProxyMoreConfig, componentsMoreConfig, setComponentsMoreConfig, + ocpCompMoreConfig, + setOcpCompMoreConfig, componentsVersionInfo, setComponentsVersionInfo, handleQuitProgress, getInfoByName, nameIndex, setNameIndex, + ocpNameIndex, + setOcpNameIndex, errorVisible, setErrorVisible, errorsList, setErrorsList, + first, + setFirst, + token, + setToken, + aliveTokenTimer, + selectCluster, + setSelectCluster }; }; diff --git a/web/src/models/ocpInstallData.ts b/web/src/models/ocpInstallData.ts new file mode 100644 index 0000000..8eb08c8 --- /dev/null +++ b/web/src/models/ocpInstallData.ts @@ -0,0 +1,91 @@ +import { useState } from 'react'; +import type { TableDataType } from '@/component/DeployConfig/constants'; +import { + OCPComponent, + OBComponent, + OBProxyComponent, +} from '@/component/DeployConfig/constants'; +import { getTailPath } from '@/utils/helper'; + +type VersionInfoType = { + version: string; + md5: string; + release: string; + versionType: 'ce' | 'business'; // Community Edition | Business version + value?: string; +}; + +export type ConnectInfoType = { + host?: string; + port?: number; + database?: string; + accessUser?: string; + accessCode?: string; + user?: string; + password?: string; +}; +export default () => { + const taiPath = getTailPath(); + const isNewDB = taiPath === 'install'; + const defaultTableData = isNewDB + ? [OCPComponent, OBComponent, OBProxyComponent] + : [OCPComponent]; + const [obVersionInfo, setObVersionInfo] = useState(); + const [ocpVersionInfo, setOcpVersionInfo] = useState(); + const [obproxyVersionInfo, setObproxyVersionInfo] = + useState(); + const [deployMemory, setDeployMemory] = useState(0); + const [useRunningUser, setUseRunningUser] = useState(false); + const [checkConnectInfo, setCheckConnectInfo] = useState< + 'unchecked' | 'fail' | 'success' + >('unchecked'); + const [installTaskId, setInstallTaskId] = useState(); + const [installStatus, setInstallStatus] = useState('RUNNING'); + const [installResult, setInstallResult] = useState< + 'SUCCESSFUL' | 'FAILED' | 'RUNNING' + >(); + const [connectId, setConnectId] = useState(); + const [isReinstall, setIsReinstall] = useState(false); + const [isSingleOcpNode, setIsSingleOcpNode] = useState(); //undefined表示没有输入 + const [username, setUsername] = useState(''); + const [logData, setLogData] = useState({}); + const [isShowMoreConfig, setIsShowMoreConfig] = useState(false); + const [connectInfo, setConnectInfo] = useState(); + const [tableData, setTableData] = useState(defaultTableData); + return { + obVersionInfo, + setObVersionInfo, + ocpVersionInfo, + setOcpVersionInfo, + obproxyVersionInfo, + setObproxyVersionInfo, + deployMemory, + setDeployMemory, + useRunningUser, + setUseRunningUser, + checkConnectInfo, + setCheckConnectInfo, + connectId, + setConnectId, + installTaskId, + setInstallTaskId, + installStatus, + setInstallStatus, + installResult, + setInstallResult, + isReinstall, + setIsReinstall, + isSingleOcpNode, + setIsSingleOcpNode, + username, + setUsername, + logData, + setLogData, + isShowMoreConfig, + setIsShowMoreConfig, + connectInfo, + setConnectInfo, + tableData, + setTableData, + }; +}; diff --git a/web/src/pages/Guide/index.less b/web/src/pages/Guide/index.less new file mode 100644 index 0000000..b955e31 --- /dev/null +++ b/web/src/pages/Guide/index.less @@ -0,0 +1,89 @@ +.content { + position: relative; + z-index: 10; + width: 100vw; + height: 79vh; + min-height: 628px; + padding: 24px calc(120 / 1280 * 100%); + padding-bottom: 92px; + background-color: rgba(245, 248, 254, 1); + box-sizing: border-box; +} +.disableCustomCardContainer { + background-color: #f5f8fe; + // pointer-events: none; +} +.disableCustomCardContainer, +.customCardContainer { + box-sizing: border-box; + min-width: 484px; + height: 100%; + min-height: 200px; + display: flex; + align-items: center; + // width: 40%; + // height: 40%; + padding: 35px 18px; + .cardHeader { + display: flex; + justify-content: center; + height: 60px; + margin-bottom: 16px; + .cardImg { + margin-right: 8px; + } + .cardTitle, + .disableCardTitle { + margin-left: 8px; + font-weight: 500; + font-size: 18px; + line-height: 60px; + } + .disableCardTitle { + color: #cdd5e4; + } + } + .cardDetail, + .disableCardDetail { + font-weight: 400; + font-size: 16px; + line-height: 22px; + text-align: center; + } + .disableCardDetail { + color: #cdd5e4; + } + + &.customCardSelect { + color: #006aff !important; + border: 2px solid #006aff; + :global { + .ant-result-title, + .ant-result-subtitle { + color: #006aff !important; + } + } + } + + &.customCardContainer:hover { + cursor: pointer; + } +} +.pageFooterContainer { + position: fixed; + right: 0; + bottom: 0; + left: 0; + z-index: 99; + padding: 16px; + background-color: #f5f8ff; + border-top: 1px solid #dde4ed; + .pageFooter { + width: 1040px; + margin: 0 auto; + overflow: hidden; + .foolterAction { + float: right; + } + } +} diff --git a/web/src/pages/Guide/index.tsx b/web/src/pages/Guide/index.tsx new file mode 100644 index 0000000..745082a --- /dev/null +++ b/web/src/pages/Guide/index.tsx @@ -0,0 +1,270 @@ +import { intl } from '@/utils/intl'; +import { history } from 'umi'; +import { useRef, useState } from 'react'; +import { Tooltip, Space, Row, Col, Card, Button, Modal } from 'antd'; +import { ExclamationCircleOutlined } from '@ant-design/icons'; +import { ProCard } from '@ant-design/pro-components'; +import { useModel } from 'umi'; + +import obSelectIcon from '../../../public/assets/welcome/ob-selected.png'; +import obUnselectIcon from '../../../public/assets/welcome/ob-unselected.png'; +import ocpSelectIcon from '../../../public/assets/welcome/ocp-selected.png'; +import ocpUnselectIcon from '../../../public/assets/welcome/ocp-unselected.png'; +import odcSelectIcon from '../../../public/assets/welcome/odc-selected.png'; +import odcUnselectIcon from '../../../public/assets/welcome/odc-unselected.png'; +import omsSelectIcon from '../../../public/assets/welcome/oms-selected.png'; +import omsUnselectIcon from '../../../public/assets/welcome/oms-unselected.png'; +import Banner from '@/component/Banner'; +import ExitBtn from '@/component/ExitBtn'; +import CustomFooter from '@/component/CustomFooter'; +import { DOCS_PRODUCTION } from '@/constant/docs'; + +import styles from './index.less'; + +type ChooseResultType = 'obdeploy' | 'ocpInstaller'; +interface CustomCardProps { + disable: boolean; + unselectIconPath: string; + selectIconPath: string; + title: string; + detail: string; + onClick?: (prop: string) => void; + type?: string; + tooltipText?: string; + select?: boolean; +} + +const getGuideConfigList = (onClick: any) => { + const guideConfigList: CustomCardProps[] = [ + { + disable: false, + unselectIconPath: obUnselectIcon, + selectIconPath: obSelectIcon, + title: intl.formatMessage({ + id: 'OBD.pages.Guide.OceanbaseAndSupportingTools', + defaultMessage: 'OceanBase 及配套工具', + }), + detail: intl.formatMessage({ + id: 'OBD.pages.Guide.DistributedDatabasesAndVariousTools', + defaultMessage: '分布式数据库以及各类工具,方便客户管理、运维和使用', + }), + onClick: () => onClick('obdeploy'), + type: 'obdeploy', + }, + { + disable: false, + unselectIconPath: ocpUnselectIcon, + selectIconPath: ocpSelectIcon, + title: 'OCP', + detail: intl.formatMessage({ + id: 'OBD.pages.Guide.OceanbaseCloudPlatformFullLifecycle', + defaultMessage: 'OceanBase 云平台:对 OB 集群进行全生命周期管理', + }), + onClick: () => onClick('ocpInstaller'), + type: 'ocpInstaller', + }, + { + disable: true, + unselectIconPath: odcUnselectIcon, + selectIconPath: odcSelectIcon, + title: 'ODC', + detail: intl.formatMessage({ + id: 'OBD.pages.Guide.OceanbaseDeveloperCenterManageDatabases', + defaultMessage: 'OceanBase 开发者中心:对数据库&表进行管理', + }), + }, + { + disable: true, + unselectIconPath: omsUnselectIcon, + selectIconPath: omsSelectIcon, + title: 'OMS', + detail: intl.formatMessage({ + id: 'OBD.pages.Guide.OceanbaseDataMigrationFastData', + defaultMessage: 'OceanBase 数据迁移:对数据进行快速迁移', + }), + }, + ]; + + return guideConfigList; +}; + +export default function Guide() { + const [chooseResult, setChooseResult] = + useState('obdeploy'); + const guideConfigListRef = useRef( + getGuideConfigList(setChooseResult), + ); + const { setCurrentStep: setOBCurrentStep } = useModel('global'); + const CustomCard = ({ + disable = false, + unselectIconPath, + selectIconPath, + title, + detail, + onClick, + type, + tooltipText, + select, + }: CustomCardProps) => { + const CardWrap = (prop: React.PropsWithChildren) => { + if (disable) { + return ( + + {prop.children} + + ); + } else { + return prop.children; + } + }; + + return ( + + onClick(type) : () => {}} + > +
    + + + + {title} + +
    +

    + {detail} +

    +
    +
    + ); + }; + + const Title = () => { + const textStyle = { + fontWeight: '400', + fontSize: '14px', + lineHeight: '22px', + }; + return ( +
    + + {intl.formatMessage({ + id: 'OBD.pages.Guide.SelectAnInstallationProduct', + defaultMessage: '请选择安装产品', + })} + {' '} + |{' '} + + {intl.formatMessage({ + id: 'OBD.pages.Guide.HelpDocument', + defaultMessage: '帮助文档', + })} + +
    + ); + }; + + const nextStep = (path: ChooseResultType) => { + if (path === 'obdeploy') { + setOBCurrentStep(1); + } + history.push(path); + }; + + return ( +
    + +
    + } + style={{ + minWidth: '1040px', + height: '100%', + boxShadow: + '0 2px 4px 0 rgba(19,32,57,0.02), 0 1px 6px -1px rgba(19,32,57,0.02), 0 1px 2px 0 rgba(19,32,57,0.03)', + }} + bodyStyle={{ height: 'calc(100% - 64px)' }} + // divided={false} + > + + {guideConfigListRef.current.map((guideConfig, idx) => { + let select = Boolean( + guideConfig.type && chooseResult === guideConfig.type, + ); + return ( +
    + + + ); + })} + + + + + + + + + ); +} diff --git a/web/src/pages/Layout/index.tsx b/web/src/pages/Layout/index.tsx new file mode 100644 index 0000000..e0a7d2e --- /dev/null +++ b/web/src/pages/Layout/index.tsx @@ -0,0 +1,132 @@ +import { ConfigProvider, Space, Dropdown } from 'antd'; +import { ReactElement, useState } from 'react'; +import type { Locale } from 'antd/es/locale-provider'; +import enUS from 'antd/es/locale/en_US'; +import zhCN from 'antd/es/locale/zh_CN'; +import { getLocale, setLocale } from 'umi'; +import { + HomeOutlined, + ReadOutlined, + ProfileOutlined, + GlobalOutlined, +} from '@ant-design/icons'; + +import { intl } from '@/utils/intl'; +import { localeList, localeText } from '@/constants'; +import theme from '../theme'; +import styles from '../Obdeploy/index.less'; + +export default function Layout(props: React.PropsWithChildren) { + const locale = getLocale(); + const [token, setToken] = useState(''); + const [localeConfig, setLocalConfig] = useState( + locale === 'zh-CN' ? zhCN : enUS, + ); + + const setCurrentLocale = (key: string) => { + if (key !== locale) { + setLocale(key); + window.localStorage.setItem('uuid', token); + } + setLocalConfig(key === 'zh-CN' ? zhCN : enUS); + }; + + const getLocaleItems = () => { + return localeList.map((item) => ({ + ...item, + label: setCurrentLocale(item.key)}>{item.label}, + })); + }; + return ( + + + + ); +} diff --git a/web/src/pages/Obdeploy/CheckInfo.tsx b/web/src/pages/Obdeploy/CheckInfo.tsx new file mode 100644 index 0000000..c558eb2 --- /dev/null +++ b/web/src/pages/Obdeploy/CheckInfo.tsx @@ -0,0 +1,658 @@ +import { intl } from '@/utils/intl'; +import { useState } from 'react'; +import { useModel } from 'umi'; +import { Space, Button, Table, Row, Col, Alert, Tooltip } from 'antd'; +import { ProCard } from '@ant-design/pro-components'; +import type { ColumnsType } from 'antd/es/table'; +import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'; +import useRequest from '@/utils/useRequest'; +import { createDeploymentConfig } from '@/services/ob-deploy-web/Deployments'; +import { handleQuit, getErrorInfo } from '@/utils'; +import PasswordCard from '@/component/PasswordCard'; +import { + componentsConfig, + allComponentsKeys, + onlyComponentsKeys, + modeConfig, + obproxyComponent, +} from '../constants'; +import { getLocale } from 'umi'; +import EnStyles from './indexEn.less'; +import ZhStyles from './indexZh.less'; + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; +interface ComponentsNodeConfig { + name: string; + servers: string[]; + key: string; + isTooltip: boolean; +} + +export default function CheckInfo() { + const { + configData, + setCheckOK, + lowVersion, + setCurrentStep, + handleQuitProgress, + setErrorVisible, + setErrorsList, + selectedConfig, + errorsList, + } = useModel('global'); + const { components = {}, auth, home_path } = configData || {}; + const { + oceanbase = {}, + obproxy = {}, + ocpexpress = {}, + obagent = {}, + } = components; + const [showPwd, setShowPwd] = useState(false); + + const { run: handleCreateConfig, loading } = useRequest( + createDeploymentConfig, + { + onSuccess: ({ success }: API.OBResponse) => { + if (success) { + setCheckOK(true); + } + }, + onError: (e: any) => { + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }, + ); + + const prevStep = () => { + setCurrentStep(3); + window.scrollTo(0, 0); + }; + + const handlePreCheck = () => { + handleCreateConfig({ name: oceanbase?.appname }, { ...configData }); + }; + + const getComponentsList = () => { + const componentsList: API.TableComponentInfo[] = []; + allComponentsKeys.forEach((key) => { + if (components?.[key]) { + const componentConfig = componentsConfig?.[key] || {}; + componentsList.push({ + ...componentConfig, + version: components?.[key].version, + key, + }); + } + }); + return componentsList; + }; + + const getComponentsNodeConfigList = () => { + const componentsNodeConfigList: ComponentsNodeConfig[] = []; + //todo:待优化 + let _selectedConfig = [...selectedConfig]; + _selectedConfig.forEach((item, idx) => { + if (item === 'ocp-express') { + _selectedConfig[idx] = 'ocpexpress'; + } + }); + let currentOnlyComponentsKeys = onlyComponentsKeys.filter( + (key) => key !== 'obagent' && _selectedConfig.includes(key), + ); + + if (lowVersion) { + currentOnlyComponentsKeys = currentOnlyComponentsKeys.filter( + (key) => key !== 'ocpexpress', + ); + } + + currentOnlyComponentsKeys.forEach((key) => { + if (componentsConfig?.[key]) { + componentsNodeConfigList.push({ + key, + name: componentsConfig?.[key]?.name, + servers: components?.[key]?.servers?.join(','), + isTooltip: key === obproxyComponent, + }); + } + }); + return componentsNodeConfigList; + }; + + const dbConfigColumns: ColumnsType = [ + { + title: intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.ZoneName', + defaultMessage: 'Zone 名称', + }), + dataIndex: 'name', + width: 200, + render: (text) => text || '-', + }, + { + title: intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.ObServerNodes', + defaultMessage: 'OB Server 节点', + }), + dataIndex: 'servers', + render: (text) => { + const serversIps = text.map((item: API.OceanbaseServers) => item.ip); + const str = serversIps.join(','); + return ( + +
    {str}
    +
    + ); + }, + }, + { + title: intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.RootServerNodes', + defaultMessage: 'Root Server 节点', + }), + dataIndex: 'rootservice', + width: 200, + render: (text) => text || '-', + }, + ]; + + const getMoreColumns = (label: string) => { + const columns: ColumnsType = [ + { + title: label, + dataIndex: 'key', + render: (text) => text, + }, + { + title: intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.ParameterValue', + defaultMessage: '参数值', + }), + dataIndex: 'value', + render: (text, record) => + record.adaptive + ? intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.Adaptive', + defaultMessage: '自动分配', + }) + : text || '-', + }, + { + title: intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.Introduction', + defaultMessage: '介绍', + }), + dataIndex: 'description', + render: (text) => ( + +
    {text}
    +
    + ), + }, + ]; + + return columns; + }; + + const componentsList = getComponentsList(); + const componentsNodeConfigList = getComponentsNodeConfigList(); + const initDir = `${home_path}/oceanbase/store`; + const clusterConfigInfo = [ + { + key: 'cluster', + group: intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.ClusterConfiguration', + defaultMessage: '集群配置', + }), + content: [ + { + label: intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.ConfigurationMode', + defaultMessage: '配置模式', + }), + colSpan: 5, + value: modeConfig[oceanbase?.mode], + }, + { + label: intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.RootSysPassword', + defaultMessage: 'root@sys 密码', + }), + colSpan: 5, + value: ( + +
    {oceanbase?.root_password}
    +
    + ), + }, + { + label: intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.DataDirectory', + defaultMessage: '数据目录', + }), + value: ( + +
    {oceanbase?.data_dir || initDir}
    +
    + ), + }, + { + label: intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.LogDirectory', + defaultMessage: '日志目录', + }), + value: ( + +
    {oceanbase?.redo_dir || initDir}
    +
    + ), + }, + { + label: intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.SqlPort', + defaultMessage: 'SQL 端口', + }), + colSpan: 3, + value: oceanbase?.mysql_port, + }, + { + label: intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.RpcPort', + defaultMessage: 'RPC 端口', + }), + colSpan: 3, + value: oceanbase?.rpc_port, + }, + ], + + more: oceanbase?.parameters?.length + ? [ + { + label: componentsConfig['oceanbase'].labelName, + parameters: oceanbase?.parameters, + }, + ] + : [], + }, + ]; + + if (selectedConfig.length) { + let content: any[] = [], + more: any = []; + if (selectedConfig.includes('obproxy')) { + content = content.concat( + { + label: intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.ObproxyServicePort', + defaultMessage: 'OBProxy 服务端口', + }), + value: obproxy?.listen_port, + }, + { + label: intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.PortObproxyExporter', + defaultMessage: 'OBProxy Exporter 端口', + }), + value: obproxy?.prometheus_listen_port, + }, + ); + obproxy?.parameters?.length && + more.push({ + label: componentsConfig['obproxy'].labelName, + parameters: obproxy?.parameters, + }); + } + + if (selectedConfig.includes('obagent')) { + content = content.concat( + { + label: intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.ObagentMonitoringServicePort', + defaultMessage: 'OBAgent 监控服务端口', + }), + value: obagent?.monagent_http_port, + }, + { + label: intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.ObagentManageServicePorts', + defaultMessage: 'OBAgent 管理服务端口', + }), + value: obagent?.mgragent_http_port, + }, + ); + obagent?.parameters?.length && + more.push({ + label: componentsConfig['obagent'].labelName, + parameters: obagent?.parameters, + }); + } + // more是否有数据跟前面是否打开更多配置有关 + if (!lowVersion && selectedConfig.includes('ocp-express')) { + content.push({ + label: intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.PortOcpExpress', + defaultMessage: 'OCP Express 端口', + }), + value: ocpexpress?.port, + }); + ocpexpress?.parameters?.length && + more.push({ + label: componentsConfig['ocpexpress'].labelName, + parameters: ocpexpress?.parameters, + }); + } + + clusterConfigInfo.push({ + key: 'components', + group: intl.formatMessage({ + id: 'OBD.pages.components.CheckInfo.ComponentConfiguration', + defaultMessage: '组件配置', + }), + content, + more, + }); + } + + return ( + + + + + + +
    + + + {oceanbase?.appname} + + + + + + + {componentsList.map( + (item: API.TableComponentInfo, index: number) => ( + 1 ? { marginTop: 16 } : {}} + key={item.key} + > + + + {item?.showComponentName} + + + {componentsConfig[item.key]?.type} + + + {item?.version} + + + + ), + )} + + + + + + + + +
    + + + {selectedConfig.length ? ( + + + + {componentsNodeConfigList.map( + (item: ComponentsNodeConfig) => ( + + {item.isTooltip ? ( + +
    {item?.servers}
    +
    + ) : ( + item?.servers + )} +
    + ), + )} +
    + + + ) : null} + + + + + {auth?.user} + + + + + + + + + + + {home_path} + + + + + + + + + + {clusterConfigInfo?.map((item, index) => ( + + + + {item.content.map((subItem) => ( + + {subItem.value} + + ))} + + + {item?.more?.length ? ( + + {item?.more.map((moreItem) => ( + +
    + + ))} + + ) : null} + + ))} + + +
    +
    + + + + + +
    +
    + + ); +} diff --git a/web/src/pages/Obdeploy/ClusterConfig/ConfigTable.tsx b/web/src/pages/Obdeploy/ClusterConfig/ConfigTable.tsx new file mode 100644 index 0000000..a420b2d --- /dev/null +++ b/web/src/pages/Obdeploy/ClusterConfig/ConfigTable.tsx @@ -0,0 +1,142 @@ +import { Space, Table, Spin, Form, Tooltip, InputNumber } from 'antd'; +import { ProCard, ProForm } from '@ant-design/pro-components'; +import { getLocale } from 'umi'; +import type { ColumnsType } from 'antd/es/table'; + +import { intl } from '@/utils/intl'; +import Parameter from './Parameter'; +import EnStyles from '../indexEn.less'; +import ZhStyles from '../indexZh.less'; +import { ReactElement } from 'react'; + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; +interface ConfigTableProps { + showVisible: boolean; + dataSource: API.NewParameterMeta[]; + loading: boolean; + customParameter?: JSX.Element; +} + +const parameterValidator = (_: any, value?: API.ParameterValue) => { + if (value?.adaptive) { + return Promise.resolve(); + } else if (value?.require && !value?.value) { + return Promise.reject( + new Error( + intl.formatMessage({ + id: 'OBD.pages.components.ClusterConfig.RequiredForCustomParameters', + defaultMessage: '自定义参数时必填', + }), + ), + ); + } + return Promise.resolve(); +}; + +const getMoreColumns = ( + label: string, + componentKey: string, + customParameter?: JSX.Element, +) => { + const columns: ColumnsType = [ + { + title: label, + dataIndex: 'name', + width: 250, + render: (text) => text || '-', + }, + { + title: intl.formatMessage({ + id: 'OBD.Obdeploy.ClusterConfig.ConfigTable.ParameterValue', + defaultMessage: '参数值', + }), + width: locale === 'zh-CN' ? 280 : 360, + dataIndex: 'parameterValue', + render: (parameterValue, record) => { + return ( + + + + ); + }, + }, + { + title: intl.formatMessage({ + id: 'OBD.pages.components.ClusterConfig.Introduction', + defaultMessage: '介绍', + }), + dataIndex: 'description', + render: (text, record) => + text ? ( + + +
    {text}
    +
    +
    + ) : ( + '-' + ), + }, + ]; + + return columns; +}; + +export default function ConfigTable({ + showVisible, + dataSource, + loading, + customParameter, +}: ConfigTableProps) { + return ( + <> + {showVisible ? ( + + + {dataSource.map((moreItem) => { + return ( + +
    + + ); + })} + + + ) : null} + + ); +} diff --git a/web/src/pages/Obdeploy/ClusterConfig/Footer.tsx b/web/src/pages/Obdeploy/ClusterConfig/Footer.tsx new file mode 100644 index 0000000..0887f86 --- /dev/null +++ b/web/src/pages/Obdeploy/ClusterConfig/Footer.tsx @@ -0,0 +1,81 @@ +import { Space, Button, Tooltip } from 'antd'; +import { getLocale, useModel } from 'umi'; + +import { intl } from '@/utils/intl'; +import { handleQuit } from '@/utils'; +import EnStyles from '../indexEn.less'; +import ZhStyles from '../indexZh.less'; + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; + +interface FooterProps { + prevStep: () => void; + nextStep: () => void; +} + +export default function Footer({ prevStep, nextStep }: FooterProps) { + const { handleQuitProgress, setCurrentStep } = useModel('global'); + + return ( +
    +
    + + + + + + + +
    +
    + ); +} diff --git a/web/src/pages/Obdeploy/ClusterConfig/Parameter.tsx b/web/src/pages/Obdeploy/ClusterConfig/Parameter.tsx new file mode 100644 index 0000000..4e08382 --- /dev/null +++ b/web/src/pages/Obdeploy/ClusterConfig/Parameter.tsx @@ -0,0 +1,244 @@ +import { intl } from '@/utils/intl'; +import { useEffect, useRef, useState } from 'react'; +import { Space, InputNumber, Input, Select } from 'antd'; +import { getLocale } from 'umi'; +import { getUnit, isTakeUnit, takeNewUnit } from './helper'; +import EnStyles from '../indexEn.less'; +import ZhStyles from '../indexZh.less'; + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; + +interface ParameterProps { + value?: API.ParameterValue; + onChange?: (value?: API.ParameterValue) => void; + onBlur?: () => void; +} + +interface AdaptiveInputProps { + parameterValue: API.ParameterValue; + onBlur?: () => void; + setParameterValue: (prop: API.ParameterValue) => void; +} + +type OptionsType = { + label: string; + value: string | Boolean; +}[]; + +const optionConfig: OptionsType = [ + { + label: intl.formatMessage({ + id: 'OBD.pages.components.Parameter.AutomaticAllocation', + defaultMessage: '自动分配', + }), + value: true, + }, + { + label: intl.formatMessage({ + id: 'OBD.pages.components.Parameter.Custom', + defaultMessage: '自定义', + }), + value: false, + }, +]; + +const unitOption: OptionsType = [ + { + label: 'KB', + value: 'KB', + }, + { + label: 'MB', + value: 'MB', + }, + { + label: 'GB', + value: 'GB', + }, +]; + +const booleanOption: OptionsType = [ + { + label: 'True', + value: 'True', + }, + { + label: 'False', + value: 'False', + }, +]; + +const AdaptiveInput = ({ + parameterValue, + onBlur, + setParameterValue, +}: AdaptiveInputProps) => { + const { type } = parameterValue; + const defaultUnit = + type === 'CapacityMB' || type === 'Capacity' + ? getUnit(parameterValue.value) + : null; + const unit = useRef(defaultUnit); + if (type === 'int' || type === 'Integer') { + return ( + + value !== null && setParameterValue({ ...parameterValue, value }) + } + /> + ); + } + if (type === 'CapacityMB' || type === 'Capacity') { + return ( +
    + { + if (value !== null) { + setParameterValue({ + ...parameterValue, + value: String(value) + unit.current, + }); + } + }} + addonAfter={ + + } + /> +
    + ); + } + + if (type === 'Boolean') { + return ( + + ); + } + + return ( + + setParameterValue({ ...parameterValue, value: e.target.value }) + } + /> + ); +}; +//参数来由:当Parameter在form.item下时自带有onchange,value +export default function Parameter({ + value: itemValue, + onChange, + onBlur, +}: ParameterProps) { + const [parameterValue, setParameterValue] = useState( + itemValue || {}, + ); + useEffect(() => { + if (onChange) { + if ( + itemValue?.adaptive !== parameterValue?.adaptive || + itemValue?.value !== parameterValue?.value || + itemValue?.type !== parameterValue?.type + ) { + onChange(parameterValue); + } + } + }, [parameterValue]); + return ( + + + + + ); +} diff --git a/web/src/pages/Obdeploy/ClusterConfig/helper.ts b/web/src/pages/Obdeploy/ClusterConfig/helper.ts new file mode 100644 index 0000000..34417ef --- /dev/null +++ b/web/src/pages/Obdeploy/ClusterConfig/helper.ts @@ -0,0 +1,50 @@ +//与UI无关的逻辑处理 + +/** + * 将容量单位转换为约定格式 KB、MB、GB,统一输出为大写 + */ +const getUnit = (val: string = 'GB'): string => { + const res = val.match(/\D+/g)?.[0].toUpperCase() || 'GB'; + if (res.includes('K')) return 'KB'; + if (res.includes('M')) return 'MB'; + if (res.includes('G')) return 'GB'; + return res; +}; + +//是否携带单位 +const isTakeUnit = (val: string | undefined): boolean => { + if (!val) return false; + const upperVal = val.toUpperCase(); + if ( + upperVal.includes('M') || + upperVal.includes('MB') || + upperVal.includes('K') || + upperVal.includes('KB') || + upperVal.includes('G') || + upperVal.includes('GB') + ) { + return true; + } + return false; +}; + +//换新单位 +const takeNewUnit = (target: string, unit: string): string => { + if (!isTakeUnit(target)) { + //无单位 + return target + unit; + } + let targetArr = target.split(''); + let tailStr = targetArr[targetArr.length - 1].toUpperCase(); + if (tailStr === 'K' || tailStr === 'M' || tailStr === 'G') { + //以K|M|G结尾 + targetArr[targetArr.length - 1] = unit; + return targetArr.join(''); + } else { + //以KB|MB|GB结尾 + targetArr.splice(-2, 2, unit); + return targetArr.join(''); + } +}; + +export { getUnit, isTakeUnit, takeNewUnit }; diff --git a/web/src/pages/Obdeploy/ClusterConfig/index.tsx b/web/src/pages/Obdeploy/ClusterConfig/index.tsx new file mode 100644 index 0000000..75e0972 --- /dev/null +++ b/web/src/pages/Obdeploy/ClusterConfig/index.tsx @@ -0,0 +1,815 @@ +import { intl } from '@/utils/intl'; +import { useState, useEffect } from 'react'; +import { useModel, getLocale } from 'umi'; +import { Space, Tooltip, Row, Switch, Table, Spin, Form, message } from 'antd'; +import { QuestionCircleOutlined } from '@ant-design/icons'; +import { + ProCard, + ProForm, + ProFormText, + ProFormRadio, + ProFormDigit, +} from '@ant-design/pro-components'; +import { getErrorInfo, getRandomPassword } from '@/utils'; +import useRequest from '@/utils/useRequest'; +import { queryComponentParameters } from '@/services/ob-deploy-web/Components'; +import { showConfigKeys } from '@/constant/configuration'; +import TooltipInput from '../TooltipInput'; +import ConfigTable from './ConfigTable'; +import Parameter from './Parameter'; +import Footer from './Footer'; +import { + commonStyle, + pathRule, + onlyComponentsKeys, + componentsConfig, + componentVersionTypeToComponent, +} from '../../constants'; +import EnStyles from '../indexEn.less'; +import ZhStyles from '../indexZh.less'; + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; + +interface FormValues extends API.Components { + oceanbase?: { + mode?: string; + parameters?: any; + }; +} + +export default function ClusterConfig() { + const { + selectedConfig, + setCurrentStep, + configData, + setConfigData, + lowVersion, + clusterMore, + setClusterMore, + componentsMore, + setComponentsMore, + clusterMoreConfig, + setClusterMoreConfig, + componentsMoreConfig, + setComponentsMoreConfig, + setErrorVisible, + setErrorsList, + errorsList, + } = useModel('global'); + const { components = {}, home_path } = configData || {}; + const { + oceanbase = {}, + ocpexpress = {}, + obproxy = {}, + obagent = {}, + } = components; + const [form] = ProForm.useForm(); + const [currentMode, setCurrentMode] = useState( + oceanbase?.mode || 'PRODUCTION', + ); + + const [passwordVisible, setPasswordVisible] = useState(true); + const [clusterMoreLoading, setClusterMoreLoading] = useState(false); + const [componentsMoreLoading, setComponentsMoreLoading] = useState(false); + const { run: getMoreParamsters } = useRequest(queryComponentParameters); + + const formatParameters = (dataSource: any) => { + if (dataSource) { + const parameterKeys = Object.keys(dataSource); + return parameterKeys.map((key) => { + const { params, ...rest } = dataSource[key]; + return { + key, + ...rest, + ...params, + }; + }); + } else { + return []; + } + }; + + const setData = (dataSource: FormValues) => { + let newComponents: API.Components = { ...components }; + if (selectedConfig.includes('obproxy')) { + newComponents.obproxy = { + ...(components.obproxy || {}), + ...dataSource.obproxy, + parameters: formatParameters(dataSource.obproxy?.parameters), + }; + } + if (selectedConfig.includes('ocp-express') && !lowVersion) { + newComponents.ocpexpress = { + ...(components.ocpexpress || {}), + ...dataSource.ocpexpress, + parameters: formatParameters(dataSource.ocpexpress?.parameters), + }; + } + if (selectedConfig.includes('obagent')) { + newComponents.obagent = { + ...(components.obagent || {}), + ...dataSource.obagent, + parameters: formatParameters(dataSource.obagent?.parameters), + }; + } + newComponents.oceanbase = { + ...(components.oceanbase || {}), + ...dataSource.oceanbase, + parameters: formatParameters(dataSource.oceanbase?.parameters), + }; + setConfigData({ ...configData, components: newComponents }); + }; + + const prevStep = () => { + const formValues = form.getFieldsValue(true); + setData(formValues); + setCurrentStep(2); + setErrorVisible(false); + setErrorsList([]); + window.scrollTo(0, 0); + }; + + const nextStep = () => { + form + .validateFields() + .then((values) => { + setData(values); + setCurrentStep(4); + setErrorVisible(false); + setErrorsList([]); + window.scrollTo(0, 0); + }) + .catch(({ errorFields }) => { + const errorName = errorFields?.[0].name; + form.scrollToField(errorName); + message.destroy(); + if (errorName.includes('parameters')) { + message.warning( + intl.formatMessage({ + id: 'OBD.pages.components.ClusterConfig.RequiredParametersForMoreConfigurations', + defaultMessage: '更多配置有必填参数未填入', + }), + ); + } + }); + }; + + const onValuesChange = (values: FormValues) => { + if (values?.oceanbase?.mode) { + setCurrentMode(values?.oceanbase?.mode); + } + }; + + const portValidator = (_: any, value: number) => { + if (value) { + if (value >= 1024 && value <= 65535) { + return Promise.resolve(); + } + return Promise.reject( + new Error( + intl.formatMessage({ + id: 'OBD.pages.components.ClusterConfig.ThePortNumberCanOnly', + defaultMessage: '端口号只支持 1024~65535 范围', + }), + ), + ); + } + }; + + const formatMoreConfig = (dataSource: API.ParameterMeta[]) => { + return dataSource.map((item) => { + const component = componentVersionTypeToComponent[item.component] + ? componentVersionTypeToComponent[item.component] + : item.component; + const componentConfig = componentsConfig[component]; + // filter out existing parameters + let configParameter = item?.config_parameters.filter((parameter) => { + return !showConfigKeys?.[componentConfig.componentKey]?.includes( + parameter.name, + ); + }); + const newConfigParameter: API.NewConfigParameter[] = configParameter.map( + (parameterItem) => { + return { + ...parameterItem, + parameterValue: { + value: parameterItem.default, + adaptive: parameterItem.auto, + auto: parameterItem.auto, + require: parameterItem.require, + }, + }; + }, + ); + + const result: API.NewParameterMeta = { + ...item, + componentKey: componentConfig.componentKey, + label: componentConfig.labelName, + configParameter: newConfigParameter, + }; + result.configParameter.forEach((item) => { + Object.assign(item.parameterValue, { type: item.type }); + }); + return result; + }); + }; + + const getInitialParameters = ( + currentComponent: string, + dataSource: API.MoreParameter[], + data: API.NewParameterMeta[], + ) => { + const currentComponentNameConfig = data?.filter( + (item) => item.component === currentComponent, + )?.[0]; + if (currentComponentNameConfig) { + const parameters: any = {}; + currentComponentNameConfig.configParameter.forEach((item) => { + let parameter = { + ...item, + key: item.name, + params: { + value: item.default, + adaptive: item.auto, + auto: item.auto, + require: item.require, + type: item.type, + }, + }; + dataSource?.some((dataItem) => { + if (item.name === dataItem.key) { + parameter = { + key: dataItem.key, + description: parameter.description, + params: { + ...parameter.params, + ...dataItem, + }, + }; + return true; + } + return false; + }); + if ( + (parameter.params.type === 'CapacityMB' || parameter.params.type === 'Capacity') && + parameter.params.value == '0' + ) { + parameter.params.value += 'GB'; + } + parameters[item.name] = parameter; + }); + return parameters; + } else { + return undefined; + } + }; + + const getClusterMoreParamsters = async () => { + setClusterMoreLoading(true); + try { + const { success, data } = await getMoreParamsters( + {}, + { + filters: [ + { + component: oceanbase?.component, + version: oceanbase?.version, + is_essential_only: true, + }, + ], + }, + ); + if (success) { + const newClusterMoreConfig = formatMoreConfig(data?.items); + setClusterMoreConfig(newClusterMoreConfig); + form.setFieldsValue({ + oceanbase: { + parameters: getInitialParameters( + oceanbase?.component, + oceanbase?.parameters, + newClusterMoreConfig, + ), + }, + }); + } + } catch (e: any) { + setClusterMore(false); + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + } + setClusterMoreLoading(false); + }; + + const getComponentsMoreParamsters = async () => { + const filters: API.ParameterFilter[] = []; + let currentOnlyComponentsKeys: string[] = onlyComponentsKeys; + if (lowVersion) { + currentOnlyComponentsKeys = onlyComponentsKeys.filter( + (key) => key !== 'ocpexpress', + ); + } + currentOnlyComponentsKeys.forEach((item) => { + if (components[item]) { + filters.push({ + component: components[item]?.component, + version: components[item]?.version, + is_essential_only: true, + }); + } + }); + setComponentsMoreLoading(true); + try { + const { success, data } = await getMoreParamsters({}, { filters }); + if (success) { + const newComponentsMoreConfig = formatMoreConfig(data?.items); + setComponentsMoreConfig(newComponentsMoreConfig); + const setValues = { + obproxy: { + parameters: getInitialParameters( + obproxy?.component, + obproxy?.parameters, + newComponentsMoreConfig, + ), + }, + obagent: { + parameters: getInitialParameters( + obagent?.component, + obagent?.parameters, + newComponentsMoreConfig, + ), + }, + }; + if (!lowVersion) { + setValues.ocpexpress = { + parameters: getInitialParameters( + ocpexpress?.component, + ocpexpress?.parameters, + newComponentsMoreConfig, + ), + }; + } + form.setFieldsValue(setValues); + } + } catch (e) { + setComponentsMore(false); + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + } + + setComponentsMoreLoading(false); + }; + + const handleCluserMoreChange = (checked: boolean) => { + setClusterMore(checked); + if (!clusterMoreConfig?.length) { + getClusterMoreParamsters(); + } + }; + + const handleComponentsMoreChange = (checked: boolean) => { + setComponentsMore(checked); + if (!componentsMoreConfig?.length) { + getComponentsMoreParamsters(); + } + }; + + useEffect(() => { + if (clusterMore) { + getClusterMoreParamsters(); + } + if (componentsMore) { + getComponentsMoreParamsters(); + } + }, [selectedConfig]); + + const initPassword = getRandomPassword(); + + const initialValues = { + oceanbase: { + mode: oceanbase?.mode || 'PRODUCTION', + root_password: oceanbase?.root_password || initPassword, + data_dir: oceanbase?.data_dir || undefined, + redo_dir: oceanbase?.redo_dir || undefined, + mysql_port: oceanbase?.mysql_port || 2881, + rpc_port: oceanbase?.rpc_port || 2882, + parameters: getInitialParameters( + oceanbase?.component, + oceanbase?.parameters, + clusterMoreConfig, + ), + }, + obproxy: { + listen_port: obproxy?.listen_port || 2883, + prometheus_listen_port: obproxy?.prometheus_listen_port || 2884, + parameters: getInitialParameters( + obproxy?.component, + obproxy?.parameters, + componentsMoreConfig, + ), + }, + obagent: { + monagent_http_port: obagent?.monagent_http_port || 8088, + mgragent_http_port: obagent?.mgragent_http_port || 8089, + parameters: getInitialParameters( + obagent?.component, + obagent?.parameters, + componentsMoreConfig, + ), + }, + }; + + if (!lowVersion) { + initialValues.ocpexpress = { + port: ocpexpress?.port || 8180, + parameters: getInitialParameters( + ocpexpress?.component, + ocpexpress?.parameters, + componentsMoreConfig, + ), + }; + } + + const singleItemStyle = { width: 448 }; + const initDir = `${home_path}/oceanbase/store`; + return ( + + + + + + + {intl.formatMessage({ + id: 'OBD.pages.components.ClusterConfig.ViewModeConfigurationRules', + defaultMessage: '查看模式配置规则', + })} + +
    +
    + {currentMode === 'PRODUCTION' + ? intl.formatMessage({ + id: 'OBD.pages.components.ClusterConfig.ThisModeWillMaximizeThe', + defaultMessage: + '此模式将最大化利用环境资源,保证集群的性能与稳定性,推荐使用此模式。', + }) + : intl.formatMessage({ + id: 'OBD.pages.components.ClusterConfig.ConfigureResourceParametersThatMeet', + defaultMessage: '配置满足集群正常运行的资源参数', + })} +
    +
    + + + + + + + + + + + + + + + + + + + +
    + {intl.formatMessage({ + id: 'OBD.pages.components.ClusterConfig.MoreConfigurations', + defaultMessage: '更多配置', + })} + + +
    + } + /> +
    +
    + {selectedConfig.length ? ( + + + {selectedConfig.includes('obproxy') && ( + + + + + + {intl.formatMessage({ + id: 'OBD.pages.components.ClusterConfig.PortObproxyExporter', + defaultMessage: 'OBProxy Exporter 端口', + })} + + + + + + } + fieldProps={{ style: commonStyle }} + placeholder={intl.formatMessage({ + id: 'OBD.pages.components.ClusterConfig.PleaseEnter', + defaultMessage: '请输入', + })} + rules={[ + { + required: true, + message: intl.formatMessage({ + id: 'OBD.pages.components.ClusterConfig.PleaseEnter', + defaultMessage: '请输入', + }), + }, + { validator: portValidator }, + ]} + /> + + + )} + {selectedConfig.includes('obagent') && ( + + + + + + + + )} + {selectedConfig.includes('ocp-express') && !lowVersion && ( + + + + )} +
    + {intl.formatMessage({ + id: 'OBD.pages.components.ClusterConfig.MoreConfigurations', + defaultMessage: '更多配置', + })} + + +
    + } + /> +
    +
    + ) : null} +
    + + + ); +} diff --git a/web/src/pages/Obdeploy/DeleteDeployModal.tsx b/web/src/pages/Obdeploy/DeleteDeployModal.tsx new file mode 100644 index 0000000..d7107d7 --- /dev/null +++ b/web/src/pages/Obdeploy/DeleteDeployModal.tsx @@ -0,0 +1,259 @@ +import { intl } from '@/utils/intl'; +import { useEffect, useState } from 'react'; +import { useModel } from 'umi'; +import { Modal, Progress, message } from 'antd'; +import { getDestroyTaskInfo } from '@/services/ob-deploy-web/Deployments'; +import useRequest from '@/utils/useRequest'; +import { checkLowVersion, getErrorInfo } from '@/utils'; +import NP from 'number-precision'; +import { oceanbaseComponent, obproxyComponent } from '../constants'; +import { getLocale } from 'umi'; +import EnStyles from './indexEn.less'; +import ZhStyles from './indexZh.less'; + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; + +interface Props { + visible: boolean; + name: string; + onCancel: () => void; + setOBVersionValue: (value: string) => void; +} + +let timerProgress: NodeJS.Timer; +let timerFetch: NodeJS.Timer; + +const statusConfig = { + RUNNING: 'normal', + SUCCESSFUL: 'success', + FAILED: 'exception', +}; + +export default function DeleteDeployModal({ + visible, + name, + onCancel, + setOBVersionValue, +}: Props) { + const { + selectedConfig, + setSelectedConfig, + setConfigData, + setIsDraft, + setClusterMore, + setComponentsMore, + componentsVersionInfo, + setComponentsVersionInfo, + getInfoByName, + setLowVersion, + setErrorVisible, + setErrorsList, + errorsList, + } = useModel('global'); + + const [status, setStatus] = useState('RUNNING'); + const [progress, setProgress] = useState(0); + const [showProgress, setShowProgress] = useState(0); + const [isFinished, setIsFinished] = useState(false); + + const { run: fetchDestroyTaskInfo } = useRequest(getDestroyTaskInfo, { + onSuccess: async ({ success, data }: API.OBResponseTaskInfo_) => { + if (success) { + if (data?.status !== 'RUNNING') { + clearInterval(timerFetch); + } + clearInterval(timerProgress); + if (data?.status === 'RUNNING') { + const newProgress = NP.times( + NP.divide(data?.finished, data?.total), + 100, + ); + + setProgress(newProgress); + let step = NP.minus(newProgress, progress); + let stepNum = 1; + timerProgress = setInterval(() => { + setShowProgress( + NP.plus(progress, NP.times(NP.divide(step, 100), stepNum)), + ); + + stepNum += 1; + }, 10); + } else if (data?.status === 'SUCCESSFUL') { + let step = NP.minus(100, progress); + let stepNum = 1; + timerProgress = setInterval(() => { + setShowProgress( + NP.plus(progress, NP.times(NP.divide(step, 100), stepNum)), + ); + + stepNum += 1; + }, 10); + try { + const { success: nameSuccess, data: nameData } = + await getInfoByName({ name }); + if (nameSuccess) { + const { config } = nameData; + const { components = {} } = config; + const newSelectedConfig:string[] = [] + Object.keys(components).forEach((key)=>{ + if(selectedConfig.includes(key) && components[key]){ + newSelectedConfig.push(key) + }else if(key === 'ocpexpress' && components[key]){ + // todo:同步为ocpexpress + newSelectedConfig.push('ocp-express') + } + }) + setSelectedConfig(newSelectedConfig) + setConfigData(config || {}); + setLowVersion(checkLowVersion(components?.oceanbase?.version)); + setClusterMore(!!components?.oceanbase?.parameters?.length); + setComponentsMore(!!components?.obproxy?.parameters?.length); + setIsDraft(true); + + const newSelectedVersionInfo = componentsVersionInfo?.[ + oceanbaseComponent + ]?.dataSource?.filter( + (item: any) => item.md5 === components?.oceanbase?.package_hash, + )[0]; + if (newSelectedVersionInfo) { + setOBVersionValue( + `${components?.oceanbase?.version}-${components?.oceanbase?.release}-${components?.oceanbase?.package_hash}`, + ); + + let currentObproxyVersionInfo = {}; + componentsVersionInfo?.[ + obproxyComponent + ]?.dataSource?.some((item: API.service_model_components_ComponentInfo) => { + if (item?.version_type === newSelectedVersionInfo?.version_type) { + currentObproxyVersionInfo = item; + return true; + } + return false + }); + + setComponentsVersionInfo({ + ...componentsVersionInfo, + [oceanbaseComponent]: { + ...componentsVersionInfo[oceanbaseComponent], + ...newSelectedVersionInfo, + }, + [obproxyComponent]: { + ...componentsVersionInfo[obproxyComponent], + ...currentObproxyVersionInfo + } + }); + } + setTimeout(() => { + onCancel(); + }, 2000); + } else { + setIsDraft(false); + message.error( + intl.formatMessage({ + id: 'OBD.pages.components.DeleteDeployModal.FailedToObtainConfigurationInformation', + defaultMessage: '获取配置信息失败', + }), + ); + onCancel(); + } + } catch (e: any) { + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + } + } else { + message.error(data?.msg); + onCancel(); + } + setStatus(data?.status); + } + }, + onError: (e: any) => { + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }); + + useEffect(() => { + fetchDestroyTaskInfo({ name }); + timerFetch = setInterval(() => { + fetchDestroyTaskInfo({ name }); + }, 1000); + return () => { + clearInterval(timerProgress); + clearInterval(timerFetch); + }; + }, []); + + useEffect(() => { + if (status !== 'RUNNING') { + setTimeout(() => { + clearInterval(timerProgress); + setIsFinished(true); + }, 1000); + } + }, [status]); + + return ( + +
    + {isFinished ? ( + <> +
    + {status === 'SUCCESSFUL' + ? intl.formatMessage({ + id: 'OBD.pages.components.DeleteDeployModal.FailedHistoryDeploymentEnvironmentCleared', + defaultMessage: '清理失败历史部署环境成功', + }) + : intl.formatMessage({ + id: 'OBD.pages.components.DeleteDeployModal.FailedToCleanUpThe', + defaultMessage: '清理失败历史部署环境失败', + })} +
    + + + ) : ( + <> +
    + {intl.formatMessage({ + id: 'OBD.pages.components.DeleteDeployModal.CleaningFailedHistoricalDeploymentEnvironments', + defaultMessage: '正在清理失败的历史部署环境', + })} + +
    + {intl.formatMessage({ + id: 'OBD.pages.components.DeleteDeployModal.PleaseWaitPatiently', + defaultMessage: '请耐心等待', + })} +
    +
    + + + )} +
    +
    + ); +} diff --git a/web/src/pages/Obdeploy/DeployType.tsx b/web/src/pages/Obdeploy/DeployType.tsx new file mode 100644 index 0000000..48f6736 --- /dev/null +++ b/web/src/pages/Obdeploy/DeployType.tsx @@ -0,0 +1,90 @@ +import { intl } from '@/utils/intl'; +import { useEffect, useState } from 'react'; +import { Space, Card, Tag } from 'antd'; +import { getLocale } from 'umi'; +import EnStyles from './indexEn.less'; +import ZhStyles from './indexZh.less'; + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; + +interface Props { + value?: string; + onChange?: (value: string) => void; +} + +const optionConfig = [ + { + label: ( + <> + {intl.formatMessage({ + id: 'OBD.pages.components.DeployType.FullyDeployed', + defaultMessage: '完全部署', + })} + + {intl.formatMessage({ + id: 'OBD.pages.components.DeployType.Recommended', + defaultMessage: '推荐', + })} + + + ), + + value: 'all', + desc: intl.formatMessage({ + id: 'OBD.pages.components.DeployType.ConfigureDatabaseClustersAndRelated', + defaultMessage: + '配置数据库集群及相关生态工具,提供全套数据库运维管理服务', + }), + }, + { + label: intl.formatMessage({ + id: 'OBD.pages.components.DeployType.ThinDeployment', + defaultMessage: '精简部署', + }), + value: 'ob', + desc: intl.formatMessage({ + id: 'OBD.pages.components.DeployType.OnlyDatabaseClustersAreConfigured', + defaultMessage: '只配置数据库集群,以最精简的数据库内核能力提供服务', + }), + }, +]; + +export default function DeployType({ value, onChange }: Props) { + const [selectValue, setSelectValue] = useState(value || 'all'); + + useEffect(() => { + if (value && value !== selectValue) { + setSelectValue(value); + } + }, [value]); + + useEffect(() => { + if (onChange) { + onChange(selectValue); + } + }, [selectValue]); + return ( + + {optionConfig.map((item) => ( +
    + setSelectValue(item.value)} + > + {item.label} + + + {item.desc} + +
    + ))} +
    + ); +} diff --git a/web/src/pages/Obdeploy/ExitPage.tsx b/web/src/pages/Obdeploy/ExitPage.tsx new file mode 100644 index 0000000..bb35474 --- /dev/null +++ b/web/src/pages/Obdeploy/ExitPage.tsx @@ -0,0 +1,71 @@ +import { intl } from '@/utils/intl'; +import { message, Card, Empty } from 'antd'; +import { CopyOutlined } from '@ant-design/icons'; +import copy from 'copy-to-clipboard'; +import { getLocale } from 'umi'; +import ExitPageWrapper from '@/component/ExitPageWrapper'; +import EnStyles from './indexEn.less'; +import ZhStyles from './indexZh.less'; + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; + +export default function ExitPage() { + const command = 'obd web'; + + const handleCopy = () => { + copy(command); + message.success( + intl.formatMessage({ + id: 'OBD.pages.components.ExitPage.CopiedSuccessfully', + defaultMessage: '复制成功', + }), + ); + }; + + return ( + + + +

    + {intl.formatMessage({ + id: 'OBD.pages.components.ExitPage.TheDeploymentProgramHasExited', + defaultMessage: '部署程序已经退出!', + })} +

    +
    + {intl.formatMessage({ + id: 'OBD.pages.components.ExitPage.ToStartAgainGoTo', + defaultMessage: '如需再次启动,请前往中控服务器执行', + })} + + + {command} + +
    +
    +
    + ); +} diff --git a/web/src/pages/Obdeploy/InstallConfig.tsx b/web/src/pages/Obdeploy/InstallConfig.tsx new file mode 100644 index 0000000..92cb8d3 --- /dev/null +++ b/web/src/pages/Obdeploy/InstallConfig.tsx @@ -0,0 +1,1090 @@ +import { intl } from '@/utils/intl'; +import { useEffect, useState, useRef } from 'react'; +import { useModel, history } from 'umi'; +import { + Space, + Button, + Form, + Tag, + Table, + Alert, + Tooltip, + Select, + Modal, + Spin, + message, +} from 'antd'; +import { ProCard, ProForm, ProFormText } from '@ant-design/pro-components'; +import { + CloseOutlined, + SafetyCertificateFilled, + InfoOutlined, + InfoCircleOutlined, + CopyOutlined, +} from '@ant-design/icons'; +import type { ColumnsType } from 'antd/es/table'; +import useRequest from '@/utils/useRequest'; +import { queryAllComponentVersions } from '@/services/ob-deploy-web/Components'; +import { + getDeployment, + destroyDeployment, +} from '@/services/ob-deploy-web/Deployments'; +import { listRemoteMirrors } from '@/services/ob-deploy-web/Mirror'; +import { handleQuit, checkLowVersion, getErrorInfo } from '@/utils'; +import NP from 'number-precision'; +import copy from 'copy-to-clipboard'; +import DeployType from './DeployType'; +import DeleteDeployModal from './DeleteDeployModal'; +import ErrorCompToolTip from '@/component/ErrorCompToolTip'; +import { + commonStyle, + allComponentsName, + oceanbaseComponent, + obproxyComponent, + ocpexpressComponent, + obagentComponent, +} from '../constants'; +import { getLocale } from 'umi'; +import { clusterNameReg } from '@/utils'; +import EnStyles from './indexEn.less'; +import ZhStyles from './indexZh.less'; + +type rowDataType = { + key: string; + name: string; + onlyAll: boolean; + desc: string; + doc: string; +}; + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; +const appnameReg = /^[a-zA-Z]([a-zA-Z0-9]{0,19})$/; + +const oceanBaseInfo = { + group: intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.Database', + defaultMessage: '数据库', + }), + key: 'database', + content: [ + { + key: oceanbaseComponent, + name: 'OceanBase Database', + onlyAll: false, + desc: intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.ItIsAFinancialLevel', + defaultMessage: + '是金融级分布式数据库,具备数据强一致、高扩展、高可用、高性价比、稳定可靠等特征。', + }), + doc: 'https://www.oceanbase.com/docs/oceanbase-database-cn', + }, + ], +}; +const componentsGroupInfo = [ + { + group: intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.Proxy', + defaultMessage: '代理', + }), + key: 'agency', + onlyAll: true, + content: [ + { + key: obproxyComponent, + name: 'OBProxy', + onlyAll: true, + desc: intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.ItIsAProxyServer', + defaultMessage: + '是 OceanBase 数据库专用的代理服务器,可以将用户 SQL 请求转发至最佳目标 OBServer 。', + }), + doc: 'https://www.oceanbase.com/docs/odp-enterprise-cn', + }, + ], + }, + { + group: intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.Tools', + defaultMessage: '工具', + }), + key: 'ocpexpressTool', + onlyAll: true, + content: [ + { + key: ocpexpressComponent, + name: 'OCP Express', + onlyAll: true, + desc: intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.ItIsAManagementAnd', + defaultMessage: + '是专为 OceanBase 设计的管控平台,可实现对集群、租户的监控管理、诊断等核心能力。', + }), + doc: 'https://www.oceanbase.com/docs/common-oceanbase-database-cn-0000000001626262', + }, + ], + }, + { + group: intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.Tools', + defaultMessage: '工具', + }), + key: 'obagentTool', + onlyAll: true, + content: [ + { + key: obagentComponent, + name: 'OBAgent', + onlyAll: true, + desc: intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.IsAMonitoringAndCollection', + defaultMessage: + '是一个监控采集框架。OBAgent 支持推、拉两种数据采集模式,可以满足不同的应用场景。', + }), + doc: 'https://www.oceanbase.com/docs/common-oceanbase-database-cn-10000000001576872', + }, + ], + }, +]; + +const mirrors = ['oceanbase.community.stable', 'oceanbase.development-kit']; + +export default function InstallConfig() { + const { + initAppName, + setCurrentStep, + configData, + setConfigData, + lowVersion, + isFirstTime, + setIsFirstTime, + isDraft, + setIsDraft, + componentsVersionInfo, + setComponentsVersionInfo, + handleQuitProgress, + getInfoByName, + setLowVersion, + setErrorVisible, + errorsList, + setErrorsList, + selectedConfig, + setSelectedConfig, + aliveTokenTimer, + } = useModel('global'); + const { components, home_path } = configData || {}; + const { oceanbase } = components || {}; + const [existNoVersion, setExistNoVersion] = useState(false); + const [obVersionValue, setOBVersionValue] = useState( + undefined, + ); + + const [hasDraft, setHasDraft] = useState(false); + const [deleteLoadingVisible, setDeleteLoadingVisible] = useState(false); + const [deleteName, setDeleteName] = useState(''); + const [deployMemory, setDeployMemory] = useState(0); + const [componentsMemory, setComponentsMemory] = useState(0); + const [form] = ProForm.useForm(); + const [unavailableList, setUnavailableList] = useState([]); + const [componentLoading, setComponentLoading] = useState(false); + const draftNameRef = useRef(); + + const { run: fetchDeploymentInfo, loading } = useRequest(getDeployment, { + onError: (e: any) => { + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }); + const { run: handleDeleteDeployment } = useRequest(destroyDeployment, { + onError: (e: any) => { + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }); + const { run: fetchListRemoteMirrors } = useRequest(listRemoteMirrors, { + onSuccess: () => { + setComponentLoading(false); + }, + onError: ({ response, data, type }: any) => { + if (response?.status === 503) { + setTimeout(() => { + fetchListRemoteMirrors(); + }, 1000); + } else { + const errorInfo = getErrorInfo({ response, data, type }); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + setComponentLoading(false); + } + }, + }); + + const judgVersions = (source: API.ComponentsVersionInfo) => { + if (Object.keys(source).length !== allComponentsName.length) { + setExistNoVersion(true); + } else { + setExistNoVersion(false); + } + }; + + const { run: fetchAllComponentVersions, loading: versionLoading } = + useRequest(queryAllComponentVersions, { + onSuccess: async ({ + success, + data, + }: API.OBResponseDataListComponent_) => { + if (success) { + const newComponentsVersionInfo = {}; + const oceanbaseVersionsData = data?.items?.filter( + (item) => item.name === oceanbaseComponent, + ); + + const initOceanbaseVersionInfo = + oceanbaseVersionsData[0]?.info[0] || {}; + const newSelectedOceanbaseVersionInfo = + oceanbaseVersionsData[0]?.info?.filter( + (item) => item.md5 === oceanbase?.package_hash, + )?.[0]; + + const currentOceanbaseVersionInfo = + newSelectedOceanbaseVersionInfo || initOceanbaseVersionInfo; + + data?.items?.forEach((item) => { + if (allComponentsName.includes(item.name)) { + if (item?.info?.length) { + const initVersionInfo = item?.info[0] || {}; + if (item.name === oceanbaseComponent) { + setOBVersionValue( + `${currentOceanbaseVersionInfo?.version}-${currentOceanbaseVersionInfo?.release}-${currentOceanbaseVersionInfo?.md5}`, + ); + newComponentsVersionInfo[item.name] = { + ...currentOceanbaseVersionInfo, + dataSource: item.info || [], + }; + } else if (item.name === obproxyComponent) { + let currentObproxyVersionInfo = {}; + item?.info?.some((subItem) => { + if ( + subItem?.version_type === + currentOceanbaseVersionInfo?.version_type + ) { + currentObproxyVersionInfo = subItem; + return true; + } + return false; + }); + newComponentsVersionInfo[item.name] = { + ...currentObproxyVersionInfo, + dataSource: item.info || [], + }; + } else { + newComponentsVersionInfo[item.name] = { + ...initVersionInfo, + dataSource: item.info || [], + }; + } + } + } + }); + + const noVersion = + Object.keys(newComponentsVersionInfo).length !== + allComponentsName.length; + judgVersions(newComponentsVersionInfo); + setComponentsVersionInfo(newComponentsVersionInfo); + + if (noVersion) { + const { success: mirrorSuccess, data: mirrorData } = + await fetchListRemoteMirrors(); + if (mirrorSuccess) { + const nameList: string[] = []; + if (mirrorData?.total < 2) { + const mirrorName = mirrorData?.items?.map( + (item: API.Mirror) => item.section_name, + ); + + const noDataName = [...mirrorName, ...mirrors].filter( + (name) => + mirrors.includes(name) && !mirrorName.includes(name), + ); + + noDataName.forEach((name) => { + nameList.push(name); + }); + } + if (mirrorData?.total) { + mirrorData?.items?.forEach((item: API.Mirror) => { + if (!item.available) { + nameList.push(item.section_name); + } + }); + } + setUnavailableList(nameList); + } + } else { + setComponentLoading(false); + } + } + }, + onError: ({ response, data, type }: any) => { + if (response?.status === 503) { + setTimeout(() => { + fetchAllComponentVersions(); + }, 1000); + } else { + const errorInfo = getErrorInfo({ response, data, type }); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + setComponentLoading(false); + } + }, + }); + + const nameValidator = async (_: any, value: string) => { + if (value) { + if (hasDraft || isDraft) { + return Promise.resolve(); + } + if (!clusterNameReg.test(value)) { + return Promise.reject( + new Error( + intl.formatMessage({ + id: 'OBD.pages.Obdeploy.InstallConfig.ItStartsWithALetter', + defaultMessage: + '以英文字母开头、英文或数字结尾,可包含英文、数字和下划线,且长度为 2 ~ 32', + }), + ), + ); + } + try { + const { success, data } = await getInfoByName({ name: value }); + if (success) { + if (['CONFIGURED', 'DESTROYED'].includes(data?.status)) { + return Promise.resolve(); + } + return Promise.reject( + new Error( + intl.formatMessage( + { + id: 'OBD.pages.components.InstallConfig.ADeploymentNameWithValue', + defaultMessage: '已存在为 {value} 的部署名称,请指定新名称', + }, + { value: value }, + ), + ), + ); + } + return Promise.resolve(); + } catch ({ response, data, type }: any) { + if (response?.status === 404) { + return Promise.resolve(); + } else { + const errorInfo = getErrorInfo({ response, data, type }); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + } + } + } + }; + + const preStep = () => { + if (aliveTokenTimer.current) { + clearTimeout(aliveTokenTimer.current); + aliveTokenTimer.current = null; + } + history.push('guide'); + }; + + const nextStep = () => { + if (form.getFieldsError(['appname'])[0].errors.length) return; + form.validateFields().then((values) => { + const lastAppName = oceanbase?.appname || initAppName; + let newHomePath = home_path; + if (values?.appname !== lastAppName && home_path) { + const firstHalfHomePath = home_path.split(`/${lastAppName}`)[0]; + newHomePath = `${firstHalfHomePath}/${values?.appname}`; + } + let newComponents: API.Components = { + oceanbase: { + ...(components?.oceanbase || {}), + component: + componentsVersionInfo?.[oceanbaseComponent]?.version_type === 'ce' + ? 'oceanbase-ce' + : 'oceanbase', + appname: values?.appname, + version: componentsVersionInfo?.[oceanbaseComponent]?.version, + release: componentsVersionInfo?.[oceanbaseComponent]?.release, + package_hash: componentsVersionInfo?.[oceanbaseComponent]?.md5, + }, + }; + if (selectedConfig.includes('obproxy')) { + newComponents.obproxy = { + ...(components?.obproxy || {}), + component: + componentsVersionInfo?.[obproxyComponent]?.version_type === 'ce' + ? 'obproxy-ce' + : 'obproxy', + version: componentsVersionInfo?.[obproxyComponent]?.version, + release: componentsVersionInfo?.[obproxyComponent]?.release, + package_hash: componentsVersionInfo?.[obproxyComponent]?.md5, + }; + } + if (selectedConfig.includes('obagent')) { + newComponents.obagent = { + ...(components?.obagent || {}), + component: obagentComponent, + version: componentsVersionInfo?.[obagentComponent]?.version, + release: componentsVersionInfo?.[obagentComponent]?.release, + package_hash: componentsVersionInfo?.[obagentComponent]?.md5, + }; + } + if (!lowVersion && selectedConfig.includes('ocp-express')) { + newComponents.ocpexpress = { + ...(components?.ocpexpress || {}), + component: ocpexpressComponent, + version: componentsVersionInfo?.[ocpexpressComponent]?.version, + release: componentsVersionInfo?.[ocpexpressComponent]?.release, + package_hash: componentsVersionInfo?.[ocpexpressComponent]?.md5, + }; + } + + setConfigData({ + ...configData, + components: newComponents, + home_path: newHomePath, + }); + setCurrentStep(2); + setIsFirstTime(false); + setErrorVisible(false); + setErrorsList([]); + window.scrollTo(0, 0); + }); + }; + + const onVersionChange = ( + value: string, + dataSource: API.service_model_components_ComponentInfo[], + ) => { + const md5 = value.split('-')[2]; + setOBVersionValue(value); + const newSelectedVersionInfo = dataSource.filter( + (item) => item.md5 === md5, + )[0]; + + let currentObproxyVersionInfo = {}; + componentsVersionInfo?.[obproxyComponent]?.dataSource?.some( + (item: API.service_model_components_ComponentInfo) => { + if (item?.version_type === newSelectedVersionInfo?.version_type) { + currentObproxyVersionInfo = item; + return true; + } + return false; + }, + ); + setComponentsVersionInfo({ + ...componentsVersionInfo, + [oceanbaseComponent]: { + ...componentsVersionInfo[oceanbaseComponent], + ...newSelectedVersionInfo, + }, + [obproxyComponent]: { + ...componentsVersionInfo[obproxyComponent], + ...currentObproxyVersionInfo, + }, + }); + setLowVersion( + !!( + newSelectedVersionInfo.version && + checkLowVersion(newSelectedVersionInfo.version.split('')[0]) + ), + ); + }; + + const directTo = (url: string) => { + const blankWindow = window.open('about:blank'); + if (blankWindow) { + blankWindow.location.href = url; + } else { + window.location.href = url; + } + }; + + const getColumns = (group: string, supportCheckbox: boolean) => { + const columns: ColumnsType = [ + { + title: group, + dataIndex: 'name', + width: supportCheckbox ? 147 : 195, + render: (text, record) => { + return ( + <> + {text} + {record.key === ocpexpressComponent && lowVersion ? ( + + ) : !componentsVersionInfo[record.key]?.version ? ( + + ) : null} + + ); + }, + }, + { + title: intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.Version', + defaultMessage: '版本', + }), + dataIndex: 'version', + width: locale === 'zh-CN' ? 130 : 154, + render: (_, record) => { + const versionInfo = componentsVersionInfo[record.key] || {}; + if (record?.key === oceanbaseComponent) { + return ( + + ); + } else { + return versionInfo?.version ? ( + <> + {versionInfo?.version} + + {intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.Latest', + defaultMessage: '最新', + })} + + + ) : ( + '-' + ); + } + }, + }, + { + title: intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.Description', + defaultMessage: '描述', + }), + dataIndex: 'desc', + render: (text, record) => { + let disabled = false; + if (record.key === ocpexpressComponent && lowVersion) { + disabled = true; + } + return ( + <> + {text || '-'} + { + if (!disabled) directTo(record.doc); + }} + target="_blank" + > + {intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.LearnMore', + defaultMessage: '了解更多', + })} + + + ); + }, + }, + ]; + + return columns; + }; + + const handleCopy = (content: string) => { + copy(content); + message.success( + intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.CopiedSuccessfully', + defaultMessage: '复制成功', + }), + ); + }; + + /** + * tip:如果选择OCP Express,则OBAgent则自动选择,无需提示 + * 如果不选择 OBAgent, 则 OCP Express 则自动不选择,无需提示 + */ + const handleSelect = (record: rowDataType, selected: boolean) => { + if (!selected) { + let newConfig = [], + target = false; + target = + record.key === 'obagent' && selectedConfig.includes('ocp-express'); + for (let val of selectedConfig) { + if (target && val === 'ocp-express') continue; + if (val !== record.key) { + newConfig.push(val); + } + } + setSelectedConfig(newConfig); + } else { + if (record.key === 'ocp-express' && !selectedConfig.includes('obagent')) { + setSelectedConfig([...selectedConfig, record.key, 'obagent']); + } else { + setSelectedConfig([...selectedConfig, record.key]); + } + } + }; + + const caculateSize = (originSize: number): string => { + return NP.divide(NP.divide(originSize, 1024), 1024).toFixed(2); + }; + + useEffect(() => { + setComponentLoading(true); + if (isFirstTime) { + fetchAllComponentVersions(); + fetchDeploymentInfo({ task_status: 'DRAFT' }).then( + ({ success: draftSuccess, data: draftData }: API.OBResponse) => { + if (draftSuccess && draftData?.items?.length) { + const defaultValue = draftData?.items[0]?.name; + draftNameRef.current = defaultValue; + setHasDraft(true); + Modal.confirm({ + title: intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.TheFollowingHistoricalConfigurationsOf', + defaultMessage: '检测到系统中存在以下部署失败的历史配置', + }), + okText: intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.ContinueDeployment', + defaultMessage: '继续部署', + }), + cancelText: intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.Ignore', + defaultMessage: '忽略', + }), + closable: true, + width: 424, + content: ( + +
    + {intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.ContinuingDeploymentWillCleanUp', + defaultMessage: + '继续部署将先清理失败的历史部署环境,是否继续历史部署流程?', + })} +
    + +
    + ), + + onOk: () => { + return new Promise(async (resolve) => { + try { + const { success: deleteSuccess } = + await handleDeleteDeployment({ + name: draftNameRef.current, + }); + if (deleteSuccess) { + resolve(); + setDeleteName(draftNameRef.current); + setDeleteLoadingVisible(true); + } + } catch { + setIsDraft(false); + resolve(); + } + }); + }, + onCancel: () => { + setIsDraft(false); + setHasDraft(false); + }, + }); + } else { + setIsDraft(false); + } + }, + ); + } else { + fetchAllComponentVersions(); + } + }, []); + + useEffect(() => { + let deployMemory: number = + componentsVersionInfo?.[oceanbaseComponent]?.estimated_size || 0; + let componentsMemory: number = 0; + const keys = Object.keys(componentsVersionInfo); + keys.forEach((key) => { + if (key !== 'oceanbaseComponent' && selectedConfig.includes(key)) { + componentsMemory += componentsVersionInfo[key]?.estimated_size; + } + }); + setDeployMemory(deployMemory); + setComponentsMemory(componentsMemory); + }, [componentsVersionInfo, selectedConfig]); + + useEffect(() => { + form.setFieldsValue({ + appname: configData?.components?.oceanbase?.appname || initAppName, + }); + }, [configData]); + + return ( + + + + + + + + + + {intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.DeployComponents', + defaultMessage: '部署组件', + })} + + + {' '} + {intl.formatMessage( + { + id: 'OBD.pages.components.InstallConfig.EstimatedInstallationRequiresSizeMb', + defaultMessage: '预计安装需要 {size}MB 空间', + }, + { size: caculateSize(deployMemory) }, + )} + + + } + className="card-header-padding-top-0 card-padding-bottom-24 card-padding-top-0" + > + + {existNoVersion ? ( + unavailableList?.length ? ( + + {intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.IfTheCurrentEnvironmentCannot', + defaultMessage: + '如当前环境无法正常访问外网,建议使用 OceanBase 离线安装包进行安装部署。', + })} + + {intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.GoToDownloadOfflineInstallation', + defaultMessage: '前往下载离线安装', + })} + + + } + type="error" + showIcon + style={{ marginTop: '16px' }} + /> + ) : ( + + {intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.IfTheCurrentEnvironmentHas', + defaultMessage: + '如当前环境可正常访问外网,可启动 OceanBase 在线镜像仓库,或联系您的镜像仓库管理员。', + })} + + {intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.RunTheCommandOnThe', + defaultMessage: + '请在主机上执行一下命令启用在线镜像仓库', + })} +
    obd mirror enable + oceanbase.community.stable + oceanbase.development-kit + + + handleCopy( + 'obd mirror enable oceanbase.community.stable oceanbase.development-kit', + ) + } + /> + + + } + > + + {intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.HowToEnableOnlineImage', + defaultMessage: '如何启用在线镜像仓库', + })} + +
    + + } + type="error" + showIcon + style={{ marginTop: '16px' }} + /> + ) + ) : null} + +
    { + if (record.key === ocpexpressComponent && lowVersion) { + return styles.disabledRow; + } + }} + /> + + + + + {intl.formatMessage({ + id: 'OBD.pages.components.InstallConfig.OptionalComponents', + defaultMessage: '可选组件', + })} + + + {' '} + {intl.formatMessage( + { + id: 'OBD.pages.components.InstallConfig.EstimatedInstallationRequiresSizeMb', + defaultMessage: '预计部署需要 {size}MB 空间', + }, + { size: caculateSize(componentsMemory) }, + )} + + + } + className="card-header-padding-top-0 card-padding-bottom-24 card-padding-top-0" + > + {componentsGroupInfo.map((componentInfo) => ( + + +
    { + if (record.key === ocpexpressComponent && lowVersion) { + return styles.disabledRow; + } + }} + /> + + + ))} + + +
    +
    + + + + + +
    +
    + {deleteLoadingVisible && ( + setDeleteLoadingVisible(false)} + setOBVersionValue={setOBVersionValue} + /> + )} + + + ); +} diff --git a/web/src/pages/Obdeploy/InstallFinished.tsx b/web/src/pages/Obdeploy/InstallFinished.tsx new file mode 100644 index 0000000..97e6cd0 --- /dev/null +++ b/web/src/pages/Obdeploy/InstallFinished.tsx @@ -0,0 +1,584 @@ +import { intl } from '@/utils/intl'; +import { useEffect, useState } from 'react'; +import { useModel } from 'umi'; +import { + Space, + Button, + Table, + Alert, + Result, + Tooltip, + message, + Tag, + Modal, + Typography, + Spin, +} from 'antd'; +import { + CloseCircleFilled, + CheckCircleFilled, + CaretRightFilled, + CaretDownFilled, + CopyOutlined, + ExclamationCircleOutlined, + CheckOutlined, +} from '@ant-design/icons'; +import { ProCard } from '@ant-design/pro-components'; +import useRequest from '@/utils/useRequest'; +import type { ColumnsType } from 'antd/es/table'; +import copy from 'copy-to-clipboard'; +import { + queryDeploymentReport, + queryConnectionInfo, + queryInstallLog, +} from '@/services/ob-deploy-web/Deployments'; +import { + componentsConfig, + componentVersionTypeToComponent, +} from '../constants'; +import { handleQuit, getErrorInfo } from '@/utils'; +import { getLocale } from 'umi'; +import EnStyles from './indexEn.less'; +import ZhStyles from './indexZh.less'; + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; + +const { Paragraph } = Typography; + +export default function InstallProcess() { + const { + configData, + installStatus, + setCurrentStep, + handleQuitProgress, + setErrorVisible, + setErrorsList, + errorsList, + } = useModel('global'); + const [logs, setLogs] = useState({}); + const [currentExpeandedName, setCurrentExpeandedName] = useState(''); + + const name = configData?.components?.oceanbase?.appname; + const { run: fetchReportInfo, data: reportInfo } = useRequest( + queryDeploymentReport, + { + onError: (e: any) => { + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }, + ); + const { run: fetchConnectInfo, data: connectInfo } = useRequest( + queryConnectionInfo, + { + onError: (e: any) => { + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }, + ); + + const { run: handleInstallLog, loading } = useRequest(queryInstallLog, { + onSuccess: ( + { success, data }: API.OBResponseInstallLog_, + [{ component_name }]: [API.queryInstallLogParams], + ) => { + if (success) { + setLogs({ ...logs, [component_name]: data?.log }); + setTimeout(() => { + const log = document.getElementById(`report-log-${component_name}`); + if (log) { + log.scrollTop = log.scrollHeight; + } + }); + } + }, + onError: (e: any) => { + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }); + + const handleCopy = (content: string) => { + copy(content); + message.success( + intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.CopiedSuccessfully', + defaultMessage: '复制成功', + }), + ); + }; + + const handleCopyCommand = (command: string) => { + copy(command); + message.success( + intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.CopiedSuccessfully', + defaultMessage: '复制成功', + }), + ); + }; + + useEffect(() => { + fetchReportInfo({ name }); + fetchConnectInfo({ name }); + }, []); + + const connectColumns: ColumnsType = [ + { + title: intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.Component', + defaultMessage: '组件', + }), + dataIndex: 'component', + width: 200, + render: (text) => { + const component = componentVersionTypeToComponent[text] + ? componentVersionTypeToComponent[text] + : text; + return componentsConfig[component]?.showComponentName || '-'; + }, + }, + { + title: intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.AccessAddress', + defaultMessage: '访问地址', + }), + dataIndex: 'access_url', + width: 160, + render: (text) => text || '-', + }, + { + title: intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.Account', + defaultMessage: '账号', + }), + dataIndex: 'user', + render: (text) => text || '-', + }, + { + title: intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.Password', + defaultMessage: '密码', + }), + dataIndex: 'password', + width: 160, + render: (text) => + text ? ( + +
    {text}
    +
    + ) : ( + '-' + ), + }, + { + title: intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.ConnectionString', + defaultMessage: '连接串', + }), + dataIndex: 'connect_url', + width: 300, + render: (text, record) => { + let content; + if (/^http/g.test(text)) { + content = ( + + {text} + + ); + } else { + content = ( +
    + {text} +
    + ); + } + return ( +
    + +
    + {content} +
    +
    + + handleCopy(text)} /> + +
    + ); + }, + }, + ]; + + const reportColumns: ColumnsType = [ + { + title: intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.ComponentName', + defaultMessage: '组件名称', + }), + dataIndex: 'name', + render: (text) => { + const component = componentVersionTypeToComponent[text] + ? componentVersionTypeToComponent[text] + : text; + return componentsConfig[component]?.showComponentName || '-'; + }, + }, + { + title: intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.ComponentType', + defaultMessage: '组件类型', + }), + dataIndex: 'type', + render: (_, record) => { + const component = componentVersionTypeToComponent[record.name] + ? componentVersionTypeToComponent[record.name] + : record.name; + return componentsConfig[component]?.type || '-'; + }, + }, + { + title: intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.Version', + defaultMessage: '版本', + }), + dataIndex: 'version', + render: (text) => text || '-', + }, + { + title: intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.InstallationResults', + defaultMessage: '安装结果', + }), + dataIndex: 'status', + width: locale === 'zh-CN' ? 200 : 260, + render: (text, record) => { + const statusIcon = + text === 'SUCCESSFUL' ? ( + + ) : ( + + ); + + const status = + text === 'SUCCESSFUL' + ? intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.Success', + defaultMessage: '成功', + }) + : intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.Failed', + defaultMessage: '失败', + }); + + const getCommand = (component: string, ip: string) => { + return `obd tool command ${name} log -c ${component} -s ${ip}`; + }; + + const serversInfo = record.servers?.map((server) => ({ + server, + command: getCommand(record.name, server), + })); + + return ( + <> + {statusIcon} + {status} + +
    + {intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.GoToTheObdConsole', + defaultMessage: '请前往 OBD 中控机执行以下命令查看日志', + })} +
    + {serversInfo.map((item) => ( + <> +
    + {statusIcon} + {item.server} +
    + + + ))} + + } + placement="topRight" + overlayClassName={styles.reportTooltip} + > + + {intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.ViewDetails', + defaultMessage: '查看详情', + })} + +
    + + ); + }, + }, + ]; + + const onExpand = (expeanded: boolean, record: API.DeploymentReport) => { + if (expeanded && !logs?.[record.name]) { + setCurrentExpeandedName(record.name); + handleInstallLog({ name, component_name: record.name }); + } + }; + + const expandedRowRender = (record: API.DeploymentReport) => { + return ( + +
    +          {logs?.[record.name]}
    +        
    +
    + ); + }; + + const handleFinished = () => { + Modal.confirm({ + title: intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.DoYouWantToExit', + defaultMessage: '是否要退出页面?', + }), + okText: intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.Exit', + defaultMessage: '退出', + }), + cancelText: intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.Cancel', + defaultMessage: '取消', + }), + okButtonProps: { type: 'primary', danger: true }, + content: ( +
    + {intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.BeforeExitingMakeSureThat', + defaultMessage: '退出前,请确保已复制访问地址及账密信息', + })} + +
    + + + {intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.CopyInformation', + defaultMessage: '复制信息', + })} + , + <> + + {intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.CopyInformation', + defaultMessage: '复制信息', + })} + , + ], + onCopy: () => + handleCopy(JSON.stringify(connectInfo?.items, null, '\n')), + }} + /> +
    + ), + + icon: , + onOk: () => { + handleQuit(handleQuitProgress, setCurrentStep, true); + }, + }); + }; + + return ( + + + } + title={ + installStatus === 'SUCCESSFUL' ? ( +
    + {intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.OceanbaseSuccessfullyDeployed', + defaultMessage: 'OceanBase 部署成功', + })} +
    + ) : ( +
    + {intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.OceanbaseDeploymentFailed', + defaultMessage: 'OceanBase 部署失败', + })} +
    + ) + } + /> + + {connectInfo?.items?.length ? ( + + + handleCopy(JSON.stringify(connectInfo?.items, null, '\n')) + } + data-aspm-click="c307514.d317299" + data-aspm-desc={intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.DeploymentResultCopyInformation', + defaultMessage: '部署结果-复制信息', + })} + data-aspm-param={``} + data-aspm-expo + > + {intl.formatMessage({ + id: 'OBD.pages.components.InstallFinished.OneClickCopy', + defaultMessage: '一键复制', + })} + + } + /> + +
    + + ) : null} + + collapsed ? : + } + bodyStyle={{ paddingLeft: '0px', paddingRight: '0px' }} + > +
    + +
    +
    + + + +
    +
    + + ); +} diff --git a/web/src/pages/Obdeploy/InstallProcess.tsx b/web/src/pages/Obdeploy/InstallProcess.tsx new file mode 100644 index 0000000..910340c --- /dev/null +++ b/web/src/pages/Obdeploy/InstallProcess.tsx @@ -0,0 +1,312 @@ +import { intl } from '@/utils/intl'; +import { useEffect, useState } from 'react'; +import { useModel } from 'umi'; +import { ProCard } from '@ant-design/pro-components'; +import useRequest from '@/utils/useRequest'; +import { + queryInstallStatus, + queryInstallLog, +} from '@/services/ob-deploy-web/Deployments'; +import { getErrorInfo } from '@/utils'; +import lottie from 'lottie-web'; +import NP from 'number-precision'; +import videojs from 'video.js'; +import 'video.js/dist/video-js.css'; +import { getLocale } from 'umi'; +import EnStyles from './indexEn.less'; +import ZhStyles from './indexZh.less'; + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; + +let timerLogScroll: NodeJS.Timer; +let timerProgress: NodeJS.Timer; + +export default function InstallProcess() { + const { + setCurrentStep, + configData, + installStatus, + setInstallStatus, + setErrorVisible, + setErrorsList, + errorsList, + } = useModel('global'); + const name = configData?.components?.oceanbase?.appname; + const progressCoverInitWidth = 282; + const [toBottom, setToBottom] = useState(true); + const [progress, setProgress] = useState(0); + const [showProgress, setShowProgress] = useState(0); + const [progressCoverStyle, setProgreddCoverStyle] = useState({ + width: progressCoverInitWidth, + background: '#fff', + borderRadius: '5px', + }); + const [currentPage, setCurrentPage] = useState(true); + const [statusData, setStatusData] = useState({}); + const [logData, setLogData] = useState({}); + let Video: any; + + const { run: fetchInstallStatus } = useRequest(queryInstallStatus, { + onSuccess: ({ success, data }: API.OBResponseTaskInfo_) => { + if (success) { + setStatusData(data || {}); + clearInterval(timerProgress); + if (data?.status !== 'RUNNING') { + setInstallStatus(data?.status); + setCurrentPage(false); + setTimeout(() => { + setCurrentStep(6); + setErrorVisible(false); + setErrorsList([]); + }, 2000); + } else { + setTimeout(() => { + fetchInstallStatus({ name }); + }, 1000); + } + const newProgress = NP.divide(data?.finished, data?.total).toFixed(2); + setProgress(newProgress); + let step = NP.minus(newProgress, progress); + let stepNum = 1; + timerProgress = setInterval(() => { + const currentProgressNumber = NP.plus( + progress, + NP.times(NP.divide(step, 100), stepNum), + ); + + if (currentProgressNumber >= 1) { + clearInterval(timerProgress); + } else { + stepNum += 1; + setShowProgress(currentProgressNumber); + } + }, 10); + } + }, + onError: (e: any) => { + if (currentPage) { + setTimeout(() => { + fetchInstallStatus({ name }); + }, 1000); + } + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }); + + const { run: handleInstallLog } = useRequest(queryInstallLog, { + onSuccess: ({ success, data }: API.OBResponseInstallLog_) => { + if (success && installStatus === 'RUNNING') { + setLogData(data || {}); + setTimeout(() => { + handleInstallLog({ name }); + }, 1000); + } + }, + onError: (e: any) => { + if (installStatus === 'RUNNING' && currentPage) { + setTimeout(() => { + handleInstallLog({ name }); + }, 1000); + } + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }); + + const toLogBottom = () => { + const log = document.getElementById('installLog'); + if (log) { + log.scrollTop = log.scrollHeight; + } + }; + + const handleScroll = (e?: any) => { + e = e || window.event; + const dom = e.target; + if (dom.scrollTop + dom.clientHeight === dom.scrollHeight) { + setToBottom(true); + } else { + setToBottom(false); + } + }; + + const getAnimate = () => { + const computerAnimate = document.querySelector('.computer-animate'); + const progressAnimate = document.querySelector('.progress-animate'); + const spacemanAnimate = document.querySelector('.spaceman-animate'); + const sqlAnimate = document.querySelector('.database-animate'); + + if (progressAnimate) { + Video = videojs(progressAnimate, { + controls: false, + autoplay: true, + loop: true, + preload: 'auto', + }); + } + + lottie.loadAnimation({ + prefetch: true, + container: computerAnimate, + renderer: 'svg', + loop: true, + autoplay: true, + path: '/assets/computer/data.json', + }); + + lottie.loadAnimation({ + prefetch: true, + container: spacemanAnimate, + renderer: 'svg', + loop: true, + autoplay: true, + path: '/assets/spaceman/data.json', + }); + + lottie.loadAnimation({ + prefetch: true, + container: sqlAnimate, + renderer: 'svg', + loop: true, + autoplay: true, + path: '/assets/database/data.json', + }); + }; + + useEffect(() => { + if (name) { + fetchInstallStatus({ name }); + handleInstallLog({ name }); + } + }, [name]); + + useEffect(() => { + getAnimate(); + const log = document.querySelector('#installLog'); + log.addEventListener('scroll', handleScroll); + return () => { + log.removeEventListener('DOMMouseScroll', handleScroll); + clearInterval(timerLogScroll); + clearInterval(timerProgress); + Video.dispose(); + }; + }, []); + + useEffect(() => { + if (toBottom) { + toLogBottom(); + timerLogScroll = setInterval(() => toLogBottom()); + } else { + clearInterval(timerLogScroll); + } + }, [toBottom]); + + useEffect(() => { + let newCoverStyle: any = { ...progressCoverStyle }; + const newCoverWidth = NP.times( + NP.minus(1, showProgress), + progressCoverInitWidth, + ); + + if (showProgress > 0) { + newCoverStyle = { + width: `${newCoverWidth}px`, + background: + 'linear-gradient( to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 10px, rgba(255, 255, 255, 1) )', + }; + } + setProgreddCoverStyle(newCoverStyle); + }, [showProgress]); + + const getText = (name?: string) => { + return intl.formatMessage( + { + id: 'OBD.pages.components.InstallProcess.DeployingName', + defaultMessage: '正在部署 {name}', + }, + { name: name }, + ); + }; + + return ( + + +
    +
    + {intl.formatMessage({ + id: 'OBD.pages.components.InstallProcess.Deploying', + defaultMessage: '部署中...', + })} +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + {getText(statusData?.current)} + +
    + +
    +          {logData?.log}
    +          {installStatus === 'RUNNING' ? (
    +            
    +
    +
    +
    +
    +
    + ) : null} +
    +
    +
    + ); +} diff --git a/web/src/pages/Obdeploy/NodeConfig.tsx b/web/src/pages/Obdeploy/NodeConfig.tsx new file mode 100644 index 0000000..29e3ecc --- /dev/null +++ b/web/src/pages/Obdeploy/NodeConfig.tsx @@ -0,0 +1,1109 @@ +import { intl } from '@/utils/intl'; +import { useEffect, useState, useRef } from 'react'; +import { useModel } from 'umi'; +import { + Space, + Button, + Tooltip, + Select, + Popconfirm, + message, + Form, +} from 'antd'; +import { QuestionCircleOutlined, DeleteOutlined } from '@ant-design/icons'; +import { + ProCard, + ProForm, + ProFormText, + ProFormSelect, + ProFormDigit, + EditableProTable, +} from '@ant-design/pro-components'; +import type { + ProColumns, + EditableFormInstance, +} from '@ant-design/pro-components'; +import { getObdInfo } from '@/services/ob-deploy-web/Info'; +import useRequest from '@/utils/useRequest'; +import { handleQuit, getErrorInfo } from '@/utils'; +import { commonStyle, pathRule } from '../constants'; +import ServerTags from './ServerTags'; +import TooltipInput from './TooltipInput'; +import { getLocale } from 'umi'; +import EnStyles from './indexEn.less'; +import ZhStyles from './indexZh.less'; + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; + +interface FormValues extends API.Components { + auth?: { + user?: string; + password?: string; + port?: number; + }; + home_path?: string; +} + +export default function NodeConfig() { + const { + selectedConfig, + setCurrentStep, + configData, + setConfigData, + lowVersion, + handleQuitProgress, + nameIndex, + setNameIndex, + setErrorVisible, + setErrorsList, + errorsList, + } = useModel('global'); + const { components = {}, auth, home_path } = configData || {}; + const { oceanbase = {}, ocpexpress = {}, obproxy = {} } = components; + const [form] = ProForm.useForm(); + const [editableForm] = ProForm.useForm(); + const tableFormRef = useRef>(); + + const initDBConfigData = oceanbase?.topology?.length + ? oceanbase?.topology?.map((item: API.Zone, index: number) => ({ + id: (Date.now() + index).toString(), + ...item, + servers: item?.servers?.map((server) => server?.ip), + })) + : [ + { + id: (Date.now() + 1).toString(), + name: 'zone1', + servers: [], + rootservice: undefined, + }, + { + id: (Date.now() + 2).toString(), + name: 'zone2', + servers: [], + rootservice: undefined, + }, + { + id: (Date.now() + 3).toString(), + name: 'zone3', + servers: [], + rootservice: undefined, + }, + ]; + + const homePathSuffix = `/${oceanbase.appname}`; + + const initHomePath = home_path + ? home_path.substring(0, home_path.length - homePathSuffix.length) + : undefined; + + const [dbConfigData, setDBConfigData] = + useState(initDBConfigData); + const [editableKeys, setEditableRowKeys] = useState(() => + dbConfigData.map((item) => item.id), + ); + + // all servers + const [allOBServer, setAllOBServer] = useState([]); + // all zone servers + const [allZoneOBServer, setAllZoneOBServer] = useState({}); + const [lastDeleteServer, setLastDeleteServer] = useState(''); + const [ocpServerDropdownVisible, setOcpServerDropdownVisible] = + useState(false); + + const serverReg = + /^((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])?$/; + + const { run: getUserInfo } = useRequest(getObdInfo, { + onSuccess: ({ success, data }: API.OBResponseServiceInfo_) => { + if (success) { + form.setFieldsValue({ + auth: { + user: data?.user || undefined, + }, + home_path: data?.user === 'root' ? '/root' : `/home/${data?.user}`, + }); + } + }, + onError: (e: any) => { + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }); + + const handleDelete = (id: string) => { + setDBConfigData(dbConfigData.filter((item) => item.id !== id)); + }; + + const setData = (dataSource: FormValues) => { + let newComponents: API.Components = {}; + if (selectedConfig.includes('obproxy')) { + newComponents.obproxy = { + ...(components.obproxy || {}), + ...dataSource.obproxy, + }; + } + if (selectedConfig.includes('ocp-express') && !lowVersion) { + newComponents.ocpexpress = { + ...(components.ocpexpress || {}), + ...dataSource?.ocpexpress, + }; + } + if (selectedConfig.includes('obagent')) { + newComponents.obagent = { + ...(components.obagent || {}), + servers: allOBServer, + }; + } + newComponents.oceanbase = { + ...(components.oceanbase || {}), + topology: dbConfigData?.map((item) => ({ + ...item, + servers: item?.servers?.map((server) => ({ ip: server })), + })), + }; + setConfigData({ + ...configData, + components: newComponents, + auth: dataSource.auth, + home_path: `${ + dataSource.home_path + ? `${dataSource.home_path}${homePathSuffix}` + : undefined + }`, + }); + }; + + const prevStep = () => { + const formValues = form.getFieldsValue(true); + setData(formValues); + setCurrentStep(1); + setErrorVisible(false); + setErrorsList([]); + window.scrollTo(0, 0); + }; + + const nextStep = () => { + const tableFormRefValidate = () => { + return tableFormRef?.current?.validateFields().then((values) => { + return values; + }); + }; + + const formValidate = () => { + return form.validateFields().then((values) => { + return values; + }); + }; + + Promise.all([tableFormRefValidate(), formValidate()]).then((result) => { + const formValues = result?.[1]; + setData(formValues); + setCurrentStep(3); + setErrorVisible(false); + setErrorsList([]); + window.scrollTo(0, 0); + }); + }; + + const formatOptions = (data: string[]) => + data?.map((item) => ({ label: item, value: item })); + + const getAllServers = (dataSource: API.DBConfig[]) => { + const allServersList = dataSource.map((item) => item.servers); + let newAllOBServer: string[] = []; + allServersList.forEach((item) => { + if (item && item.length) { + newAllOBServer = [...newAllOBServer, ...item]; + } + }); + return newAllOBServer; + }; + + const onValuesChange = (values: FormValues) => { + if (values?.auth?.user) { + form.setFieldsValue({ + home_path: + values?.auth?.user === 'root' + ? '/root' + : `/home/${values?.auth?.user}`, + }); + } + }; + + useEffect(() => { + const allServers = getAllServers(dbConfigData); + const allZoneServers: any = {}; + dbConfigData.forEach((item) => { + allZoneServers[`${item.id}`] = item.servers; + }); + const obproxyServers = form.getFieldValue(['obproxy', 'servers']); + const ocpexpressServers = form.getFieldValue(['ocpexpress', 'servers']); + const customOBproxyServers = obproxyServers?.filter( + (item: string) => + !(allServers?.includes(item) || item === lastDeleteServer), + ); + + const customOcpexpressServers = ocpexpressServers?.filter( + (item: string) => + !(allServers?.includes(item) || item === lastDeleteServer), + ); + + let obproxyServersValue; + let ocpexpressServersValue; + if (allServers?.length) { + const checkPass = serverReg.test(allServers[0]); + if (!obproxyServers?.length) { + obproxyServersValue = [allServers[0]]; + } else { + const newOBproxyServers: string[] = []; + obproxyServers?.forEach((item: string) => { + if (allServers?.includes(item)) { + newOBproxyServers.push(item); + } + }); + if (newOBproxyServers?.length) { + obproxyServersValue = [...customOBproxyServers, ...newOBproxyServers]; + } else if (customOBproxyServers?.length) { + obproxyServersValue = customOBproxyServers; + } else { + obproxyServersValue = [allServers[0]]; + if (!checkPass) { + form.setFields([ + { + name: ['obproxy', 'servers'], + errors: [ + intl.formatMessage({ + id: 'OBD.pages.components.NodeConfig.SelectTheCorrectObproxyNode', + defaultMessage: '请选择正确的 OBProxy 节点', + }), + ], + }, + ]); + } + } + } + + if (!ocpexpressServers?.length) { + ocpexpressServersValue = [allServers[0]]; + } else { + const newOcpexpressServers: string[] = []; + ocpexpressServers?.forEach((item: string) => { + if (allServers?.includes(item)) { + newOcpexpressServers.push(item); + } + }); + if (newOcpexpressServers?.length) { + ocpexpressServersValue = [ + ...customOcpexpressServers, + ...newOcpexpressServers, + ]; + } else if (customOcpexpressServers?.length) { + ocpexpressServersValue = customOcpexpressServers; + } else { + ocpexpressServersValue = [allServers[0]]; + if (!checkPass) { + form.setFields([ + { + name: ['ocpexpress', 'servers'], + errors: [ + intl.formatMessage({ + id: 'OBD.pages.components.NodeConfig.SelectTheCorrectOcpExpress', + defaultMessage: '请选择正确的 OCP Express 节点', + }), + ], + }, + ]); + } + } + } + } else { + if (!customOBproxyServers?.length) { + obproxyServersValue = undefined; + } else { + obproxyServersValue = customOBproxyServers; + } + if (!customOcpexpressServers?.length) { + ocpexpressServersValue = undefined; + } else { + ocpexpressServersValue = customOcpexpressServers; + } + } + + form.setFieldsValue({ + obproxy: { + servers: obproxyServersValue, + }, + ocpexpress: { + servers: ocpexpressServersValue, + }, + }); + + setAllOBServer(allServers); + setAllZoneOBServer(allZoneServers); + }, [dbConfigData, lastDeleteServer]); + + useEffect(() => { + if (!auth?.user) { + getUserInfo(); + } + }, []); + + const nameValidator = ({ field }: any, value: string) => { + const currentId = field.split('.')[0]; + let validtor = true; + const reg = /^[a-zA-Z]([a-zA-Z0-9_]{0,30})[a-zA-Z0-9]$/; + if (value) { + if (reg.test(value)) { + dbConfigData.some((item) => { + if (currentId !== item.id && item.name === value) { + validtor = false; + return true; + } + return false; + }); + } else { + return Promise.reject( + new Error( + intl.formatMessage({ + id: 'OBD.pages.components.NodeConfig.ItStartsWithALetter', + defaultMessage: + '以英文字母开头,英文或数字结尾,可包含英文数字和下划线且长度在 2-32 个字符之间', + }), + ), + ); + } + } + if (validtor) { + return Promise.resolve(); + } + return Promise.reject( + new Error( + intl.formatMessage({ + id: 'OBD.pages.components.NodeConfig.ZoneNameAlreadyOccupied', + defaultMessage: 'Zone 名称已被占用', + }), + ), + ); + }; + + const ocpServersValidator = (_: any, value: string[]) => { + let validtor = true; + if (value?.length > 1) { + return Promise.reject( + new Error( + intl.formatMessage({ + id: 'OBD.pages.components.NodeConfig.OnlyOneNodeCanBe', + defaultMessage: '仅可选择或输入一个节点', + }), + ), + ); + } + if (value && value.length) { + value.some((item) => { + validtor = serverReg.test(item.trim()); + return !serverReg.test(item.trim()); + }); + } + if (validtor) { + return Promise.resolve(); + } + return Promise.reject( + new Error( + intl.formatMessage({ + id: 'OBD.pages.components.NodeConfig.SelectTheCorrectOcpExpress', + defaultMessage: '请选择正确的 OCP Express 节点', + }), + ), + ); + }; + + const serversValidator = (_: any, value: string[], type: string) => { + let validtor = true; + if (value && value.length) { + value.some((item) => { + validtor = serverReg.test(item.trim()); + return !serverReg.test(item.trim()); + }); + } + if (validtor) { + return Promise.resolve(); + } + if (type === 'OBServer') { + return Promise.reject( + new Error( + intl.formatMessage({ + id: 'OBD.pages.components.NodeConfig.EnterTheCorrectIpAddress', + defaultMessage: '请输入正确的 IP 地址', + }), + ), + ); + } else { + return Promise.reject( + new Error( + intl.formatMessage({ + id: 'OBD.pages.components.NodeConfig.SelectTheCorrectObproxyNode', + defaultMessage: '请选择正确的 OBProxy 节点', + }), + ), + ); + } + }; + + const columns: ProColumns[] = [ + { + title: ( + <> + {intl.formatMessage({ + id: 'OBD.pages.components.NodeConfig.ZoneName', + defaultMessage: 'Zone 名称', + })} + + + + + + ), + + dataIndex: 'name', + width: 224, + formItemProps: { + rules: [ + { + required: true, + whitespace: false, + message: intl.formatMessage({ + id: 'OBD.pages.components.NodeConfig.ThisItemIsRequired', + defaultMessage: '此项是必填项', + }), + }, + { validator: nameValidator }, + ], + }, + }, + { + title: ( + <> + {intl.formatMessage({ + id: 'OBD.pages.components.NodeConfig.ObserverNodes', + defaultMessage: 'OBServer 节点', + })} + + + + + + ), + + dataIndex: 'servers', + formItemProps: { + rules: [ + { + required: true, + message: intl.formatMessage({ + id: 'OBD.pages.components.NodeConfig.ThisItemIsRequired', + defaultMessage: '此项是必填项', + }), + }, + { + validator: (_: any, value: string[]) => + serversValidator(_, value, 'OBServer'), + }, + ], + }, + renderFormItem: (_: any, { isEditable, record }: any) => { + return isEditable ? ( + + ) : null; + }, + }, + { + title: ( + <> + {intl.formatMessage({ + id: 'OBD.pages.components.NodeConfig.RootserverNodes', + defaultMessage: 'RootServer 节点', + })} + + + + + + ), + + dataIndex: 'rootservice', + formItemProps: { + rules: [ + { + required: true, + message: intl.formatMessage({ + id: 'OBD.pages.components.NodeConfig.ThisOptionIsRequired', + defaultMessage: '此项是必选项', + }), + }, + { + pattern: serverReg, + message: intl.formatMessage({ + id: 'OBD.pages.components.NodeConfig.SelectTheCorrectRootserverNode', + defaultMessage: '请选择正确的 RootServer 节点', + }), + }, + ], + }, + width: 224, + renderFormItem: (_: any, { isEditable, record }: any) => { + // rootservice options are items entered by the OBServer + const options = record?.servers ? formatOptions(record?.servers) : []; + return isEditable ? ( + setVisible(false)} + onFocus={() => setVisible(false)} + onBlur={() => setVisible(false)} + onDeselect={(value) => setLastDeleteServer(value)} + /> + + ); +}; diff --git a/web/src/pages/Obdeploy/Steps.tsx b/web/src/pages/Obdeploy/Steps.tsx new file mode 100644 index 0000000..32f302a --- /dev/null +++ b/web/src/pages/Obdeploy/Steps.tsx @@ -0,0 +1,121 @@ +import { intl } from '@/utils/intl'; +import { useModel } from 'umi'; +import { Space } from 'antd'; +import { ClockCircleOutlined, CheckCircleOutlined } from '@ant-design/icons'; +import { getLocale } from 'umi'; +import EnStyles from './indexEn.less'; +import ZhStyles from './indexZh.less'; + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; +import { useEffect, useState } from 'react'; + +export default function Steps() { + const { currentStep } = useModel('global'); + const [showBorder, setShowBorder] = useState(false); + + const getIcon = (key: number) => { + return currentStep > key ? ( + + ) : ( + + ); + }; + + const getStepsItems = () => { + return [ + { + title: intl.formatMessage({ + id: 'OBD.pages.components.Steps.DeploymentConfiguration', + defaultMessage: '部署配置', + }), + key: 1, + icon: getIcon(1), + }, + { + title: intl.formatMessage({ + id: 'OBD.pages.components.Steps.NodeConfiguration', + defaultMessage: '节点配置', + }), + key: 2, + icon: getIcon(2), + }, + { + title: intl.formatMessage({ + id: 'OBD.pages.components.Steps.ClusterConfiguration', + defaultMessage: '集群配置', + }), + key: 3, + icon: getIcon(3), + }, + { + title: intl.formatMessage({ + id: 'OBD.pages.components.Steps.PreCheck', + defaultMessage: '预检查', + }), + key: 4, + icon: getIcon(4), + }, + { + title: intl.formatMessage({ + id: 'OBD.pages.components.Steps.Deployment', + defaultMessage: '部署', + }), + key: 5, + icon: getIcon(5), + }, + ]; + }; + + const showStepsKeys = [1, 2, 3, 4, 5]; + + const handleScroll = () => { + if (document.documentElement.scrollTop > 0) { + setShowBorder(true); + } else { + setShowBorder(false); + } + }; + + useEffect(() => { + document.addEventListener('scroll', handleScroll); + }, []); + + return ( +
    + {showStepsKeys.includes(currentStep) ? ( +
    +
    +
    +
    +
    + + {getStepsItems().map((item) => ( + + {item.icon} + item.key ? styles.stepAlreadyTitle : ''}`} + > + {item.title} + + + ))} + +
    +
    + ) : null} +
    + ); +} diff --git a/web/src/pages/Obdeploy/TooltipInput.tsx b/web/src/pages/Obdeploy/TooltipInput.tsx new file mode 100644 index 0000000..5db16b2 --- /dev/null +++ b/web/src/pages/Obdeploy/TooltipInput.tsx @@ -0,0 +1,142 @@ +import { useEffect, useState, useRef } from 'react'; +import { Input, Tooltip } from 'antd'; + +interface Props { + value?: string; + onChange?: (value?: string) => void; + placeholder: string; + name: string; + isPassword: boolean; + fieldProps: any; +} + +export default ({ + value, + onChange, + placeholder, + name, + isPassword, + fieldProps, +}: Props) => { + const [visible, setVisible] = useState(false); + const [currentValue, setCurrentValue] = useState(value); + const open = useRef(); + open.current = { + input: false, + tooltip: false, + }; + + const onMouseEnterInput = () => { + open.current = { + ...(open?.current || {}), + input: true, + }; + setVisible(true); + }; + + const onMouseEnterTooltip = () => { + open.current = { + ...(open?.current || {}), + tooltip: true, + }; + setVisible(true); + }; + + const onMouseLeaveInput = () => { + setTimeout(() => { + if (!open?.current?.tooltip) { + setVisible(false); + } + }, 300); + }; + + const onMouseLeaveTooltip = () => { + setVisible(false); + }; + + const addEventTooltipOverlay = () => { + const tooltipOverlay = document.querySelector( + `.tooltip-input-tooltip-overlay-${name}`, + ); + if (tooltipOverlay) { + tooltipOverlay?.addEventListener('mouseenter', onMouseEnterTooltip); + tooltipOverlay?.addEventListener('mouseleave', onMouseLeaveTooltip); + } else { + setTimeout(() => { + addEventTooltipOverlay(); + }, 500); + } + }; + + const addEventInputConatiner = () => { + const inputConatiner = document.querySelector(`.tooltip-input-${name}`); + if (inputConatiner) { + inputConatiner?.addEventListener('mouseenter', onMouseEnterInput); + inputConatiner?.addEventListener('mouseleave', onMouseLeaveInput); + } else { + setTimeout(() => { + addEventInputConatiner(); + }, 500); + } + }; + + useEffect(() => { + const tooltipOverlay = document.querySelector( + `.tooltip-input-tooltip-overlay-${name}`, + ); + const inputConatiner = document.querySelector(`.tooltip-input-${name}`); + addEventTooltipOverlay(); + addEventInputConatiner(); + return () => { + tooltipOverlay?.removeEventListener('mouseenter', onMouseEnterTooltip); + tooltipOverlay?.removeEventListener('mouseleave', onMouseLeaveTooltip); + inputConatiner?.removeEventListener('mouseenter', onMouseEnterInput); + inputConatiner?.removeEventListener('mouseleave', onMouseLeaveInput); + }; + }, []); + + useEffect(() => { + if (onChange) { + onChange(currentValue); + } + }, [currentValue]); + + return ( + 48 && visible} + title={placeholder} + overlayClassName={`tooltip-input-tooltip-overlay-${name}`} + > + {isPassword ? ( + { + setCurrentValue(e?.target?.value); + setVisible(false); + }} + style={{ width: 448 }} + onFocus={() => setVisible(false)} + {...fieldProps} + /> + ) : ( + { + setCurrentValue(e?.target?.value); + setVisible(false); + }} + autoComplete="off" + style={{ width: 448 }} + onFocus={() => setVisible(false)} + {...fieldProps} + /> + )} + + ); +}; diff --git a/web/src/pages/Obdeploy/Welcome.tsx b/web/src/pages/Obdeploy/Welcome.tsx new file mode 100644 index 0000000..a7b9ef4 --- /dev/null +++ b/web/src/pages/Obdeploy/Welcome.tsx @@ -0,0 +1,111 @@ +import { intl } from '@/utils/intl'; +import { useEffect } from 'react'; +import { useModel } from 'umi'; +import { Button } from 'antd'; +import videojs from 'video.js'; +import 'video.js/dist/video-js.css'; +import NP from 'number-precision'; +import { getLocale } from 'umi'; +import EnStyles from './indexEn.less'; +import ZhStyles from './indexZh.less'; + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; + +export default function Welcome() { + const { setCurrentStep, setErrorVisible, setErrorsList } = useModel('global'); + let Video: any; + + const aspectRatio = NP.divide(2498, 3940).toFixed(10); + + const screenWidth = window.innerWidth * 1.3; + let videoWidth = 0; + let videoHeight = 0; + + if (screenWidth < 1040) { + videoWidth = 1040; + } else { + videoWidth = screenWidth; + } + + videoHeight = Math.ceil(NP.times(videoWidth, aspectRatio)); + + useEffect(() => { + const welcomeVideo = document.querySelector('.welcome-video'); + if (welcomeVideo) { + Video = videojs(welcomeVideo, { + controls: false, + autoplay: true, + loop: true, + preload: 'auto', + }); + } + return () => { + Video.dispose(); + }; + }, []); + + return ( +
    +
    +
    +

    + {intl.formatMessage({ + id: 'OBD.pages.components.Welcome.WelcomeToDeploy', + defaultMessage: '欢迎您部署', + })} +

    + {locale === 'zh-CN' ? ( +

    + OceanBase + {intl.formatMessage({ + id: 'OBD.pages.components.Welcome.DistributedDatabase', + defaultMessage: '分布式数据库', + })} +

    + ) : ( +

    + {intl.formatMessage({ + id: 'OBD.pages.components.Welcome.DistributedDatabase', + defaultMessage: '分布式数据库', + })} +

    + )} +

    OceanBase comprehensive database

    +
    + +
    +
    + +
    +
    + ); +} diff --git a/web/src/pages/Obdeploy/index.less b/web/src/pages/Obdeploy/index.less new file mode 100644 index 0000000..5b6006b --- /dev/null +++ b/web/src/pages/Obdeploy/index.less @@ -0,0 +1,66 @@ +@backgroundColor: #f5f8ff; + +.container { + height: 100%; +} + +.englishContainer { + font-family: SourceSansPro-Semibold, SourceSansPro-Regular; +} + +.pageHeader { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 99; + height: 48px; + padding: 0 20px; + overflow: hidden; + line-height: 48px; + background-color: @backgroundColor; + border-bottom: 1px solid #dde4ed; + .logo { + position: relative; + top: -2px; + width: 125px; + vertical-align: middle; + } + .logoText { + margin-left: 8px; + font-size: 14px; + } + .actionContent { + float: right; + } + .action { + color: #5c6b8a; + } + .actionIcon { + margin-right: 10px; + } +} + +.pageContainer { + min-height: calc(100% - 240px); + padding-top: 170px; + padding-bottom: 70px; + background-color: @backgroundColor; + .pageMain { + .pageContent { + width: 1040px; + margin: 0 auto; + overflow: auto; + } + } +} + +.mask { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 100; + background: rgba(0, 0, 0, 0.45); +} diff --git a/web/src/pages/Obdeploy/index.tsx b/web/src/pages/Obdeploy/index.tsx new file mode 100644 index 0000000..099e826 --- /dev/null +++ b/web/src/pages/Obdeploy/index.tsx @@ -0,0 +1,310 @@ +import { intl } from '@/utils/intl'; +import { useEffect, useState } from 'react'; +import { useModel } from 'umi'; +import { Space, notification, ConfigProvider, Dropdown, Modal } from 'antd'; +import { + HomeOutlined, + ReadOutlined, + ProfileOutlined, + GlobalOutlined, + InfoCircleOutlined, +} from '@ant-design/icons'; +import useRequest from '@/utils/useRequest'; +import { getErrorInfo, getRandomPassword } from '@/utils'; +import { getDeployment } from '@/services/ob-deploy-web/Deployments'; +import { validateOrSetKeepAliveToken } from '@/services/ob-deploy-web/Common'; +import Welcome from './Welcome'; +import InstallConfig from './InstallConfig'; +import NodeConfig from './NodeConfig'; +import ClusterConfig from './ClusterConfig'; +import PreCheck from './PreCheck'; +import InstallProcess from './InstallProcess'; +import InstallFinished from './InstallFinished'; +import ExitPage from './ExitPage'; +import ProgressQuit from './ProgressQuit'; +import Steps from './Steps'; +import { localeList, localeText } from '@/constants'; +import type { Locale } from 'antd/es/locale-provider'; +import { setLocale, getLocale } from 'umi'; +import enUS from 'antd/es/locale/en_US'; +import zhCN from 'antd/es/locale/zh_CN'; +import theme from '../theme'; +import styles from './index.less'; + +export default function IndexPage() { + const uuid = window.localStorage.getItem('uuid'); + const locale = getLocale(); + const { + setCurrentStep, + setConfigData, + currentStep, + errorVisible, + errorsList, + setErrorVisible, + setErrorsList, + first, + setFirst, + token, + setToken, + aliveTokenTimer + } = useModel('global'); + const [lastError, setLastError] = useState({}); + const [isInstall, setIsInstall] = useState(false); + const [localeConfig, setLocalConfig] = useState( + locale === 'zh-CN' ? zhCN : enUS, + ); + + const { run: fetchDeploymentInfo } = useRequest(getDeployment, { + onError: (e: any) => { + const errorInfo = getErrorInfo(e); + setErrorVisible(true); + setErrorsList([...errorsList, errorInfo]); + }, + }); + + const { run: handleValidateOrSetKeepAliveToken } = useRequest( + validateOrSetKeepAliveToken, + { + onSuccess: ({ success, data }: API.OBResponse) => { + if (success) { + if (!data) { + if (first) { + Modal.confirm({ + className: 'new-page-confirm', + title: intl.formatMessage({ + id: 'OBD.src.pages.ItIsDetectedThatYou', + defaultMessage: + '检测到您打开了一个新的部署流程页面,请确认是否使用新页面继续部署工作?', + }), + width: 424, + icon: , + content: intl.formatMessage({ + id: 'OBD.src.pages.UseTheNewPageTo', + defaultMessage: + '使用新的页面部署,原部署页面将无法再提交任何部署请求', + }), + onOk: () => { + handleValidateOrSetKeepAliveToken({ token, overwrite: true }); + }, + onCancel: () => { + setCurrentStep(8); + }, + }); + setTimeout(() => { + document.activeElement.blur(); + }, 100); + } else { + setCurrentStep(8); + } + } else if (currentStep > 4) { + if (!isInstall) { + handleValidateOrSetKeepAliveToken({ + token: token, + is_clear: true, + }); + setIsInstall(true); + } + } else { + aliveTokenTimer.current = setTimeout(() => { + handleValidateOrSetKeepAliveToken({ token }); + }, 1000); + } + setFirst(false); + } + }, + onError: () => { + if (currentStep > 4) { + handleValidateOrSetKeepAliveToken({ token: token, is_clear: true }); + } else { + aliveTokenTimer.current = setTimeout(() => { + handleValidateOrSetKeepAliveToken({ token }); + }, 1000); + } + }, + }, + ); + + const setCurrentLocale = (key: string) => { + if (key !== locale) { + setLocale(key); + window.localStorage.setItem('uuid', token); + } + setLocalConfig(key === 'zh-CN' ? zhCN : enUS); + }; + + const getLocaleItems = () => { + return localeList.map((item) => ({ + ...item, + label: setCurrentLocale(item.key)}>{item.label}, + })); + }; + + const contentConfig = { + 1: , + 2: , + 3: , + 4: , + 5: , + 6: , + 7: , + 8: , + }; + + useEffect(() => { + let newToken = ''; + + fetchDeploymentInfo({ task_status: 'INSTALLING' }).then( + ({ success, data }: API.OBResponse) => { + if (success && data?.items?.length) { + setCurrentStep(5); + setConfigData({ + components: { oceanbase: { appname: data?.items[0]?.name } }, + }); + } else { + if (!token) { + if (uuid) { + newToken = uuid; + } else { + newToken = `${Date.now()}${getRandomPassword(true)}`; + } + setToken(newToken); + handleValidateOrSetKeepAliveToken({ token: newToken }); + } else { + handleValidateOrSetKeepAliveToken({ token }); + } + window.localStorage.setItem('uuid', ''); + } + }, + ); + const sendBeacon = () => { + const url = + window.location.origin + + '/api/v1/connect/keep_alive?token=' + + token + + '&is_clear=true'; + navigator.sendBeacon(url); + }; + window.addEventListener('beforeunload', function (e) { + sendBeacon(); + }); + }, []); + + useEffect(() => { + const newLastError = errorsList?.[errorsList?.length - 1] || null; + if (errorVisible) { + if (newLastError?.desc !== lastError?.desc) { + notification.error({ + description: newLastError?.desc, + message: newLastError?.title, + duration: null, + }); + } + } else { + notification.destroy(); + } + setLastError(newLastError); + }, [errorVisible, errorsList, lastError]); + + const containerStyle = { + minHeight: `${ + currentStep < 6 ? 'calc(100% - 240px)' : 'calc(100% - 140px)' + }`, + paddingTop: `${currentStep < 6 ? '170px' : '70px'}`, + }; + + return ( + + ); +} diff --git a/web/src/pages/Obdeploy/indexEn.less b/web/src/pages/Obdeploy/indexEn.less new file mode 100644 index 0000000..49831fa --- /dev/null +++ b/web/src/pages/Obdeploy/indexEn.less @@ -0,0 +1,888 @@ +@cardBackgroundColor: #f8fafe; +@smallSpace: 8px; +@subTitleColor: #5c6b8a; +@greyTextColor: #8592ad; +@backgroundColor: #f5f8ff; +@welcomeBackgroundColor: #e6ecf1; + +.videoContainer { + position: relative; + width: 100%; + height:100%; + padding-top: 50px; + overflow: hidden; + text-align: center; + background-color: @welcomeBackgroundColor; + :global { + .vjs-tech { + z-index: 1; + } + .vjs-text-track-display { + background-color: @welcomeBackgroundColor !important; + } + } + .videoContent { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-47%, -43%); + .videoActions { + position: absolute; + top: 35%; + left: 16%; + z-index: 10; + .h1 { + margin: 0 !important; + font-size: 2.4vw !important; + line-height: 4vw; + letter-spacing: 0vw; + // font-weight: 500; + // font-size: 40px; + // color: #000000; + // letter-spacing: 0; + // text-align: left; + // line-height: 48px; + } + .h2 { + position: relative; + left: -0.2vw; + margin: 0 !important; + font-weight: 500 !important; + font-size: 1vw !important; + letter-spacing: 0vw; + // font-weight: 500; + // font-size: 40px; + // color: #000000; + // letter-spacing: 0; + // text-align: left; + // line-height: 48px; + .letter { + font-family: SourceSansPro-Semibold, SourceSansPro-Regular; + } + } + + .desc { + color: #000000; + font-weight: 400; + font-size: 18px; + line-height: 24px; + letter-spacing: 0; + text-align: left; + opacity: 0.65; + } + .startButtonContainer { + text-align: center; + .startButton { + height: 2.8vw !important; + margin-top: 1.5vw !important; + padding: 0.4vw 1vw !important; + font-size: 1.3vw !important; + border-radius: 0.6vw; + } + } + } + .video { + width: 100%; + background-color: @welcomeBackgroundColor; + } + :global { + .vjs-poster { + top: 1px !important; + left: 1px !important; + background-position: 0 0 !important; + background-size: 100% !important; + } + } + } +} + +.spaceWidth { + width: 100%; +} + +.stepsContainer { + position: fixed; + top: 49px; + right: 0; + left: 0; + z-index: 99; + background-color: #f5f8ff; + .stepsContent { + position: relative; + width: 900px; + margin: 0 auto; + padding-top: 30px; + .stepsBackground { + position: absolute; + top: 40px; + left: 83px; + z-index: 0; + width: 725px; + height: 12px; + background-color: #e2e8f3; + } + .stepsBackgroundProgress { + height: 12px; + background-image: linear-gradient(-45deg, #006aff 0%, #5189fb 100%); + } + .stepItem { + position: relative; + z-index: 10; + display: inline-block; + width: 180px; + height: 60px; + color: #5c6b8a; + text-align: center; + .stepTitle { + position: absolute; + bottom: 0; + left: 0; + width: 184px; + white-space: nowrap; + &.stepAlreadyTitle { + color: #132039; + } + &.stepCurrentTitle { + color: #0055ff; + font-weight: 500; + } + } + + .stepIcon { + display: inline-block; + width: 18px; + margin-top: 5px; + color: #417cf6; + font-size: 20px; + text-align: center; + background-color: #fff; + border-radius: 50%; + & > svg { + margin-left: -1px !important; + } + &.stepWaitIcon { + color: #cdd5e4; + } + &.stepCurrentIcon { + width: 28px; + margin-top: 0; + color: #417cf6 !important; + font-size: 30px; + } + } + } + } +} + +.draftModal { + .modalTitleIcon { + margin-right: 16px; + font-size: 24px; + } + .modalTitle { + vertical-align: top; + } + :global { + .ant-modal-content { + padding: 32px !important; + } + .ant-modal-title { + color: #132039 !important; + font-weight: 500 !important; + line-height: 24px !important; + } + } +} + +.deleteDeployContent { + height: 170px; + padding-top: 30px; + text-align: center; + .deleteDeployText { + font-weight: 500; + font-size: 16px; + } + .deleteDeployProgress { + margin-top: 32px; + } +} + +.checkInfoSpace { + :global { + .ant-col { + padding-right: 0 !important; + padding-left: 0 !important; + } + .ant-col.ant-col-12:nth-child(2n + 1) { + padding-right: @smallSpace !important; + } + .ant-col.ant-col-12:nth-child(2n) { + padding-left: @smallSpace !important; + } + } +} + +.pageCard { + box-shadow: 0 2px 4px 0 rgba(19, 32, 57, 0.02), + 0 1px 6px -1px rgba(19, 32, 57, 0.02), 0 1px 2px 0 rgba(19, 32, 57, 0.03); + :global { + .ant-space-item { + .ant-col { + padding-right: 0 !important; + padding-left: 0 !important; + } + } + } +} + +.titleExtra { + margin-left: 12px; + color: @greyTextColor; + font-weight: 400 !important; + font-size: 14px !important; +} + +.deployTypeCardContailer { + display: inline-block; + width: 488px; + :global { + .ant-card-body { + line-height: 22px !important; + } + } + .deployTypeCard { + font-size: 18px; + text-align: center; + cursor: pointer; + &.selectedDeployTypeCard { + font-weight: 500; + border: 2px solid #006aff; + } + } + + .typeTag { + vertical-align: top; + } + + .typeDesc { + display: inline-block; + height: 44px; + margin-top: @smallSpace; + color: @greyTextColor; + visibility: hidden; + &.selectedTypeDesc { + visibility: visible; + } + } +} + +.iconContainer { + position: relative; + display: inline-block; + width: 16px; + height: 16px; + margin-left: @smallSpace; + color: #fff; + font-size: 12px; + line-height: 22px; + vertical-align: middle; + border-radius: 50%; + .icon { + position: absolute; + top: 2px; + left: 2px; + } +} + +.popupClassName { + width: 500px !important; + .localTag { + float: right; + color: #006aff; + font-weight: normal !important; + } +} + +.learnMore { + float: right; + color: #006aff !important; +} + +.disabledDel { + color: #cdd5e4; + cursor: not-allowed; +} + +.inputText { + width: 216px; +} + +.componentCard { + margin-bottom: 16px !important; + background-color: @cardBackgroundColor !important; + :global { + .ant-pro-card-body { + padding: 0 !important; + } + } + &.disabledCard { + opacity: 0.4; + } + &:last-child { + margin-bottom: 0 !important; + } +} + +.disabledRow { + opacity: 0.4; +} + +.viewRule { + position: absolute; + top: 92px; + left: 360px; +} + +.modeExtra { + position: absolute; + top: 143px; + width: 100%; + height: 22px; + .modeExtraContent { + position: absolute; + top: -22px; + color: @greyTextColor; + line-height: 22px; + } +} + +.moreSwitch { + color: #132039; + font-weight: 500; + font-size: 16px; +} + +.infoSubCard { + overflow: hidden; + border-radius: 8px; + .pwdIcon { + position: absolute; + top: 2px; + right: 0; + color: #8592ad; + font-size: 17px; + } + :global { + .ant-pro-card .ant-pro-card-body { + padding-top: 4px !important; + } + + .ant-pro-card-body, + .ant-pro-card-header { + background-color: @cardBackgroundColor !important; + } + .ant-pro-card-title { + color: @subTitleColor !important ; + font-weight: normal !important; + font-size: 14px !important; + } + .ant-pro-card-body { + color: #132039 !important; + } + .ant-pro-card-col.ant-pro-card-split-vertical { + border-inline-end: none !important; + .ant-pro-card::before { + position: absolute; + top: 50%; + width: 1px; + height: 48px; + background-color: #e8eaf3; + transform: translateY(-50%); + transition: #e8eaf3 0.3s; + content: ''; + inset-inline-end: 0; + } + } + } +} + +.inlineFormItem { + margin-block: -5px; + margin-inline: 0px; +} + +.preCheckSubCard { + height: 400px; + background-color: @cardBackgroundColor; + :global { + .ant-pro-card-body { + padding-top: 0 !important; + overflow: auto; + } + .ant-pro-card-header { + padding-top: 12px !important; + padding-bottom: 14px !important; + border-bottom: 1px solid #e2e8f3 !important; + } + .ant-pro-card-header .ant-pro-card-title { + font-weight: normal !important; + } + } + + .preCheckProgress { + position: absolute; + top: 42px; + left: 0px; + z-index: 9; + :global { + .ant-progress-inner { + height: 1px; + overflow: visible !important; + background-color: #e2e8f3 !important; + .ant-progress-bg { + height: 2px !important; + border-radius: 0 !important; + } + } + } + } + + .preCheckBtn { + height: 28px !important; + padding: 2px 8px !important; + } + + :global { + .ant-progress-status-active { + .ant-progress-bg::after { + position: absolute; + top: -2px; + right: -4px; + display: block; + width: 6px; + height: 6px; + background-color: #006aff; + border-radius: 50%; + content: ''; + } + } + } + + .timelineContainer { + position: relative; + height: 322px; + padding-top: 15px; + overflow: auto; + + :global { + .ant-timeline-item-last { + height: 10px !important; + padding-bottom: 0 !important; + .ant-timeline-item-content { + min-height: 22px !important; + } + } + } + } + + .failedContainer { + position: relative; + height: 322px; + overflow: auto; + } + + .failedItem { + padding: 12px 24px; + border-top: 1px solid #e2e8f3; + &:first-child { + border-top: none; + } + .preCheckLearnMore { + display: inline-block; + margin-top: 6px; + margin-left: 102px; + } + } + .failedItemIcon { + position: relative; + width: 10px; + height: 10px; + margin-left: 0px; + font-size: 6px; + .icon { + top: 2px; + left: 2px; + } + } +} + +@keyframes animate1 { + 0% { + background-color: #1677ff; + transform: scale(1.5); + } +} + +@keyframes animate2 { + 25% { + background-color: #1677ff; + transform: scale(1.5); + } +} + +@keyframes animate3 { + 50% { + background-color: #1677ff; + transform: scale(1.5); + } +} + +@keyframes animate4 { + 75% { + background-color: #1677ff; + transform: scale(1.5); + } +} + +.installSubCard, +.reportLog { + background-color: @cardBackgroundColor; +} +.installLog, +.reportLog { + margin: 0 !important; + overflow: auto; + color: #8592ad; +} +.installLog { + height: 360px; +} +.reportLog { + max-width: 1008px; + min-height: 100px; + max-height: 360px; + padding: 16px; + border-radius: 8px; +} + +.preLoading { + padding-top: 130px; + text-align: center; + .shapeContainer { + position: relative; + left: -6px; + display: inline-block !important; + } + .desc { + margin-top: 16px; + color: #8592ad; + } +} + +.shapeContainer { + display: flex; + height: 16px; + margin: 10px 0 auto; + .shape { + position: relative; + display: inline-block; + width: 5px; + height: 5px; + margin-left: 10px; + background-color: #b3ccff; + border-radius: 100%; + &:before { + position: absolute; + top: 0; + left: 0; + width: 5px; + height: 5px; + background-color: #b3ccff; + border-radius: 100%; + animation-fill-mode: both; + content: ''; + } + } + .shape:nth-child(1) { + animation-delay: -0.16s; + &::before { + animation: animate1 1.4s infinite linear; + } + } + .shape:nth-child(2) { + animation-delay: -0.16s; + &::before { + animation: animate2 1.4s infinite linear; + } + } + .shape:nth-child(3) { + animation-delay: -0.32s; + &::before { + animation: animate3 1.4s infinite linear; + } + } + .shape:nth-child(4) { + animation-delay: -0.16s; + &::before { + animation: animate4 1.4s infinite linear; + } + } +} + +.reportTooltip { + max-width: 520px; + :global { + .ant-tooltip-arrow { + color: #fff; + --antd-arrow-background-color: #fff; + } + .ant-tooltip-inner { + width: 520px; + max-height: 230px; + padding: 16px; + overflow: auto; + color: #132039; + background-color: #fff; + } + } +} + +.pageFooterContainer { + position: fixed; + right: 0; + bottom: 0; + left: 0; + z-index: 99; + padding: 16px; + background-color: #f5f8ff; + border-top: 1px solid #dde4ed; + .pageFooter { + width: 1040px; + margin: 0 auto; + overflow: hidden; + .foolterAction { + float: right; + } + } +} + +@media screen and (max-width: 1040px) { + .pageFooterContainer { + .pageFooter { + width: 100% !important; + } + } +} + +.componentTable, +.nodeEditabletable { + :global { + .ant-table, + .ant-table-wrapper .ant-table-thead > tr > th, + .ant-table-thead > tr > th { + background-color: rgba(0, 0, 0, 0) !important; + } + .ant-table { + color: #132039 !important; + } + .ant-table-thead > tr > th { + color: @subTitleColor !important; + font-weight: normal !important; + } + } +} + +.componentTable { + :global { + .ant-table + .ant-table-tbody + tr:nth-child(2n + 1):not(.ant-table-placeholder) + td { + background-color: rgba(0, 0, 0, 0) !important ; + } + } +} + +.componentTable, +.nodeEditabletable, +.connectTable { + :global { + .ant-table-cell::before { + width: 0 !important; + } + .ant-table-thead > tr > th { + padding-bottom: 0 !important; + border-bottom: none !important; + } + } +} + +.nodeEditabletable { + :global { + .ant-pro-card-body { + padding-inline: 0 !important; + padding-block: 0 !important; + } + .ant-table-cell { + padding-top: 0 !important; + padding-left: 0 !important; + } + .ant-btn-dashed { + width: calc(100% - 36px) !important; + margin-top: 4px !important; + color: @greyTextColor !important; + } + .ant-table + .ant-table-tbody + tr:nth-child(2n):not(.ant-table-placeholder) + td { + background-color: #fff !important; + } + .ant-table .ant-table-tbody tr td { + padding-top: 11px !important; + padding-bottom: 11px !important; + } + } +} + +.connectTable { + :global { + .ant-table-thead > tr > th { + padding-left: 0 !important; + } + } +} + +.collapsibleCard { + :global { + .ant-pro-card-title .anticon { + position: absolute; + top: 21px; + left: 180px; + } + } +} + +.paramterSelect { + :global { + .ant-select-selector { + height: 28px !important; + } + .ant-select-selection-item { + line-height: 26px !important; + } + } +} + +.paramterInput { + width: 126px !important; + :global { + .ant-input { + height: 28px; + } + } +} + +.progressEffectContainer { + position: relative; + height: 150px; + .deployTitle { + position: absolute; + left: calc(50% - 70px); + font-weight: 500; + font-size: 16px; + } + .computer { + position: absolute; + top: 20px; + left: 195px; + .computerAnimate { + width: 150px; + } + } + .progress { + position: absolute; + top: 65px; + left: 327px; + .progressVedio { + width: 285px; + height: 11px; + background-color: #fff; + :global { + .vjs-text-track-display { + background-color: #fff !important; + } + .vjs-poster { + top: 1px !important; + left: 1px !important; + background-position: 0 0 !important; + background-size: 100% !important; + } + .vjs-modal-dialog { + background: #fff !important; + } + .vjs-error-display:before { + content: '' !important; + } + } + } + .progressCover { + position: absolute; + top: 2.5px; + right: 2px; + height: 5.5px; + background: #fff; + border-radius: 0 5px 5px 0; + } + } + + .spaceman { + position: absolute; + top: 25px; + left: 310px; + .spacemanAnimate { + width: 320px; + } + } + .database { + position: absolute; + top: 20px; + right: 190px; + .sqlAnimate { + width: 150px; + } + } +} + +.deploymentName { + position: absolute; + bottom: 40px; + left: 50%; + color: @greyTextColor; + font-size: 12px; + transform: translateX(-50%); +} + +.exitPage { + height: 680px; + margin-top: 32px; + padding-top: 160px; + text-align: center; + border: none; + .exitPageText { + font-size: 18px !important; + } +} + +.commandTooltip { + :global { + .ant-tooltip-inner { + width: 400px; + } + } +} + +:global { + .english-container { + } +} diff --git a/web/src/pages/Obdeploy/indexZh.less b/web/src/pages/Obdeploy/indexZh.less new file mode 100644 index 0000000..f4048f8 --- /dev/null +++ b/web/src/pages/Obdeploy/indexZh.less @@ -0,0 +1,890 @@ +@cardBackgroundColor: #f8fafe; +@smallSpace: 8px; +@subTitleColor: #5c6b8a; +@greyTextColor: #8592ad; +@backgroundColor: #f5f8ff; +@welcomeBackgroundColor: #e6ecf1; + +.videoContainer { + position: relative; + width: 100%; + height: calc(100% - 50px); + box-sizing: content-box; + padding-top: 50px; + overflow: hidden; + text-align: center; + background-color: @welcomeBackgroundColor; + :global { + .vjs-tech { + z-index: 1; + } + .vjs-text-track-display { + background-color: @welcomeBackgroundColor !important; + } + } + .videoContent { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-47%, -43%); + .videoActions { + position: absolute; + top: 35%; + left: 18%; + z-index: 10; + .h1 { + margin: 0 !important; + // font-size: 6vw !important; + // line-height: 6vw; + // letter-spacing: 0.7vw; + font-weight: 500; + font-size: 40px; + color: #000000; + letter-spacing: 0; + text-align: left; + line-height: 48px; + } + .h2 { + position: relative; + left: -0.2vw; + margin: 0 !important; + // font-weight: 400 !important; + // font-size: 2.8vw !important; + // letter-spacing: 0.1vw; + font-weight: 500; + font-size: 40px; + color: #000000; + letter-spacing: 0; + text-align: left; + line-height: 48px; + .letter { + font-family: SourceSansPro-Semibold, SourceSansPro-Regular; + } + } + .desc { + color: #000000; + font-weight: 400; + font-size: 18px; + line-height: 24px; + letter-spacing: 0; + text-align: left; + opacity: 0.65; + } + .startButtonContainer { + display: flex; + text-align: center; + .startButton { + height: 2.8vw !important; + margin-top: 2.5vw !important; + padding: 0.4vw 1vw !important; + font-size: 1.3vw !important; + border-radius: 0.6vw; + } + } + } + .video { + width: 100%; + background-color: @welcomeBackgroundColor; + } + :global { + .vjs-poster { + top: 1px !important; + left: 1px !important; + background-position: 0 0 !important; + background-size: 100% !important; + } + } + } +} + +.spaceWidth { + width: 100%; +} + +.stepsContainer { + position: fixed; + top: 49px; + right: 0; + left: 0; + z-index: 99; + background-color: #f5f8ff; + .stepsContent { + position: relative; + width: 700px; + margin: 0 auto; + padding-top: 30px; + .stepsBackground { + position: absolute; + top: 40px; + left: 30px; + z-index: 0; + width: 635px; + height: 12px; + background-color: #e2e8f3; + } + .stepsBackgroundProgress { + height: 12px; + background-image: linear-gradient(-45deg, #006aff 0%, #5189fb 100%); + } + .stepItem { + position: relative; + z-index: 10; + display: inline-block; + width: 60px; + height: 60px; + color: #5c6b8a; + text-align: center; + .stepTitle { + position: absolute; + bottom: 0; + left: -25px; + width: 110px; + &.stepAlreadyTitle { + color: #132039; + } + &.stepCurrentTitle { + color: #0055ff; + font-weight: 500; + } + } + + .stepIcon { + display: inline-block; + width: 18px; + margin-top: 5px; + color: #417cf6; + font-size: 20px; + text-align: center; + background-color: #fff; + border-radius: 50%; + & > svg { + margin-left: -1px !important; + } + &.stepWaitIcon { + color: #cdd5e4; + } + &.stepCurrentIcon { + width: 28px; + margin-top: 0; + color: #417cf6 !important; + font-size: 30px; + } + } + } + } +} + +.draftModal { + .modalTitleIcon { + margin-right: 16px; + font-size: 24px; + } + .modalTitle { + vertical-align: top; + } + :global { + .ant-modal-content { + padding: 32px !important; + } + .ant-modal-title { + color: #132039 !important; + font-weight: 500 !important; + line-height: 24px !important; + } + } +} + +.deleteDeployContent { + height: 170px; + padding-top: 30px; + text-align: center; + .deleteDeployText { + font-weight: 500; + font-size: 16px; + } + .deleteDeployProgress { + margin-top: 32px; + } +} + +.checkInfoSpace { + :global { + .ant-col { + padding-right: 0 !important; + padding-left: 0 !important; + } + .ant-col.ant-col-12:nth-child(2n + 1) { + padding-right: @smallSpace !important; + } + .ant-col.ant-col-12:nth-child(2n) { + padding-left: @smallSpace !important; + } + } +} + +.pageCard { + box-shadow: 0 2px 4px 0 rgba(19, 32, 57, 0.02), + 0 1px 6px -1px rgba(19, 32, 57, 0.02), 0 1px 2px 0 rgba(19, 32, 57, 0.03); + :global { + .ant-space-item { + .ant-col { + padding-right: 0 !important; + padding-left: 0 !important; + } + } + } +} + +.titleExtra { + margin-left: 12px; + color: @greyTextColor; + font-weight: 400 !important; + font-size: 14px !important; +} + +.deployTypeCardContailer { + display: inline-block; + width: 216px; + :global { + .ant-card-body { + line-height: 22px !important; + } + } + .deployTypeCard { + font-size: 18px; + text-align: center; + cursor: pointer; + &.selectedDeployTypeCard { + font-weight: 500; + border: 2px solid #006aff; + } + } + + .typeTag { + vertical-align: top; + } + + .typeDesc { + display: inline-block; + margin-top: @smallSpace; + color: @greyTextColor; + visibility: hidden; + &.selectedTypeDesc { + visibility: visible; + } + } +} + +.iconContainer { + position: relative; + display: inline-block; + width: 16px; + height: 16px; + margin-left: @smallSpace; + color: #fff; + font-size: 12px; + line-height: 22px; + vertical-align: middle; + border-radius: 50%; + .icon { + position: absolute; + top: 2px; + left: 2px; + } +} + +.popupClassName { + width: 400px !important; + + .localTag { + float: right; + color: #006aff; + font-weight: normal !important; + } +} + +.learnMore { + float: right; + color: #006aff !important; +} + +.disabledDel { + color: #cdd5e4; + cursor: not-allowed; +} + +.inputText { + width: 216px; +} + +.componentCard { + margin-bottom: 16px !important; + background-color: @cardBackgroundColor !important; + :global { + .ant-pro-card-body { + padding: 0 !important; + } + } + &.disabledCard { + opacity: 0.4; + } + &:last-child { + margin-bottom: 0 !important; + } +} + +.disabledRow { + opacity: 0.4; +} + +.viewRule { + position: absolute; + top: 92px; + left: 209px; +} + +.modeExtra { + position: absolute; + top: 143px; + width: 100%; + height: 22px; + .modeExtraContent { + position: absolute; + top: -22px; + color: @greyTextColor; + line-height: 22px; + } +} + +.moreSwitch { + color: #132039; + font-weight: 500; + font-size: 16px; +} + +.infoSubCard { + overflow: hidden; + border-radius: 8px; + .pwdIcon { + position: absolute; + top: 2px; + right: 0; + color: #8592ad; + font-size: 17px; + } + :global { + .ant-pro-card .ant-pro-card-body { + padding-top: 4px !important; + } + + .ant-pro-card-body, + .ant-pro-card-header { + background-color: @cardBackgroundColor !important; + } + .ant-pro-card-title { + color: @subTitleColor !important ; + font-weight: normal !important; + font-size: 14px !important; + } + .ant-pro-card-body { + color: #132039 !important; + } + .ant-pro-card-col.ant-pro-card-split-vertical { + border-inline-end: none !important; + .ant-pro-card::before { + position: absolute; + top: 50%; + width: 1px; + height: 48px; + background-color: #e8eaf3; + transform: translateY(-50%); + transition: #e8eaf3 0.3s; + content: ''; + inset-inline-end: 0; + } + } + } +} + +.inlineFormItem { + margin-block: -5px; + margin-inline: 0px; +} + +.preCheckSubCard { + height: 400px; + background-color: @cardBackgroundColor; + :global { + .ant-pro-card-body { + padding-top: 0 !important; + overflow: auto; + } + .ant-pro-card-header { + padding-top: 12px !important; + padding-bottom: 14px !important; + border-bottom: 1px solid #e2e8f3 !important; + } + .ant-pro-card-header .ant-pro-card-title { + font-weight: normal !important; + } + } + + .preCheckProgress { + position: absolute; + top: 42px; + left: 0px; + z-index: 9; + :global { + .ant-progress-inner { + height: 1px; + overflow: visible !important; + background-color: #e2e8f3 !important; + .ant-progress-bg { + height: 2px !important; + border-radius: 0 !important; + } + } + } + } + + .preCheckBtn { + height: 28px !important; + padding: 2px 8px !important; + } + + :global { + .ant-progress-status-active { + .ant-progress-bg::after { + position: absolute; + top: -2px; + right: -4px; + display: block; + width: 6px; + height: 6px; + background-color: #006aff; + border-radius: 50%; + content: ''; + } + } + } + + .timelineContainer { + position: relative; + height: 322px; + padding-top: 15px; + overflow: auto; + + :global { + .ant-timeline-item-last { + height: 10px !important; + padding-bottom: 0 !important; + .ant-timeline-item-content { + min-height: 22px !important; + } + } + } + } + + .failedContainer { + position: relative; + height: 322px; + overflow: auto; + } + + .failedItem { + padding: 12px 24px; + border-top: 1px solid #e2e8f3; + &:first-child { + border-top: none; + } + .preCheckLearnMore { + display: inline-block; + margin-top: 6px; + margin-left: 60px; + } + } + .failedItemIcon { + position: relative; + top: -1px; + width: 10px; + height: 10px; + margin-left: 0px; + font-size: 6px; + .icon { + top: 2px; + left: 2px; + } + } +} + +@keyframes animate1 { + 0% { + background-color: #1677ff; + transform: scale(1.5); + } +} + +@keyframes animate2 { + 25% { + background-color: #1677ff; + transform: scale(1.5); + } +} + +@keyframes animate3 { + 50% { + background-color: #1677ff; + transform: scale(1.5); + } +} + +@keyframes animate4 { + 75% { + background-color: #1677ff; + transform: scale(1.5); + } +} + +.installSubCard, +.reportLog { + background-color: @cardBackgroundColor; +} +.installLog, +.reportLog { + margin: 0 !important; + overflow: auto; + color: #8592ad; +} +.installLog { + height: 360px; +} +.reportLog { + max-width: 1008px; + min-height: 100px; + max-height: 360px; + padding: 16px; + border-radius: 8px; +} + +.preLoading { + padding-top: 130px; + text-align: center; + .shapeContainer { + position: relative; + left: -6px; + display: inline-block !important; + } + .desc { + margin-top: 16px; + color: #8592ad; + } +} + +.shapeContainer { + display: flex; + height: 16px; + margin: 10px 0 auto; + .shape { + position: relative; + display: inline-block; + width: 4px; + height: 4px; + margin-left: 10px; + background-color: #b3ccff; + border-radius: 100%; + &:before { + position: absolute; + top: 0; + left: 0; + width: 4px; + height: 4px; + background-color: #b3ccff; + border-radius: 100%; + animation-fill-mode: both; + content: ''; + } + } + .shape:nth-child(1) { + animation-delay: -0.16s; + &::before { + animation: animate1 1.4s infinite linear; + } + } + .shape:nth-child(2) { + animation-delay: -0.16s; + &::before { + animation: animate2 1.4s infinite linear; + } + } + .shape:nth-child(3) { + animation-delay: -0.32s; + &::before { + animation: animate3 1.4s infinite linear; + } + } + .shape:nth-child(4) { + animation-delay: -0.16s; + &::before { + animation: animate4 1.4s infinite linear; + } + } +} + +.reportTooltip { + max-width: 520px; + :global { + .ant-tooltip-arrow { + color: #fff; + --antd-arrow-background-color: #fff; + } + .ant-tooltip-inner { + width: 520px; + max-height: 230px; + padding: 16px; + overflow: auto; + color: #132039; + background-color: #fff; + } + } +} + +.pageFooterContainer { + position: fixed; + right: 0; + bottom: 0; + left: 0; + z-index: 99; + padding: 16px; + background-color: #f5f8ff; + border-top: 1px solid #dde4ed; + .pageFooter { + width: 1040px; + margin: 0 auto; + overflow: hidden; + .foolterAction { + float: right; + } + } +} + +@media screen and (max-width: 1040px) { + .pageFooterContainer { + .pageFooter { + width: 100% !important; + } + } +} + +.componentTable, +.nodeEditabletable { + :global { + .ant-table, + .ant-table-wrapper .ant-table-thead > tr > th, + .ant-table-thead > tr > th { + background-color: rgba(0, 0, 0, 0) !important; + } + .ant-table { + color: #132039 !important; + } + .ant-table-thead > tr > th { + color: @subTitleColor !important; + font-weight: normal !important; + } + } +} + +.componentTable { + :global { + .ant-table + .ant-table-tbody + tr:nth-child(2n + 1):not(.ant-table-placeholder) + td { + background-color: rgba(0, 0, 0, 0) !important ; + } + } +} + +.componentTable, +.nodeEditabletable, +.connectTable { + :global { + .ant-table-cell::before { + width: 0 !important; + } + .ant-table-thead > tr > th { + padding-bottom: 0 !important; + border-bottom: none !important; + } + } +} + +.nodeEditabletable { + :global { + .ant-pro-card-body { + padding-inline: 0 !important; + padding-block: 0 !important; + } + .ant-table-cell { + padding-left: 0 !important; + padding-left: 0 !important; + } + .ant-btn-dashed { + width: calc(100% - 36px) !important; + margin-top: 4px !important; + color: @greyTextColor !important; + } + .ant-table + .ant-table-tbody + tr:nth-child(2n):not(.ant-table-placeholder) + td { + background-color: #fff !important; + } + .ant-table .ant-table-tbody tr td { + padding-top: 11px !important; + padding-bottom: 11px !important; + } + } +} + +.connectTable { + :global { + .ant-table-thead > tr > th { + padding-left: 0 !important; + } + } +} + +.collapsibleCard { + :global { + .ant-pro-card-title .anticon { + position: absolute; + top: 21px; + left: 100px; + } + } +} + +.paramterSelect { + :global { + .ant-select-selector { + height: 28px !important; + } + .ant-select-selection-item { + line-height: 26px !important; + } + } +} + +.paramterInput { + width: 126px !important; + :global { + .ant-input { + height: 28px; + } + } +} + +.progressEffectContainer { + position: relative; + height: 150px; + .deployTitle { + position: absolute; + left: 50%; + font-weight: 500; + font-size: 16px; + transform: translateX(-50%); + } + .computer { + position: absolute; + top: 20px; + left: 195px; + .computerAnimate { + width: 150px; + } + } + .progress { + position: absolute; + top: 65px; + left: 327px; + .progressVedio { + width: 285px; + height: 11px; + background-color: #fff; + :global { + .vjs-text-track-display { + background-color: #fff !important; + } + .vjs-poster { + top: 1px !important; + left: 1px !important; + background-position: 0 0 !important; + background-size: 100% !important; + } + .vjs-modal-dialog { + background: #fff !important; + } + .vjs-error-display:before { + content: '' !important; + } + } + } + .progressCover { + position: absolute; + top: 2.5px; + right: 2px; + height: 5.5px; + background: #fff; + border-radius: 0 5px 5px 0; + } + } + + .spaceman { + position: absolute; + top: 25px; + left: 310px; + .spacemanAnimate { + width: 320px; + } + } + .database { + position: absolute; + top: 20px; + right: 190px; + .sqlAnimate { + width: 150px; + } + } +} + +.deploymentName { + position: absolute; + bottom: 40px; + left: 50%; + color: @greyTextColor; + font-size: 12px; + transform: translateX(-50%); +} + +.exitPage { + height: 680px; + margin-top: 32px; + padding-top: 160px; + text-align: center; + border: none; + .exitPageText { + font-size: 18px !important; + } +} + +.commandTooltip { + :global { + .ant-tooltip-inner { + width: 400px; + } + } +} + +:global { + .english-container { + } +} diff --git a/web/src/pages/OcpInstaller/Configuration/index.tsx b/web/src/pages/OcpInstaller/Configuration/index.tsx new file mode 100644 index 0000000..ad90824 --- /dev/null +++ b/web/src/pages/OcpInstaller/Configuration/index.tsx @@ -0,0 +1,114 @@ +import React, { useState, useEffect } from 'react'; +import { useModel } from 'umi'; +import { PageContainer } from '@oceanbase/ui'; +import { useRequest } from 'ahooks'; +import { errorHandler } from '@/utils'; +import * as OCP from '@/services/ocp_installer_backend/OCP'; +import { + METADB_OCP_INSTALL, + STEPS_KEYS_INSTALL, +} from '@/constant/configuration'; +import Steps from '@/component/Steps'; +import DeployConfig from '@/component/DeployConfig'; +import ConnectConfig from '@/component/ConnectConfig'; +import OCPConfigNew from '@/component/OCPConfigNew'; +import OCPPreCheck from '@/component/OCPPreCheck'; +import InstallProcessNew from '@/component/InstallProcessNew'; +import InstallResult from '@/component/InstallResult'; + +const Configuration: React.FC = () => { + const [current, setCurrent] = useState(1); + const { + connectId, + installTaskId, + installStatus, + setInstallStatus, + installResult, + } = useModel('ocpInstallData'); + + // 获取ocp 信息 + const { data: ocpInfoData, run: getInstalledOcpInfo } = useRequest( + OCP.getInstalledOcpInfo, + { + manual: true, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }, + ); + + const ocpInfo = ocpInfoData?.data || {}; + + useEffect(() => { + if ( + current == 6 && + installStatus === 'FINISHED' && + installResult === 'SUCCESSFUL' + ) { + getInstalledOcpInfo({ + id: connectId, + }); + } + }, [current, installStatus, installResult]); + + return ( + + + +
    + {current === 1 && ( + + )} + + {current === 2 && ( + + )} + + {current === 3 && ( + + )} + + {current === 4 && ( + + )} + + {current === 5 && ( + + )} + + {current === 6 && ( + + )} +
    +
    + ); +}; + +export default Configuration; diff --git a/web/src/pages/OcpInstaller/Error/403.tsx b/web/src/pages/OcpInstaller/Error/403.tsx new file mode 100644 index 0000000..8ce8ade --- /dev/null +++ b/web/src/pages/OcpInstaller/Error/403.tsx @@ -0,0 +1,28 @@ +import { history } from 'umi'; +import { intl } from '@/utils/intl'; +import React from 'react'; +import AobException from '@/component/AobException'; + +export default () => { + return ( + { + history.push(`/`); + }} + style={{ + paddingTop: 50, + height: '100%', + }} + /> + ); +}; diff --git a/web/src/pages/OcpInstaller/Error/404.tsx b/web/src/pages/OcpInstaller/Error/404.tsx new file mode 100644 index 0000000..af1fb0e --- /dev/null +++ b/web/src/pages/OcpInstaller/Error/404.tsx @@ -0,0 +1,27 @@ +import { intl, history } from 'umi'; +import React from 'react'; +import AobException from '@/component/AobException'; + +export default () => { + return ( + { + history.push(`/`); + }} + style={{ + paddingTop: 50, + height: '100%', + }} + /> + ); +}; diff --git a/web/src/pages/OcpInstaller/Index/index.less b/web/src/pages/OcpInstaller/Index/index.less new file mode 100644 index 0000000..352664a --- /dev/null +++ b/web/src/pages/OcpInstaller/Index/index.less @@ -0,0 +1,142 @@ +@import '~@oceanbase/design/es/theme/index.less'; + +.container { + padding-bottom: 24px; +} + +@media (max-width: 1441px) and (max-height: 676px) { + .introduce { + position: absolute; + bottom: 24px; + } +} + +@media (min-width: 1441px) and (min-height: 676px) { + .introduce { + position: absolute; + bottom: 25%; + } +} + +.container, +.updateContainer { + width: 100vw; + height: calc(100vh - 48px); + min-height: 700px; + font-family: PingFangSC; + + .upgrade { + display: flex; + flex-direction: column; + justify-content: center; + height: 100%; + padding-left: 151px; + background-image: url('/assets/welcome/banner.png'); + background-repeat: no-repeat; + background-position-x: right; + background-position-y: bottom; + background-size: contain; + } + .title { + position: absolute; + top: 98px; + left: 144px; + height: 48px; + color: #fff; + font-weight: 500; + font-size: 28px; + line-height: 24px; + letter-spacing: 0; + } + .descriptions { + height: 24px; + margin: 12px 0; + color: #fff; + font-weight: 300; + font-size: 14px; + line-height: 24px; + letter-spacing: 0; + text-align: left; + opacity: 0.65; + } + .version { + // width: 120px; + height: 26px; + color: #fff; + font-weight: 400; + font-size: 16px; + font-family: PingFangSC; + line-height: 26px; + } + .startBtn { + width: 240px; + height: 50px; + margin-top: 24px; + // background-color: #0000ff; + border-radius: @borderRadius; + } + .introduce { + margin-top: 100px; + color: #fff; + .featureName { + display: flex; + font-weight: 600; + font-size: 16px; + opacity: 0.85; + .icon { + display: inline-block; + width: 20px; + height: 36px; + margin-right: 12px; + background: url('/assets/welcome/checkbox.svg') no-repeat; + } + .description { + width: 440px; + margin-top: 5px; + font-size: 12px; + line-height: 22px; + opacity: 0.65; + } + } + } + + .content { + position: relative; + z-index: 10; + width: 100vw; + height: calc(100% - 148px); + min-height: 650px; + padding: 24px 151px; + background-color: rgba(245, 248, 254, 1); + .intallType { + border: 2px solid #e2e8f3; + border-radius: 8px; + :global { + .ant-result-title { + font-weight: 500; + font-size: 18px; + line-height: 22px; + } + } + :global { + .ant-result-subtitle { + font-size: 14px; + line-height: 22px; + font-weight: 400; + } + } + + &:hover, + &.selected { + color: #006aff !important; + border: 2px solid #006aff; + :global { + .ant-result-title, + .ant-result-subtitle { + color: #006aff !important; + } + } + } + } + } +} diff --git a/web/src/pages/OcpInstaller/Index/index.tsx b/web/src/pages/OcpInstaller/Index/index.tsx new file mode 100644 index 0000000..b7e550b --- /dev/null +++ b/web/src/pages/OcpInstaller/Index/index.tsx @@ -0,0 +1,332 @@ +import { intl } from '@/utils/intl'; +import React, { useState } from 'react'; +import { history } from 'umi'; +import { Button, Card, Result, Tag, Col, Row } from '@oceanbase/design'; +import { Alert } from 'antd'; +import { useRequest, useUpdateEffect } from 'ahooks'; +import { errorHandler } from '@/utils'; +import * as Process from '@/services/ocp_installer_backend/Process'; +import Banner from '@/component/Banner'; +import CustomFooter from '@/component/CustomFooter'; +import ExitBtn from '@/component/ExitBtn'; +import styles from './index.less'; + +export interface IndexProps { + location: { + query: { type: string }; + }; +} + +type ConfigMethodType = 'ocpInstaller/configuration' | 'ocpInstaller/install'; +type InstallIconType = + | '/assets/welcome/new-db-selected.svg' + | '/assets/welcome/new-db-unselected.svg'; +type ConfigurationIconType = + | '/assets/welcome/old-db-selected.svg' + | '/assets/welcome/old-db-unselected.svg'; +//创建新的数据库——》install +//使用已有的 ——》configuration +const Index: React.FC = ({ + location: { + query: { type }, + }, +}) => { + let isUpdate, isHaveMetadb; + const [configMethod, setConfigMethod] = useState( + 'ocpInstaller/install', + ); + const [installIcon, setInstallIcon] = useState( + '/assets/welcome/new-db-selected.svg', + ); + const [configurationIcon, setConfigurationIcon] = + useState('/assets/welcome/old-db-unselected.svg'); + // useEffect(() => { + // dispatch({ + // type: 'global/update', + // payload: { + // isUpdate: type === 'upgrade', + // }, + // }); + // }, [type]); + // 退出 + const { run: suicide, loading: suicideLoading } = useRequest( + Process.suicide, + { + manual: true, + onSuccess: (res) => { + if (res?.success) { + // dispatch({ + // type: 'global/update', + // payload: { + // installStatus: '', + // installResult: '', + // }, + // }); + history.push(`/quit`); + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }, + ); + + const features = [ + { + name: intl.formatMessage({ + id: 'OBD.OcpInstaller.Index.LifecycleManagementOM', + defaultMessage: '全生命周期管理(运维管控)', + }), + description: intl.formatMessage({ + id: 'OBD.OcpInstaller.Index.OcpImplementsUnifiedManagementOf', + defaultMessage: + 'OCP 实现对 OceanBase 资源的统一管理,实现了对资源的创建、备份恢复、监控告警、巡检、自治、升级、删除等全生命周期管理。', + }), + }, + { + name: intl.formatMessage({ + id: 'OBD.OcpInstaller.Index.MonitoringAlarm', + defaultMessage: '监控告警', + }), + description: intl.formatMessage({ + id: 'OBD.OcpInstaller.Index.OcpMonitorsOceanbaseFromDifferent', + defaultMessage: + 'OCP 支持从主机、集群、租户等不同维度对 OceanBase 进行监控,并且提供包括钉钉、微信、邮件等多种不同的告警方式,保障集群安全 。', + }), + }, + { + name: intl.formatMessage({ + id: 'OBD.OcpInstaller.Index.BackupAndRecovery', + defaultMessage: '备份恢复', + }), + description: intl.formatMessage({ + id: 'OBD.OcpInstaller.Index.OcpProvidesBackupAndRecovery', + defaultMessage: + 'OCP 提供对 OceanBase 集群、租户的备份恢复能力,支持自动将全量、增量、日志备份到NAS、OSS等存储类型,支持一键恢复操作。', + }), + }, + // 自动的判断商业版还是社区版改起来比较多。我们这次先直接下掉 + // 商业版特有 + // { + // name: '容灾管理', + // description: + // 'OCP 支持自动化部署主备集群,实现对业务的容灾保护,支持主备集群解藕、主备切换演练,容灾应急切换等运维能力对集群进行管理。', + // }, + { + name: intl.formatMessage({ + id: 'OBD.OcpInstaller.Index.DiagnosticOptimization', + defaultMessage: '诊断优化', + }), + description: intl.formatMessage({ + id: 'OBD.OcpInstaller.Index.OcpProvidesClosedLoopDiagnostics', + defaultMessage: + 'OCP 针对 SQL 提供从感知、根因分析、执行建议的闭环诊断能力。OCP 同时还实现了从集群复制、会话、死锁、容量等维度的诊断能力。', + }), + }, + // 商业版特有 + // { + // name: '自治服务', + // description: + // 'OCP 将多年的 OceanBase 集群的专家经验沉淀为产品功能,提供从事件感知、根因分析、自治自愈到告警通知、应急处理的全链路自治能力。', + // }, + ]; + + const mouseLeaveInstall = () => { + if (configMethod !== 'ocpInstaller/install') { + setInstallIcon('/assets/welcome/new-db-unselected.svg'); + } + }; + + const mouseLeaveConfiguration = () => { + if (configMethod !== 'ocpInstaller/configuration') { + setConfigurationIcon('/assets/welcome/old-db-unselected.svg'); + } + }; + + useUpdateEffect(() => { + if (configMethod === 'ocpInstaller/install') { + setInstallIcon('/assets/welcome/new-db-selected.svg'); + setConfigurationIcon('/assets/welcome/old-db-unselected.svg'); + } else { + setConfigurationIcon('/assets/welcome/old-db-selected.svg'); + setInstallIcon('/assets/welcome/new-db-unselected.svg'); + } + }, [configMethod]); + + return ( +
    + {isUpdate ? ( +
    +
    +
    + {intl.formatMessage({ + id: 'OBD.OcpInstaller.Index.WelcomeToTheOcpUpgrade', + defaultMessage: '欢迎使用 OCP 升级向导', + })} +
    +
    + OceanBase Cloud Platfrom upgrade wizard +
    + +
    +
    + ) : ( +
    + +
    + + + + +
    +
    setConfigMethod('ocpInstaller/install')} + onMouseEnter={() => + setInstallIcon('/assets/welcome/new-db-selected.svg') + } + onMouseLeave={mouseLeaveInstall} + > + } + status="success" + title={intl.formatMessage({ + id: 'OBD.OcpInstaller.Index.CreateANewOceanbaseDatabase', + defaultMessage: '创建全新的 OceanBase 数据库', + })} + subTitle={intl.formatMessage({ + id: 'OBD.OcpInstaller.Index.MetadbAsOcp', + defaultMessage: '作为 OCP 的 MetaDB', + })} + extra={[ + + {intl.formatMessage({ + id: 'OBD.OcpInstaller.Index.Recommend', + defaultMessage: '推荐', + })} + , + ]} + /> +
    + + +
    + setConfigMethod('ocpInstaller/configuration') + } + onMouseEnter={() => + setConfigurationIcon( + '/assets/welcome/old-db-selected.svg', + ) + } + onMouseLeave={mouseLeaveConfiguration} + > + } + status="success" + title={intl.formatMessage({ + id: 'OBD.OcpInstaller.Index.UseAnExistingOceanbaseDatabase', + defaultMessage: '使用已有的 OceanBase 数据库', + })} + subTitle={intl.formatMessage({ + id: 'OBD.OcpInstaller.Index.MetadbAsOcp', + defaultMessage: '作为 OCP 的 MetaDB', + })} + extra={[ +
    , + ]} + /> +
    + + + +
    + + + + + + + )} + + ); +}; + +export default Index; diff --git a/web/src/pages/OcpInstaller/Install/Component/MetadbDeployResult.tsx b/web/src/pages/OcpInstaller/Install/Component/MetadbDeployResult.tsx new file mode 100644 index 0000000..e69de29 diff --git a/web/src/pages/OcpInstaller/Install/Component/ModifyResourcePoolModal/index.less b/web/src/pages/OcpInstaller/Install/Component/ModifyResourcePoolModal/index.less new file mode 100644 index 0000000..97ac794 --- /dev/null +++ b/web/src/pages/OcpInstaller/Install/Component/ModifyResourcePoolModal/index.less @@ -0,0 +1,11 @@ +.resorcePollModal { + height: 600px; + overflow: hidden; + :global { + .ant-form-item-label > label { + display: inline-block; + justify-content: space-between !important; + width: 100%; + } + } +} diff --git a/web/src/pages/OcpInstaller/Install/Component/ModifyResourcePoolModal/index.tsx b/web/src/pages/OcpInstaller/Install/Component/ModifyResourcePoolModal/index.tsx new file mode 100644 index 0000000..109a461 --- /dev/null +++ b/web/src/pages/OcpInstaller/Install/Component/ModifyResourcePoolModal/index.tsx @@ -0,0 +1,476 @@ +import { intl } from '@/utils/intl'; +import { + Col, + Descriptions, + Form, + Modal, + Row, + Card, + message, +} from '@oceanbase/design'; +import React, { useEffect, useState } from 'react'; +import { ExclamationCircleFilled } from '@ant-design/icons'; +// import { Pie } from '@alipay/ob-charts'; +import { minBy, find } from 'lodash'; +import { useRequest } from 'ahooks'; +import { Alert } from 'antd'; +import { errorHandler } from '@/utils'; +import * as Metadb from '@/services/ocp_installer_backend/Metadb'; +import SliderAndInputNumber from '@/component/SliderAndInputNumber'; +import { findBy } from '@oceanbase/util'; +import styles from './index.less'; + +export interface ModifyResourcePoolModalProps { + createMetadbDeployment: (params) => void; + currentMetadbDeploymentConfig?: any; + createMetadbData?: any; + loading?: boolean; + visible?: boolean; + id: number; +} + +const ModifyResourcePoolModal: React.FC = ({ + currentMetadbDeploymentConfig, + createMetadbDeployment, + createMetadbData, + visible, + loading, + id, + ...restProps +}) => { + const [form] = Form.useForm(); + const { validateFields, setFieldsValue, getFieldValue } = form; + + // 剩余空间 + const [dataDirFreeSize, setDataDirFreeSize] = useState(0); + const [logDirFreeSize, setLogDirFreeSize] = useState(0); + + const [maxDataDirDisk, setMaxDataDirDisk] = useState(0); + const [maxLogSize, setMaxLogSize] = useState(0); + + const [memoryLimitSize, setMemoryLimitSize] = useState(1); + const [dataFileSize, setDataFileSize] = useState(1); + const [logDiskSize, setLogDiskSize] = useState(1); + + const [minMetadbResource, setMinMetadbResource] = + useState(); + + const [commonTenantReserve, setCommonTenantReserve] = useState(0); + + // 查询主机的资源 + const { + data: metadbDeploymentResourceData, + run: getMetadbDeploymentResource, + } = useRequest(Metadb.getMetadbDeploymentResource, { + manual: true, + onSuccess: (res) => { + if (res.success) { + const metadbDeploymentResource = res?.data || {}; + if (metadbDeploymentResource?.items?.length === 0) { + return message.warning( + intl.formatMessage({ + id: 'OBD.Component.ModifyResourcePoolModal.NoResourcesFound', + defaultMessage: '未查询到资源', + }), + ); + } + + const currentMinMetadbResource: API.ObserverResource = minBy( + res?.data?.items, + (item) => item?.memory_limit_higher_limit, + ); + // 如果用户如有上次的手动输入,需要采用用户输入 + if (currentMetadbDeploymentConfig?.id) { + const { parameters } = currentMetadbDeploymentConfig?.config; + setFieldsValue({ + memory_limit: find( + parameters, + (item) => item?.name === 'memory_limit', + )?.value?.split('G')[0], + datafile_size: find( + parameters, + (item) => item?.name === 'datafile_size', + )?.value?.split('G')[0], + log_disk_size: find( + parameters, + (item) => item?.name === 'log_disk_size', + )?.value?.split('G')[0], + }); + } else { + setFieldsValue({ + memory_limit: currentMinMetadbResource?.memory_limit_default, + datafile_size: currentMinMetadbResource?.memory_limit_default * 3, + log_disk_size: currentMinMetadbResource?.memory_limit_default * 3, + }); + } + + setMemoryLimitSize(currentMinMetadbResource?.memory_limit_default); + setMinMetadbResource(currentMinMetadbResource); + + const memoryLimitSizeMax = + currentMinMetadbResource?.memory_limit_higher_limit - + Math.ceil(currentMinMetadbResource?.memory_limit_higher_limit * 0.1) - + Math.floor(currentMinMetadbResource?.memory_limit_higher_limit * 0.1); + + setCommonTenantReserve( + memoryLimitSizeMax - currentMinMetadbResource?.memory_limit_default, + ); + + const { config } = createMetadbData; + const data_dir = config?.data_dir || 'data/1'; + const log_dir = config?.log_dir || 'data/log'; + + // 根据对应路径找到对应盘 取出相应盘的剩余空间 + const data_dir_disk = findBy( + currentMinMetadbResource?.disk || [], + 'path', + data_dir, + ); + const log_dir_disk = findBy( + currentMinMetadbResource?.disk || [], + 'path', + log_dir, + ); + + const dataDirDiskInfoFreeSize = Number( + data_dir_disk?.disk_info?.free_size, + ); + const logDirDiskInfoFreeSize = Number( + log_dir_disk?.disk_info?.free_size, + ); + + setDataDirFreeSize(dataDirDiskInfoFreeSize); + setLogDirFreeSize(logDirDiskInfoFreeSize); + + setLimit( + dataDirDiskInfoFreeSize, + logDirDiskInfoFreeSize, + currentMinMetadbResource?.data_size_default, + currentMinMetadbResource?.log_size_default, + ); + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }); + + const metadbResource = metadbDeploymentResourceData?.data || {}; + + const setLimit = ( + dataDirDiskInfoFreeSize: number, + logDirDiskInfoFreeSize: number, + currentDataSize: number, + currentLogSize: number, + ) => { + let data_size_limit = 0; + let log_size_limit = 0; + + switch ( + minBy(metadbResource?.items, (item) => item?.memory_limit_higher_limit) + ?.flag + ) { + case 1: + data_size_limit = dataDirDiskInfoFreeSize - 2 - currentLogSize; + log_size_limit = dataDirDiskInfoFreeSize - 2 - currentDataSize; + break; + case 2: + data_size_limit = dataDirDiskInfoFreeSize - currentLogSize; + log_size_limit = dataDirDiskInfoFreeSize - currentDataSize; + break; + case 3: + data_size_limit = dataDirDiskInfoFreeSize - 2; + log_size_limit = dataDirDiskInfoFreeSize - 2; + break; + case 4: + data_size_limit = dataDirDiskInfoFreeSize * 0.9; + log_size_limit = logDirDiskInfoFreeSize * 0.9; + break; + default: + break; + } + + setMaxDataDirDisk(data_size_limit); + setMaxLogSize(log_size_limit); + }; + + useEffect(() => { + if (id && visible) { + getMetadbDeploymentResource({ id }); + } + }, [id, visible]); + + const handleSubmit = () => { + validateFields().then((values) => { + const { datafile_size, log_disk_size } = values; + + if (createMetadbDeployment) { + createMetadbDeployment({ + parameters: [ + { + name: 'memory_limit', + value: `${values?.memory_limit || memoryLimitSize}G`, + }, + { + name: 'datafile_size', + value: `${datafile_size}G`, + }, + { + name: 'log_disk_size', + value: `${log_disk_size}G`, + }, + ], + }); + } + }); + }; + + const memoryFreeGB = minMetadbResource?.memory_limit_higher_limit; + + const resourceList = [ + { + type: intl.formatMessage({ + id: 'OBD.Component.ModifyResourcePoolModal.SystemPreOccupation', + defaultMessage: '系统预占用', + }), + value: Math.ceil(memoryFreeGB * 0.1), + }, + { + type: 'memory_limit', + value: memoryLimitSize, + }, + { + type: intl.formatMessage({ + id: 'OBD.Component.ModifyResourcePoolModal.OcpServiceReservation', + defaultMessage: 'OCP 服务预留', + }), + value: Math.floor(memoryFreeGB * 0.1), + }, + { + type: intl.formatMessage({ + id: 'OBD.Component.ModifyResourcePoolModal.CommonTenantReservation', + defaultMessage: '普通租户预留', + }), + value: commonTenantReserve, + }, + ]; + + const memoryLimitSizeMax = + minMetadbResource?.memory_limit_higher_limit - + Math.ceil(memoryFreeGB * 0.1) - + Math.floor(memoryFreeGB * 0.1); + const config1 = { + data: resourceList, + angleField: 'value', + colorField: 'type', + innerRadius: 0.8, + isDonut: true, + lineWidth: 20, + label: false, + style: { + textAlign: 'center', + fontSize: 14, + }, + }; + + return ( + + + +
    + +
    + + {/* 内存分配图(GiB)} + style={{ marginBottom: 24 }} + > + + + + */} + + // } + name="memory_limit" + initialValue={minMetadbResource?.memory_limit_default} + // validateStatus={memoryLimitSizeMax < minMetadbResource?.memory_limit_default ? "warning" : ''} + > + 12 + ? minMetadbResource?.memory_limit_lower_limit + : 12 + } + // value={minMetadbResource?.memory_limit_default} + max={memoryLimitSizeMax} + onChange={(val) => { + setMemoryLimitSize(val); + setCommonTenantReserve(memoryLimitSizeMax - val); + setFieldsValue({ + datafile_size: val * 3, + log_disk_size: val * 3, + }); + }} + /> + + + + + + + + {intl.formatMessage({ + id: 'OBD.Component.ModifyResourcePoolModal.DataFile', + defaultMessage: '数据文件', + })} + + {maxDataDirDisk < getFieldValue('memory_limit') * 3 && ( +
    + {' '} + {intl.formatMessage({ + id: 'OBD.Component.ModifyResourcePoolModal.TheDataFileSpaceIs', + defaultMessage: + '数据文件空间不足,数据文件大小默认为 memory_limit 的 3 倍', + })} +
    + )} + + } + name="datafile_size" + initialValue={getFieldValue('memory_limit') * 3} + validateStatus={ + maxDataDirDisk < getFieldValue('memory_limit') * 3 + ? 'warning' + : '' + } + > + { + setDataFileSize(val); + setLimit(dataDirFreeSize, logDirFreeSize, val, logDiskSize); + }} + /> +
    +
    + + + + + + {intl.formatMessage({ + id: 'OBD.Component.ModifyResourcePoolModal.LogFile', + defaultMessage: '日志文件', + })} + + {maxLogSize < getFieldValue('memory_limit') * 3 ? ( +
    + + {intl.formatMessage({ + id: 'OBD.Component.ModifyResourcePoolModal.TheLogFileHasInsufficient', + defaultMessage: + '日志文件空间不足,日志文件大小默认为 memory_limit 的 3 倍', + })} +
    + ) : null} + + } + name="log_disk_size" + initialValue={getFieldValue('memory_limit') * 3} + validateStatus={ + maxLogSize < getFieldValue('memory_limit') * 3 + ? 'warning' + : '' + } + > + { + setLogDiskSize(val); + setLimit( + dataDirFreeSize, + logDirFreeSize, + dataFileSize, + val, + ); + }} + /> +
    +
    + + + + + ); +}; + +export default ModifyResourcePoolModal; diff --git a/web/src/pages/OcpInstaller/Install/Component/SystemConfig.tsx b/web/src/pages/OcpInstaller/Install/Component/SystemConfig.tsx new file mode 100644 index 0000000..71e1ba5 --- /dev/null +++ b/web/src/pages/OcpInstaller/Install/Component/SystemConfig.tsx @@ -0,0 +1,625 @@ +import { intl } from '@/utils/intl'; +import React, { useEffect, useState } from 'react'; +import { + Card, + Form, + Input, + Row, + Col, + Space, + Radio, + InputNumber, +} from '@oceanbase/design'; +import { InfoCircleOutlined } from '@ant-design/icons'; +import { some } from 'lodash'; +import Password from '@/component/Password'; +import MyInput from '@/component/MyInput'; +import MySelect from '@/component/MySelect'; +import { + SMLL_FORM_ITEM_LAYOUT, + PASSWORD_REGEX, + SELECT_TOKEN_SPEARATORS, +} from '@/constant'; +import { validatePassword } from '@/utils'; +// import tracert from '@/util/tracert'; +import validator from 'validator'; + +export interface SystemConfigProps { + form: any; + step?: number; + userInfo?: any; + currentMetadbDeploymentConfig?: any; + checkHomePathcheckStatus?: boolean; + checkDataDircheckStatus?: boolean; + checkLogDircheckStatus?: boolean; + checkMachineResult?: API.ResourceCheckResult[]; + onChangeHomePath: () => void; + onChangeDataDir: () => void; + onChangeLogDir: () => void; +} + +const SystemConfig: React.FC = ({ + form, + step, + userInfo, + onChangeHomePath, + onChangeDataDir, + onChangeLogDir, + checkMachineResult, + checkHomePathcheckStatus, + checkDataDircheckStatus, + checkLogDircheckStatus, + currentMetadbDeploymentConfig, +}) => { + const { getFieldValue, setFieldsValue } = form; + + // 密码校验是否通过 + const [passed, setPassed] = useState(true); + const [devnameType, setDevnameType] = useState('AUTO'); + + const [homePathcheckResult, setHomePathcheckResult] = useState(true); + const [dataDircheckResult, setDataDircheckResult] = useState(true); + const [logDircheckResult, setLogDircheckResult] = useState(true); + + useEffect(() => { + if (checkMachineResult && checkMachineResult?.length > 0) { + setHomePathcheckResult(checkMachineResult[0] || true); + setDataDircheckResult(checkMachineResult[1]); + setLogDircheckResult(checkMachineResult[2]); + } + }, [checkMachineResult, checkMachineResult?.length]); + + useEffect(() => { + if (userInfo?.username) { + setFieldsValue({ + user: userInfo?.username, + home_path: `/home/${userInfo?.username || 'root'}`, + }); + } + if (currentMetadbDeploymentConfig?.id) { + const { + auth, + cluster_name, + servers, + // root_password, + home_path, + data_dir, + log_dir, + sql_port, + rpc_port, + devname, + } = currentMetadbDeploymentConfig?.config; + setFieldsValue({ + servers, + user: auth?.user, + private_key: auth?.private_key, + username: auth?.username, + // password: auth?.password, + cluster_name, + // root_password, + home_path: home_path + ? home_path.split('/oceanbase')[0] + : `/home/${userInfo?.username || 'root'}`, + data_dir: data_dir ? data_dir : '/data/1', + log_dir: log_dir ? log_dir : '/data/log', + sql_port, + rpc_port, + devname, + }); + setDevnameType(devname || devname !== '' ? 'MANUAL' : 'AUTO'); + } + }, [currentMetadbDeploymentConfig?.id, step, userInfo?.username]); + + const validate = (rule, values: any[], callback) => { + if ( + values && + some( + values, + (item) => + // ipv4 地址 + !validator.isIP(item, '4'), + ) + ) { + callback( + intl.formatMessage({ + id: 'OBD.Install.Component.SystemConfig.InvalidIpAddress', + defaultMessage: 'IP 地址不合法', + }), + ); + + return; + } + callback(); + }; + + return ( +
    + +
    + + {intl.formatMessage({ + id: 'OBD.Install.Component.SystemConfig.SystemConfiguration', + defaultMessage: '系统配置', + })} + + + + {intl.formatMessage({ + id: 'OBD.Install.Component.SystemConfig.ToAvoidOperatingSystemUser', + defaultMessage: + '为了避免操作系统用户冲突,请为 MetaDB 及 OCP 配置独立的操作系统用户', + })} + + + } + > + + + + + + + + + + {intl.formatMessage({ + id: 'OBD.Install.Component.SystemConfig.IfYouHaveSetPassword', + defaultMessage: '如果您已设置免密,请忽略本选项', + })} + + } + > + + + + + + + + + + + { + setPassed(value); + }} + /> + + {homePathcheckResult?.error_message?.join(',')} + ) : null + } + > + { + onChangeHomePath(); + }} + /> + + {dataDircheckResult?.error_message?.join(',')} + ) : null + } + > + { + onChangeDataDir(); + }} + /> + + {logDircheckResult?.error_message?.join(',')} + ) : null + } + > + { + onChangeLogDir(); + }} + /> + + + + { + if (value == getFieldValue('rpc_port')) { + callback( + intl.formatMessage({ + id: 'OBD.Install.Component.SystemConfig.TheSqlPortCannotBe', + defaultMessage: 'SQL 端口不可与 RPC 端口相同', + }), + ); + } else { + callback(); + } + }, + }, + ]} + {...{ + labelCol: { + span: 24, + }, + + wrapperCol: { + span: 24, + }, + }} + > + + + + + + { + if (value == getFieldValue('sql_port')) { + callback( + intl.formatMessage({ + id: 'OBD.Install.Component.SystemConfig.TheRpcPortCannotBe', + defaultMessage: 'RPC 端口不可与 SQL 端口相同', + }), + ); + } else { + callback(); + } + }, + }, + ]} + {...{ + labelCol: { + span: 24, + }, + + wrapperCol: { + span: 24, + }, + }} + > + + + + + + + + { + setDevnameType(e.target.value); + }} + > + + {intl.formatMessage({ + id: 'OBD.Install.Component.SystemConfig.AutomaticConfiguration', + defaultMessage: '自动配置', + })} + + + {intl.formatMessage({ + id: 'OBD.Install.Component.SystemConfig.ManualConfiguration', + defaultMessage: '手动配置', + })} + + + + + {devnameType === 'MANUAL' && ( + + + + + + )} + + + + + + ); +}; + +export default SystemConfig; diff --git a/web/src/pages/OcpInstaller/Install/index.less b/web/src/pages/OcpInstaller/Install/index.less new file mode 100644 index 0000000..0d20647 --- /dev/null +++ b/web/src/pages/OcpInstaller/Install/index.less @@ -0,0 +1,9 @@ + +.sideTip { + padding: 16px 24px; + font-size: 14px; + color: #5C6B8A; + line-height: 24px; + background-color: #F8FAFE; + border-radius: 8px; +} \ No newline at end of file diff --git a/web/src/pages/OcpInstaller/Install/index.tsx b/web/src/pages/OcpInstaller/Install/index.tsx new file mode 100644 index 0000000..000cbb8 --- /dev/null +++ b/web/src/pages/OcpInstaller/Install/index.tsx @@ -0,0 +1,141 @@ +import { intl } from '@/utils/intl'; +import { useModel } from 'umi'; +import React, { useState, useEffect } from 'react'; +import { Alert } from 'antd'; +import { PageContainer } from '@oceanbase/ui'; + +import { useRequest } from 'ahooks'; +import { errorHandler } from '@/utils'; +import * as OCP from '@/services/ocp_installer_backend/OCP'; +import { NEW_METADB_OCP_INSTALL } from '@/constant/configuration'; +import DeployConfig from '@/component/DeployConfig'; +import OCPPreCheck from '@/component/OCPPreCheck'; +import InstallProcessNew from '@/component/InstallProcessNew'; +import InstallResult from '@/component/InstallResult'; +import Steps from '@/component/Steps'; +import { STEPS_KEYS_INSTALL } from '@/constant/configuration'; +import MetaDBConfig from '@/component/MetaDBConfig'; +import OCPConfigNew from '@/component/OCPConfigNew'; + +export interface InstallProps { + location: { + query: { step: number; metadbId: number; ocpId: number }; + }; +} + +const Install: React.FC = ({ + location: { + query: { step, metadbId, ocpId }, + }, +}) => { + const [current, setCurrent] = useState(step ? Number(step) : 1); + + const { + connectId, + installTaskId, + installStatus, + setInstallStatus, + installResult, + } = useModel('ocpInstallData'); + + // 获取ocp 信息 + const { data: ocpInfoData, run: getInstalledOcpInfo } = useRequest( + OCP.getInstalledOcpInfo, + { + manual: true, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }, + ); + + const ocpInfo = ocpInfoData?.data || {}; + + useEffect(() => { + if ( + current == 6 && + installStatus === 'FINISHED' && + installResult === 'SUCCESSFUL' + ) { + getInstalledOcpInfo({ + id: connectId, + }); + } + }, [current, installStatus, installResult]); + return ( + + + +
    + {current === 1 || + (current === 2 && ( + + ))} + + {current === 1 && ( + + )} + + {current === 2 && ( + + )} + + {current === 3 && ( + + )} + + {current === 4 && ( + + )} + + {current === 5 && ( + + )} + + {current === 6 && ( + + )} +
    +
    + ); +}; + +export default Install; diff --git a/web/src/pages/OcpInstaller/Layout/BasicLayout/index.less b/web/src/pages/OcpInstaller/Layout/BasicLayout/index.less new file mode 100644 index 0000000..f95bdf3 --- /dev/null +++ b/web/src/pages/OcpInstaller/Layout/BasicLayout/index.less @@ -0,0 +1,10 @@ +.container { + .action { + color: #5c6b8a; + } + :global { + .ob-layout-header .ob-layout-header-extra > .ob-layout-header-extra-item { + margin-right: 24px; + } + } +} diff --git a/web/src/pages/OcpInstaller/Layout/BasicLayout/index.tsx b/web/src/pages/OcpInstaller/Layout/BasicLayout/index.tsx new file mode 100644 index 0000000..1bf5ad5 --- /dev/null +++ b/web/src/pages/OcpInstaller/Layout/BasicLayout/index.tsx @@ -0,0 +1,88 @@ +import { intl } from '@/utils/intl'; +import React from 'react'; +import { HomeOutlined, ReadOutlined } from '@ant-design/icons'; +import { Space } from '@oceanbase/design'; +import { BasicLayout as OBUIBasicLayout } from '@oceanbase/ui'; +import type { BasicLayoutProps as OBUIBasicLayoutProps } from '@oceanbase/ui/es/BasicLayout'; +import styles from './index.less'; + +interface BasicLayoutProps extends OBUIBasicLayoutProps { + children: React.ReactNode; + location: { + pathname: string; + }; +} + +const BasicLayout: React.FC = (props) => { + // const { isUpdate } = useSelector((state: DefaultRootState) => state.global); + const isUpdate = false; + // 全局菜单 + const { location, children, ...restProps } = props; + + const simpleLogoUrl = '/assets/logo/logo.png'; + + return ( + + + + + {intl.formatMessage({ + id: 'OBD.Layout.BasicLayout.VisitTheOfficialWebsite', + defaultMessage: '访问官网', + })} + + + + + + {intl.formatMessage({ + id: 'OBD.Layout.BasicLayout.HelpCenter', + defaultMessage: '帮助中心', + })} + + + + ), + + showLocale: false, + showHelp: false, + }} + > + {children} + + ); +}; + +export default BasicLayout; diff --git a/web/src/pages/OcpInstaller/Layout/BlankLayout/index.less b/web/src/pages/OcpInstaller/Layout/BlankLayout/index.less new file mode 100644 index 0000000..f390d14 --- /dev/null +++ b/web/src/pages/OcpInstaller/Layout/BlankLayout/index.less @@ -0,0 +1,15 @@ +.main { + min-width: 1280px; + height: 100%; + .layout { + min-height: 100%; + :global { + .ant-pro-page-container { + margin: 0 120px; + // width: 1040px; + margin: 0 auto; + overflow: auto; + } + } + } +} \ No newline at end of file diff --git a/web/src/pages/OcpInstaller/Layout/BlankLayout/index.tsx b/web/src/pages/OcpInstaller/Layout/BlankLayout/index.tsx new file mode 100644 index 0000000..dad1814 --- /dev/null +++ b/web/src/pages/OcpInstaller/Layout/BlankLayout/index.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { Layout } from '@oceanbase/design'; +import styles from './index.less'; + +const BlankLayout: React.FC = ({ children, ...restProps }) => ( +
    + {children} +
    +); + +export default BlankLayout; diff --git a/web/src/pages/OcpInstaller/Layout/index.tsx b/web/src/pages/OcpInstaller/Layout/index.tsx new file mode 100644 index 0000000..652d7a3 --- /dev/null +++ b/web/src/pages/OcpInstaller/Layout/index.tsx @@ -0,0 +1,42 @@ +import { getLocale, history } from 'umi'; +import { intl } from '@/utils/intl'; +import React, { useEffect } from 'react'; +import { theme, ConfigProvider } from '@oceanbase/design'; +import en_US from 'antd/es/locale/en_US'; +import zh_CN from 'antd/es/locale/zh_CN'; +import BlankLayout from './BlankLayout'; +import ErrorBoundary from '@/component/ErrorBoundary'; + +interface LayoutProps { + children: React.ReactNode; +} + +const Layout: React.FC = ({ children }) => { + const locale = getLocale(); + const antdLocaleMap = { + 'en-US': en_US, + 'zh-CN': zh_CN, + }; + + useEffect(() => { + // 设置标签页的 title + document.title = intl.formatMessage({ + id: 'OBD.OcpInstaller.Layout.OceanbaseCloudPlatform', + defaultMessage: 'OceanBase 云平台', + }); + }, []); + + return ( + + + {children} + + + ); +}; + +export default Layout; diff --git a/web/src/pages/OcpInstaller/Quit/index.less b/web/src/pages/OcpInstaller/Quit/index.less new file mode 100644 index 0000000..e45c7c4 --- /dev/null +++ b/web/src/pages/OcpInstaller/Quit/index.less @@ -0,0 +1,17 @@ +.container { + .quitDesc { + font-size: 18px; + line-height: 22px; + font-weight: 400; + color: #132039; + margin-top: 24px; + :global { + .ant-typography { + font-size: 18px; + margin-bottom: 0; + color: #006AFF; + } + } + } + +} \ No newline at end of file diff --git a/web/src/pages/OcpInstaller/Quit/index.tsx b/web/src/pages/OcpInstaller/Quit/index.tsx new file mode 100644 index 0000000..0c5959e --- /dev/null +++ b/web/src/pages/OcpInstaller/Quit/index.tsx @@ -0,0 +1,72 @@ +import { intl } from '@/utils/intl'; +import { history } from 'umi'; +import React, { useEffect } from 'react'; +import { Typography, Result, Space } from '@oceanbase/design'; +import { PageContainer } from '@oceanbase/ui'; + +import PageCard from '@/component/PageCard'; +import styles from './index.less'; +import { PathType } from '@/pages/type'; +import ExitPageWrapper from '@/component/ExitPageWrapper'; + +const { Paragraph } = Typography; + +export default function Quit() { + //@ts-ignore + const path = history.location.query.path as PathType | undefined; + + return ( + + + + } + title={ + path === 'update' + ? intl.formatMessage({ + id: 'OBD.OcpInstaller.Quit.TheUpgradeProgramHasExited', + defaultMessage: '升级程序已退出', + }) + : intl.formatMessage({ + id: 'OBD.OcpInstaller.Quit.TheDeploymentInstallerHasExited', + defaultMessage: '部署安装程序已经退出!', + }) + } + subTitle={ + + {path === 'update' + ? intl.formatMessage({ + id: 'OBD.OcpInstaller.Quit.TheUpgradeProgramHasQuit', + defaultMessage: + '升级程序已退出 如需再次启用升级程序,请在系统中执行', + }) + : intl.formatMessage({ + id: 'OBD.OcpInstaller.Quit.ToEnableTheDeploymentProgram', + defaultMessage: '如需再次启用部署程序,请在系统中执行', + })} + + + + {path === 'update' ? 'obd web upgrade' : 'obd web install'} + + + + } + /> + + + + ); +} diff --git a/web/src/pages/OcpInstaller/Update/Component/ConnectionInfo/index.less b/web/src/pages/OcpInstaller/Update/Component/ConnectionInfo/index.less new file mode 100644 index 0000000..48edd6c --- /dev/null +++ b/web/src/pages/OcpInstaller/Update/Component/ConnectionInfo/index.less @@ -0,0 +1,33 @@ +@cardBackgroundColor: #f8fafe; + +.componentTable { + :global { + .ant-table-thead > tr > th { + background-color: #f5f8fe !important; + } + } +} + +.componentCard { + margin-bottom: 16px !important; + background-color: @cardBackgroundColor !important; + :global { + .ant-pro-card-body { + padding: 0 !important; + } + } + &.disabledCard { + opacity: 0.4; + } + &:last-child { + margin-bottom: 0 !important; + } +} + +.cardContainer { + :global { + .ant-pro-card-header,.ant-pro-card-body{ + padding: 0; + } + } +} \ No newline at end of file diff --git a/web/src/pages/OcpInstaller/Update/Component/ConnectionInfo/index.tsx b/web/src/pages/OcpInstaller/Update/Component/ConnectionInfo/index.tsx new file mode 100644 index 0000000..ba4f931 --- /dev/null +++ b/web/src/pages/OcpInstaller/Update/Component/ConnectionInfo/index.tsx @@ -0,0 +1,449 @@ +import InputPort from '@/component/InputPort'; +import MyInput from '@/component/MyInput'; +import { FORM_ITEM_SMALL_LAYOUT } from '@/constant'; +import type { ConnectInfoType } from '@/models/ocpInstallData'; +import * as Metadb from '@/services/ocp_installer_backend/Metadb'; +import { intl } from '@/utils/intl'; +import { CheckCircleFilled, CloseCircleFilled } from '@ant-design/icons'; +import { ProCard } from '@ant-design/pro-components'; +import { Card, Form, Spin } from '@oceanbase/design'; +import { useRequest } from 'ahooks'; +import { Alert, Button, Table, Tag } from 'antd'; +import type { ColumnsType } from 'antd/es/table'; +import type { FormInstance } from 'antd/lib/form'; +import React from 'react'; +import { useModel } from 'umi'; +import styles from './index.less'; +export interface ConnectionInfoProps { + form: FormInstance; + loading?: boolean; + onSuccess?: () => void; + handleCheck: () => void; + systemUserForm: any; + checkConnectInfo?: 'unchecked' | 'fail' | 'success'; + checkStatus: 'unchecked' | 'fail' | 'success'; + setCheckStatus: React.Dispatch< + React.SetStateAction<'unchecked' | 'fail' | 'success'> + >; + + setCheckConnectInfo: React.Dispatch< + React.SetStateAction<'unchecked' | 'fail' | 'success'> + >; + + updateInfo: API.connectMetaDB | undefined; + upgraadeHosts?: Array; + allowInputUser: boolean; +} + +type DataType = { + name: string; + servers: string[]; +}; + +const commonWidthStyle = { width: 328 }; + +const ConnectionInfo: React.FC = ({ + form, + loading = false, + handleCheck, + checkConnectInfo, + systemUserForm, + checkStatus, + setCheckStatus, + setCheckConnectInfo, + updateInfo, + allowInputUser, +}) => { + const { setFieldsValue, getFieldsValue } = form; + const { ocpConfigData = {}, setOcpConfigData } = useModel('global'); + const { updateConnectInfo = {} } = ocpConfigData; + const columns: ColumnsType = [ + { + title: intl.formatMessage({ + id: 'OBD.Component.ConnectionInfo.ComponentName', + defaultMessage: '组件名称', + }), + dataIndex: 'name', + key: 'componentName', + width: 135, + }, + { + title: intl.formatMessage({ + id: 'OBD.Component.ConnectionInfo.NodeIp', + defaultMessage: '节点 IP', + }), + dataIndex: 'ip', + key: 'ip', + render: (_, record) => ( + <> + {_.length && + _.map((server: string, idx: number) => ( + + {server} + + ))} + + ), + }, + ]; + + const { run: checkOperatingUser, loading: checkUserLoading } = useRequest( + Metadb.checkOperatingUser, + { + manual: true, + onError: (e) => { + setCheckStatus('fail'); + }, + }, + ); + + const handleCheckSystemUser = () => { + systemUserForm.validateFields().then(async (values: any) => { + const { user, password, systemPort: port } = values; + const res = await checkOperatingUser({ + user, + password, + port, + servers: + updateInfo?.component.find( + (item: any) => + item.name === 'ocp-server' || item.name === 'ocp-server-ce', + ).ip || [], + }); + if (res.success) { + setCheckStatus('success'); + setOcpConfigData({ + ...ocpConfigData, + updateConnectInfo: { + ...ocpConfigData.updateConnectInfo, + ...values, + }, + }); + } else { + setCheckStatus('fail'); + } + }); + }; + const initialValues: ConnectInfoType = { + ...updateConnectInfo, + accessUser: updateConnectInfo.accessUser || 'root@sys', + }; + + const systemUserInitialValues = { + user: updateConnectInfo.user || undefined, + systemPort: updateConnectInfo.systemPort || 22, + password: updateConnectInfo.password || undefined, + }; + + return ( + + + + +
    + + setCheckConnectInfo('unchecked')} + /> + + + + + { + setCheckConnectInfo('unchecked'); + }} + style={commonWidthStyle} + placeholder={intl.formatMessage({ + id: 'OBD.Component.ConnectionInfo.EnterADatabaseName', + defaultMessage: '请输入数据库名', + })} + /> + + + + setCheckConnectInfo('unchecked')} + style={commonWidthStyle} + placeholder={intl.formatMessage({ + id: 'OBD.Component.ConnectionInfo.EnterAnAccount', + defaultMessage: '请输入账号', + })} + /> + + + { + setCheckConnectInfo('unchecked'); + }} + style={commonWidthStyle} + placeholder={intl.formatMessage({ + id: 'OBD.Component.ConnectionInfo.PleaseEnter', + defaultMessage: '请输入密码', + })} + /> + + + {checkConnectInfo === 'fail' && ( +
    + + {intl.formatMessage({ + id: 'OBD.Component.ConnectionInfo.TheCurrentVerificationFailedPlease', + defaultMessage: '当前验证失败,请重新填写错误参数', + })} +
    + )} + + {checkConnectInfo === 'success' && ( +
    + + {intl.formatMessage({ + id: 'OBD.Component.ConnectionInfo.TheVerificationIsSuccessfulPlease', + defaultMessage: '当前验证成功,请填写下方参数', + })} +
    + )} + + {checkConnectInfo === 'success' && updateInfo && ( +
    + +
    + + + + + setCheckStatus('unchecked')} + disabled={!allowInputUser} + style={commonWidthStyle} + /> + +

    + {intl.formatMessage({ + id: 'OBD.Component.ConnectionInfo.PleaseProvideTheUserName', + defaultMessage: + '请提供用户名用以自动化配置平台专用操作系统用户', + })} +

    + + +
    + + setCheckStatus('unchecked')} + placeholder={intl.formatMessage({ + id: 'OBD.Component.ConnectionInfo.IfYouHaveConfiguredPassword', + defaultMessage: '如已配置免密登录,则无需再次输入密码', + })} + style={commonWidthStyle} + /> + + +
    +
    + {checkStatus === 'success' && ( +
    + + + {intl.formatMessage({ + id: 'OBD.Component.ConnectionInfo.TheVerificationIsSuccessfulProceed', + defaultMessage: '当前验证成功,请进行下一步', + })} + +
    + )} + + {checkStatus === 'fail' && ( +
    + + + {intl.formatMessage({ + id: 'OBD.Component.ConnectionInfo.TheCurrentVerificationFailedPlease.1', + defaultMessage: '当前验证失败,请重新输入', + })} + +
    + )} +
    +
    + + + )} + + + ); +}; + +export default ConnectionInfo; diff --git a/web/src/pages/OcpInstaller/Update/Component/UpdatePreCheck/index.less b/web/src/pages/OcpInstaller/Update/Component/UpdatePreCheck/index.less new file mode 100644 index 0000000..e22f94a --- /dev/null +++ b/web/src/pages/OcpInstaller/Update/Component/UpdatePreCheck/index.less @@ -0,0 +1,62 @@ +@cardBackgroundColor: #f8fafe; +@subTitleColor: #5c6b8a; + +.ocpVersion { + float: left; + width: calc(50% - 66px); + padding: 21px 0; + color: #5c6b8a; + font-size: 16px; + text-align: center; + background-color: #ffffff; + border: 1px solid #cdd5e4; + border-radius: 8px; + span { + padding-right: 8px; + color: #132039; + font-weight: 500; + } +} +.infoSubCard { + overflow: hidden; + border-radius: 8px; + .pwdIcon { + position: absolute; + top: 2px; + right: 0; + color: #8592ad; + font-size: 17px; + } + :global { + .ant-pro-card .ant-pro-card-body { + padding-top: 4px !important; + } + + .ant-pro-card-body, + .ant-pro-card-header { + background-color: @cardBackgroundColor !important; + } + .ant-pro-card-title { + color: @subTitleColor !important ; + font-weight: normal !important; + font-size: 14px !important; + } + .ant-pro-card-body { + color: #132039 !important; + } + .ant-pro-card-col.ant-pro-card-split-vertical { + border-inline-end: none !important; + .ant-pro-card::before { + position: absolute; + top: 50%; + width: 1px; + height: 48px; + background-color: #e8eaf3; + transform: translateY(-50%); + transition: #e8eaf3 0.3s; + content: ''; + inset-inline-end: 0; + } + } + } +} \ No newline at end of file diff --git a/web/src/pages/OcpInstaller/Update/Component/UpdatePreCheck/index.tsx b/web/src/pages/OcpInstaller/Update/Component/UpdatePreCheck/index.tsx new file mode 100644 index 0000000..e4bfdb0 --- /dev/null +++ b/web/src/pages/OcpInstaller/Update/Component/UpdatePreCheck/index.tsx @@ -0,0 +1,373 @@ +import CheckBadge from '@/component/CheckBadge'; +import ArrowIcon from '@/component/Icon/ArrowIcon'; +import NewIcon from '@/component/Icon/NewIcon'; +import { DOCS_SOP } from '@/constant/docs'; +import { OCP_UPGRADE_STATUS_LIST } from '@/constant/index'; +import { intl } from '@/utils/intl'; +import { ProCard } from '@ant-design/pro-components'; +import { + Button, + Card, + Col, + Popconfirm, + Row, + Space, + Spin, + Table, + Tooltip, +} from '@oceanbase/design'; +import { Alert } from 'antd'; +import { find } from 'lodash'; +import React, { useEffect, useState } from 'react'; +import { useModel } from 'umi'; +import styles from './index.less'; + +export interface UpdatePreCheckProps { + refresh?: () => void; + updateInfo?: API.connectMetaDB; + ocpUpgradePrecheckTask?: any; + getOcpInfoLoading?: boolean; + precheckOcpUpgradeLoading?: boolean; + changePrecheckNoPassed?: (val: boolean) => void; + cluster_name: string; +} + +const UpdatePreCheck: React.FC = ({ + refresh, + updateInfo, + getOcpInfoLoading, + ocpUpgradePrecheckTask, + changePrecheckNoPassed, + precheckOcpUpgradeLoading, + cluster_name, +}) => { + const [ocpUpgradePrecheckResult, setOcpUpgradePrecheckResult] = useState( + ocpUpgradePrecheckTask?.precheck_result, + ); + const { ocpConfigData } = useModel('global'); + const version: string = ocpConfigData?.components?.ocpserver?.version; + const precheckOcpUpgradeStatus = ocpUpgradePrecheckTask?.task_info?.status; + + const precheckOcpUpgradeResultFaild = + ocpUpgradePrecheckTask?.precheck_result?.filter( + (item) => item.result === 'FAILED', + ); + + useEffect(() => { + setOcpUpgradePrecheckResult(ocpUpgradePrecheckTask?.precheck_result); + }, [ocpUpgradePrecheckTask]); + + const columns = [ + { + title: intl.formatMessage({ + id: 'OBD.Component.UpdatePreCheck.CheckItems', + defaultMessage: '检查项', + }), + dataIndex: 'name', + width: '30%', + }, + { + title: intl.formatMessage({ + id: 'OBD.Component.UpdatePreCheck.CheckStatus', + defaultMessage: '检查状态', + }), + dataIndex: 'result', + width: 120, + filters: OCP_UPGRADE_STATUS_LIST.map((item) => ({ + text: item.label, + value: item.value, + })), + onFilter: (value: string, record: API.PrecheckResult) => + record.result === value, + render: (text: string, record: API.PrecheckResult) => { + const statusItem = find( + OCP_UPGRADE_STATUS_LIST, + (item) => item.value === text, + ); + + return ( + + ); + }, + }, + { + title: intl.formatMessage({ + id: 'OBD.Component.UpdatePreCheck.Impact', + defaultMessage: '影响', + }), + dataIndex: 'advisement', + render: (text) => (text ? text : '-'), + }, + ]; + + return ( +
    + + {!ocpUpgradePrecheckTask ? ( + <> + + + +
    + + + {cluster_name} + + + {intl.formatMessage({ + id: 'OBD.Component.UpdatePreCheck.UpgradeAll', + defaultMessage: '全部升级', + })} + + + + + + + +
    + {intl.formatMessage({ + id: 'OBD.Component.UpdatePreCheck.PreUpgradeVersion', + defaultMessage: '升级前版本:', + })} + V {updateInfo?.ocp_version} +
    +
    + +
    +
    + {intl.formatMessage({ + id: 'OBD.Component.UpdatePreCheck.UpgradedVersion', + defaultMessage: '升级后版本:', + })} + + V {version} + +
    + + +
    +
    { + if (!ip || ip === '') { + return '-'; + } + return ip.map((item: string) => {item} ); + }, + }, + ]} + rowKey="name" + pagination={false} + dataSource={ + updateInfo?.component ? updateInfo?.component : [] + } + /> + + {updateInfo?.tips && ( +

    + {intl.formatMessage({ + id: 'OBD.Component.UpdatePreCheck.MetadbSharesMetaTenantResources', + defaultMessage: + 'MetaDB与MonitorDB共享Meta租户资源,容易造成OCP运行异常,强烈建议您新建Monitor租户,并进行MetaDB数据清理和MonitorDB数据迁移,详情请参考《', + })} + + SOP + + 》 +

    + )} + + + ) : ( + +
    +
    + + + {precheckOcpUpgradeResultFaild.length > 0 && ( + { + setOcpUpgradePrecheckResult( + ocpUpgradePrecheckResult?.map((item) => ({ + ...item, + result: + item?.result === 'FAILED' ? 'IGNORED' : item?.result, + })), + ); + if (changePrecheckNoPassed) { + changePrecheckNoPassed(false); + } + }} + > + + + )} + + + + + + + )} + + + ); +}; + +export default UpdatePreCheck; diff --git a/web/src/pages/OcpInstaller/Update/index.tsx b/web/src/pages/OcpInstaller/Update/index.tsx new file mode 100644 index 0000000..3b1edb7 --- /dev/null +++ b/web/src/pages/OcpInstaller/Update/index.tsx @@ -0,0 +1,536 @@ +import { intl } from '@/utils/intl'; +import React, { useState, useEffect } from 'react'; +import { history,useModel } from 'umi'; +import { Button, Form, Tooltip, Space,message } from '@oceanbase/design'; +import { PageContainer } from '@oceanbase/ui'; +import { useRequest } from 'ahooks'; +import { errorHandler } from '@/utils'; +import { find } from 'lodash'; +import * as Metadb from '@/services/ocp_installer_backend/Metadb'; +import * as OCP from '@/services/ocp_installer_backend/OCP'; +import { destroyDeployment,getDestroyTaskInfo } from '@/services/ob-deploy-web/Deployments'; +import ConnectionInfo from './Component/ConnectionInfo'; +import UpdatePreCheck from './Component/UpdatePreCheck'; +import InstallProcess from '@/component/InstallProcess'; +import DeployConfig from '@/component/DeployConfig'; +import Steps from '@/component/Steps'; +import CustomFooter from '@/component/CustomFooter'; +import ExitBtn from '@/component/ExitBtn'; +import { METADB_OCP_UPDATE, STEPS_KEYS_UPDATE } from '@/constant/configuration'; + +export interface UpdateProps { + location: { + pathname: string; + query: { step: number; taskId: number }; + }; +} + +const Update: React.FC = ({ + location: { + query: { step }, + }, +}) => { + const [form] = Form.useForm(); + const [systemUserForm] = Form.useForm(); + const { validateFields } = form; + const { + checkConnectInfo, + setCheckConnectInfo, + installStatus, + setInstallStatus, + installResult, + setInstallResult, + } = useModel('ocpInstallData'); + const { ocpConfigData, setOcpConfigData } = useModel('global'); + const [current, setCurrent] = useState(step ? Number(step) : -1); + const [precheckNoPassed, setPrecheckNoPassed] = useState(false); + const [preCheckLoading,setPreCheckLoading] = useState(false) + const [allowInputUser,setAllowInputUser] = useState(true) + // const [serverErrorInfo, setServerErrorInfo] = useState(); + // 操作系统用户验证状态 + const [checkStatus, setCheckStatus] = useState< + 'unchecked' | 'fail' | 'success' + >('unchecked'); + + const { components = {} } = ocpConfigData; + const { oceanbase = {}, ocpserver = {} } = components; + const cluster_name = oceanbase?.appname; + const version = ocpserver?.version; + const package_hash = ocpserver?.package_hash; + + useEffect(() => { + if (cluster_name && !upgradeOcpInfo?.id && step === 2) { + upgradeOcp({ + cluster_name, + version, + usable: package_hash, + }); + } + }, [cluster_name, step]); + + const { + data:connectReqData, + run: connectMetaDB, + loading, + } = useRequest(OCP.connectMetaDB, { + manual: true, + onSuccess: ({success,data}) => { + if (success) { + if(data?.user){ + setAllowInputUser(false) + systemUserForm.setFieldValue('user',data.user) + } + setCheckConnectInfo('success'); + } else { + setCheckConnectInfo('fail'); + } + }, + onError: ({ response, data }: any) => { + setCheckConnectInfo('fail'); + // const errorInfo = data?.msg || data?.detail || response?.statusText; + // Modal.error({ + // title: 'MetaDB 连接失败,请检查连接配置', + // icon: , + // content: errorInfo, + // okText: '我知道了', + // }); + }, + }); + + const updateInfo = connectReqData?.data + + const { run: createOcpPrecheck } = useRequest(OCP.createUpgradePrecheck, { + manual: true, + onSuccess: (res) => { + precheckOcpUpgrade({ cluster_name }); + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }); + + // 发起OCP的预检查 + const { + run: precheckOcpUpgrade, + refresh: refreshPrecheckOcpUpgrade, + loading: precheckOcpUpgradeLoading, + } = useRequest(OCP.precheckOcpUpgrade, { + manual: true, + onSuccess: (res) => { + if (res?.success) { + history.push({ + pathname: '/update', + query: { + step: `${current}`, + }, + }); + getOcpUpgradePrecheckTask({ + cluster_name, + task_id: res?.data?.id, + }); + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }); + + // OCP的预检查结果 + const { + data: ocpUpgradePrecheckTaskData, + run: getOcpUpgradePrecheckTask, + cancel:stopPreCheck + } = useRequest(OCP.getOcpUpgradePrecheckTask, { + manual: true, + pollingInterval:1000, + onSuccess: (res) => { + if (res?.success) { + if(res?.data?.task_info?.status !== 'RUNNING'){ + stopPreCheck() + setPreCheckLoading(false) + }else{ + setPreCheckLoading(true) + } + if (find(res.data?.precheck_result || [], ['result', 'FAILED'])) { + setPrecheckNoPassed(true); + } else { + setPrecheckNoPassed(false); + } + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }); + + const ocpUpgradePrecheckTask = ocpUpgradePrecheckTaskData?.data; + const precheckOcpUpgradeStatus = ocpUpgradePrecheckTask?.task_info?.status; + const precheckOcpUpgradeResult = ocpUpgradePrecheckTask?.task_info?.result; + + // 升级ocp + const { + data: upgradeOcpData, + run: upgradeOcp, + refresh, + loading: upgradeOcpLoading, + } = useRequest(OCP.upgradeOcp, { + manual: true, + onSuccess: (res) => { + if (res?.success) { + getOcpInfo({ + cluster_name, + }); + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }); + + // 清理环境 + const {run:handleDestroyDeployment} = useRequest(destroyDeployment,{ + manual:true, + onSuccess:({success})=>{ + if(success){ + handleGetDestroyTaskInfo({name:cluster_name}) + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }) + + // 获取清理结果 + const {run:handleGetDestroyTaskInfo,cancel:stopGetDestroyTaskInfo} = useRequest(getDestroyTaskInfo,{ + manual:true, + pollingInterval:1000, + onSuccess:({success,data})=>{ + if(success && data?.status !== 'RUNNING'){ + stopGetDestroyTaskInfo() + if(data?.status === 'SUCCESSFUL'){ + refresh() + setInstallStatus('RUNNING'); + } + if(data?.status === 'FAILED'){ + message.error(data?.msg); + } + } + }, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }) + + const upgradeOcpInfo = upgradeOcpData?.data || {}; + + // 获取ocp 信息 + const { + data: ocpInfoData, + run: getOcpInfo, + loading: getOcpInfoLoading, + } = useRequest(OCP.getOcpInfo, { + manual: true, + onError: ({ response, data }: any) => { + errorHandler({ response, data }); + }, + }); + + const ocpInfo = ocpInfoData?.data || {}; + + const handleSubmit = (currentStep: number) => { + switch (currentStep) { + case 0: + break; + case 1: + createOcpPrecheck({ name: cluster_name }); + break; + case 2: + if (cluster_name && version) { + upgradeOcp({ + cluster_name, + version, + usable: package_hash, + }).then(() => { + setCurrent(current + 1); + }); + } + break; + default: + break; + } + }; + + const handleCheck = () => { + validateFields().then((values) => { + const { host, port, database, accessUser, accessCode } = values; + setOcpConfigData({ + ...ocpConfigData, + updateConnectInfo:{ + ...ocpConfigData.updateConnectInfo, + ...values + } + }); + connectMetaDB({ + host, + port, + database, + user: accessUser, + password: accessCode, + cluster_name, + }); + }); + }; + + const preStep = () => { + setCurrent(current - 1); + }; + + const resetConnectState = ()=>{ + systemUserForm.setFieldsValue({ + user:'', + password:'', + systemPort:22 + }) + setCheckConnectInfo('unchecked') + } + + + + return ( + + {installResult !== 'FAILED' && installResult !== 'SUCCESSFUL' && ( + + )} + +
    + {current == -1 && ( + + )} + + {current == 0 && ( + + )} + + {current == 1 && ( + { + setPrecheckNoPassed(val); + }} + getOcpInfoLoading={getOcpInfoLoading} + ocpUpgradePrecheckTask={ocpUpgradePrecheckTask} + precheckOcpUpgradeLoading={ + precheckOcpUpgradeLoading || preCheckLoading + } + cluster_name={cluster_name} + /> + )} + + {current == 2 && ( + + )} +
    + {current === 2 && installStatus === 'RUNNING' ? null : ( + <> + {current !== -1 && ( + + + {current === 2 && installStatus === 'RUNNING' ? null : ( + + )} + + {current < 2 ? ( + <> + {current > 0 && ( + + + + )} + + {current === 0 && ( + + )} + + + + + + ) : ( + <> + {installResult === 'FAILED' ? ( + + ) : null} + + )} + + + )} + + )} +
    + ); +}; + +export default Update; diff --git a/web/src/pages/OcpInstaller/Welcome/index.tsx b/web/src/pages/OcpInstaller/Welcome/index.tsx new file mode 100644 index 0000000..da520c6 --- /dev/null +++ b/web/src/pages/OcpInstaller/Welcome/index.tsx @@ -0,0 +1,88 @@ +import { intl } from '@/utils/intl'; +import { useEffect } from 'react'; +import { useModel } from 'umi'; +import { Button } from 'antd'; +import videojs from 'video.js'; +import 'video.js/dist/video-js.css'; +import NP from 'number-precision'; +import { getLocale, history } from 'umi'; +import EnStyles from '../../Obdeploy/indexEn.less'; +import ZhStyles from '../../Obdeploy/indexZh.less'; + +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; + +export default function Welcome() { + const { setCurrentStep, setErrorVisible, setErrorsList } = useModel('global'); + let Video: any; + + const aspectRatio = NP.divide(2498, 3940).toFixed(10); + + const screenWidth = window.innerWidth * 1.3; + let videoWidth = 0; + let videoHeight = 0; + + if (screenWidth < 1040) { + videoWidth = 1040; + } else { + videoWidth = screenWidth; + } + + videoHeight = Math.ceil(NP.times(videoWidth, aspectRatio)); + + useEffect(() => { + const welcomeVideo = document.querySelector('.welcome-video'); + if (welcomeVideo) { + Video = videojs(welcomeVideo, { + controls: false, + autoplay: true, + loop: true, + preload: 'auto', + }); + } + return () => { + Video.dispose(); + }; + }, []); + + return ( +
    +
    +
    +

    + {intl.formatMessage({ + id: 'OBD.OcpInstaller.Welcome.WelcomeToTheOcpUpgrade', + defaultMessage: '欢迎您使用 OCP 升级向导', + })} +

    +

    OceanBase Cloud Platfrom upgrade wizard

    +
    + +
    +
    + +
    +
    + ); +} diff --git a/web/src/pages/constants/index.ts b/web/src/pages/constants/index.ts index 2995ad7..0ba374f 100644 --- a/web/src/pages/constants/index.ts +++ b/web/src/pages/constants/index.ts @@ -1,8 +1,11 @@ import { intl } from '@/utils/intl'; export const commonStyle = { width: 216 }; +export const TIME_REFRESH = 5000; +export const STABLE_OCP_VERSION = '421'; export const oceanbaseComponent = 'oceanbase'; export const obproxyComponent = 'obproxy'; export const ocpexpressComponent = 'ocp-express'; +export const ocpComponent = 'ocpserver'; export const obagentComponent = 'obagent'; export const ocpexpressComponentKey = 'ocpexpress'; @@ -101,6 +104,19 @@ export const componentsConfig = { defaultMessage: 'OCP Express 参数名称', }), }, + [ocpComponent]: { + name: 'OCP', + showComponentName: 'OCP', + type: intl.formatMessage({ + id: 'OBD.pages.constants.Tools', + defaultMessage: '工具', + }), + componentKey: ocpexpressComponentKey, + labelName: intl.formatMessage({ + id: 'OBD.pages.constants.OcpParameterName', + defaultMessage: 'OCP 参数名称', + }), + }, }; export const modeConfig = { @@ -124,3 +140,87 @@ export const pathRule = { '以 “/” 开头的绝对路径,只能包含字母、数字和特殊字符(~@%^_+=(){}[]:,./)', }), }; +//https://www.oceanbase.com/docs/community-ocp-cn-1000000000261244 +export const resourceMap = { + metaDB: [ + { + hosts: 10, + cpu: 2, + memory: 4, + }, + { + hosts: 50, + cpu: 4, + memory: 8, + }, + { + hosts: 100, + cpu: 8, + memory: 16, + }, + { + hosts: 200, + cpu: 16, + memory: 32, + }, + { + hosts: 400, + cpu: 32, + memory: 64, + }, + ], + monitorDB: [ + { + hosts: 10, + cpu: 2, + memory: 8, + }, + { + hosts: 50, + cpu: 4, + memory: 32, + }, + { + hosts: 100, + cpu: 8, + memory: 64, + }, + { + hosts: 200, + cpu: 16, + memory: 128, + }, + { + hosts: 400, + cpu: 32, + memory: 256, + }, + ], + OCP: [ + { + hosts: 10, + cpu: 2, + memory: 4, + }, + { + hosts: 50, + cpu: 4, + memory: 8, + }, + { + hosts: 100, + cpu: 8, + memory: 16, + }, + { + hosts: 200, + cpu: 16, + memory: 32, + }, + { + hosts: 400, + cpu: 32, + memory: 64, + }, + ], +}; diff --git a/web/src/pages/index.less b/web/src/pages/index.less index 5b6006b..e69de29 100644 --- a/web/src/pages/index.less +++ b/web/src/pages/index.less @@ -1,66 +0,0 @@ -@backgroundColor: #f5f8ff; - -.container { - height: 100%; -} - -.englishContainer { - font-family: SourceSansPro-Semibold, SourceSansPro-Regular; -} - -.pageHeader { - position: fixed; - top: 0; - right: 0; - left: 0; - z-index: 99; - height: 48px; - padding: 0 20px; - overflow: hidden; - line-height: 48px; - background-color: @backgroundColor; - border-bottom: 1px solid #dde4ed; - .logo { - position: relative; - top: -2px; - width: 125px; - vertical-align: middle; - } - .logoText { - margin-left: 8px; - font-size: 14px; - } - .actionContent { - float: right; - } - .action { - color: #5c6b8a; - } - .actionIcon { - margin-right: 10px; - } -} - -.pageContainer { - min-height: calc(100% - 240px); - padding-top: 170px; - padding-bottom: 70px; - background-color: @backgroundColor; - .pageMain { - .pageContent { - width: 1040px; - margin: 0 auto; - overflow: auto; - } - } -} - -.mask { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 100; - background: rgba(0, 0, 0, 0.45); -} diff --git a/web/src/pages/index.tsx b/web/src/pages/index.tsx index 799eb5f..1b3220b 100644 --- a/web/src/pages/index.tsx +++ b/web/src/pages/index.tsx @@ -1,309 +1,108 @@ +import { getLocale,history } from 'umi'; import { intl } from '@/utils/intl'; -import { useEffect, useState } from 'react'; -import { useModel } from 'umi'; -import { Space, ConfigProvider, notification, Dropdown, Modal } from 'antd'; -import { - HomeOutlined, - ReadOutlined, - ProfileOutlined, - GlobalOutlined, - InfoCircleOutlined, -} from '@ant-design/icons'; -import useRequest from '@/utils/useRequest'; -import { getErrorInfo, getRandomPassword } from '@/utils'; -import { getDeployment } from '@/services/ob-deploy-web/Deployments'; -import { validateOrSetKeepAliveToken } from '@/services/ob-deploy-web/Common'; -import Welcome from './components/Welcome'; -import InstallConfig from './components/InstallConfig'; -import NodeConfig from './components/NodeConfig'; -import ClusterConfig from './components/ClusterConfig'; -import PreCheck from './components/PreCheck'; -import InstallProcess from './components/InstallProcess'; -import InstallFinished from './components/InstallFinished'; -import ExitPage from './components/ExitPage'; -import ProgressQuit from './components/ProgressQuit'; -import Steps from './components/Steps'; -import { localeList, localeText } from '@/constants'; -import type { Locale } from 'antd/es/locale'; -import { setLocale, getLocale } from 'umi'; -import enUS from 'antd/es/locale/en_US'; -import zhCN from 'antd/es/locale/zh_CN'; -import theme from './theme'; -import styles from './index.less'; +import NP from 'number-precision'; +import videojs from 'video.js'; +import 'video.js/dist/video-js.css'; +import { useEffect } from 'react'; +import { Button } from 'antd'; -export default function IndexPage() { - const uuid = window.localStorage.getItem('uuid'); - const locale = getLocale(); - const { - setCurrentStep, - setConfigData, - currentStep, - errorVisible, - errorsList, - setErrorVisible, - setErrorsList, - } = useModel('global'); - const [lastError, setLastError] = useState({}); - const [first, setFirst] = useState(true); - const [token, setToken] = useState(''); - const [isInstall, setIsInstall] = useState(false); - const [localeConfig, setLocalConfig] = useState( - locale === 'zh-CN' ? zhCN : enUS, - ); +import EnStyles from './Obdeploy/indexEn.less'; +import ZhStyles from './Obdeploy/indexZh.less'; - const { run: fetchDeploymentInfo } = useRequest(getDeployment, { - onError: (e: any) => { - const errorInfo = getErrorInfo(e); - setErrorVisible(true); - setErrorsList([...errorsList, errorInfo]); - }, - }); +const locale = getLocale(); +const styles = locale === 'zh-CN' ? ZhStyles : EnStyles; +export default function IndexPage(){ + let Video: any; - const { run: handleValidateOrSetKeepAliveToken } = useRequest( - validateOrSetKeepAliveToken, - { - onSuccess: ({ success, data }: API.OBResponse) => { - if (success) { - if (!data) { - if (first) { - Modal.confirm({ - className: 'new-page-confirm', - title: intl.formatMessage({ - id: 'OBD.src.pages.ItIsDetectedThatYou', - defaultMessage: - '检测到您打开了一个新的部署流程页面,请确认是否使用新页面继续部署工作?', - }), - width: 424, - icon: , - content: intl.formatMessage({ - id: 'OBD.src.pages.UseTheNewPageTo', - defaultMessage: - '使用新的页面部署,原部署页面将无法再提交任何部署请求', - }), - onOk: () => { - handleValidateOrSetKeepAliveToken({ token, overwrite: true }); - }, - onCancel: () => { - setCurrentStep(8); - }, - }); - setTimeout(() => { - document.activeElement.blur(); - }, 100); - } else { - setCurrentStep(8); - } - } else if (currentStep > 4) { - if (!isInstall) { - handleValidateOrSetKeepAliveToken({ - token: token, - is_clear: true, - }); - setIsInstall(true); - } - } else { - setTimeout(() => { - handleValidateOrSetKeepAliveToken({ token }); - }, 1000); - } - setFirst(false); - } - }, - onError: () => { - if (currentStep > 4) { - handleValidateOrSetKeepAliveToken({ token: token, is_clear: true }); - } else { - setTimeout(() => { - handleValidateOrSetKeepAliveToken({ token }); - }, 1000); - } - }, - }, - ); + const aspectRatio = NP.divide(2498, 3940).toFixed(10); - const setCurrentLocale = (key: string) => { - if (key !== locale) { - setLocale(key); - window.localStorage.setItem('uuid', token); - } - setLocalConfig(key === 'zh-CN' ? zhCN : enUS); - }; - - const getLocaleItems = () => { - return localeList.map((item) => ({ - ...item, - label: setCurrentLocale(item.key)}>{item.label}, - })); - }; + const screenWidth = window.innerWidth * 1.3; + let videoWidth = 0; + let videoHeight = 0; - const contentConfig = { - 1: , - 2: , - 3: , - 4: , - 5: , - 6: , - 7: , - 8: , - }; + if (screenWidth < 1040) { + videoWidth = 1040; + } else { + videoWidth = screenWidth; + } + videoHeight = Math.ceil(NP.times(videoWidth, aspectRatio)); useEffect(() => { - let token = ''; - - fetchDeploymentInfo({ task_status: 'INSTALLING' }).then( - ({ success, data }: API.OBResponse) => { - if (success && data?.items?.length) { - setCurrentStep(5); - setConfigData({ - components: { oceanbase: { appname: data?.items[0]?.name } }, - }); - } else { - if (uuid) { - token = uuid; - } else { - token = `${Date.now()}${getRandomPassword(true)}`; - } - setToken(token); - handleValidateOrSetKeepAliveToken({ token }); - window.localStorage.setItem('uuid', ''); - } - }, - ); - const sendBeacon = () => { - const url = - window.location.origin + - '/api/v1/connect/keep_alive?token=' + - token + - '&is_clear=true'; - navigator.sendBeacon(url); + const welcomeVideo = document.querySelector('.welcome-video'); + if (welcomeVideo) { + Video = videojs(welcomeVideo, { + controls: false, + autoplay: true, + loop: true, + preload: 'auto', + }); + } + return () => { + Video.dispose(); }; - window.addEventListener('beforeunload', function (e) { - sendBeacon(); - }); }, []); - - useEffect(() => { - const newLastError = errorsList?.[errorsList?.length - 1] || null; - if (errorVisible) { - if (newLastError?.desc !== lastError?.desc) { - notification.error({ - description: newLastError?.desc, - message: newLastError?.title, - duration: null, - }); - } - } else { - notification.destroy(); - } - setLastError(newLastError); - }, [errorVisible, errorsList, lastError]); - - const containerStyle = { - minHeight: `${currentStep < 6 ? 'calc(100% - 240px)' : 'calc(100% - 140px)' - }`, - paddingTop: `${currentStep < 6 ? '170px' : '70px'}`, - }; - - return ( - -
    -
    - logo - - {intl.formatMessage({ - id: 'OBD.src.pages.DeploymentWizard', - defaultMessage: '部署向导', - })} - - - - e.preventDefault()} - data-aspm-click="c307509.d326700" + return( +
    +
    +
    +

    + {intl.formatMessage({ + id: 'OBD.pages.components.Welcome.WelcomeToDeploy', + defaultMessage: '欢迎您部署', + })} +

    + {locale === 'zh-CN' ? ( +

    + OceanBase + {intl.formatMessage({ + id: 'OBD.pages.components.Welcome.DistributedDatabase', + defaultMessage: '分布式数据库', + })} +

    + ) : ( +

    + {intl.formatMessage({ + id: 'OBD.pages.components.Welcome.DistributedDatabase', + defaultMessage: '分布式数据库', + })} +

    + )} +

    OceanBase comprehensive database

    +
    - - {currentStep === 0 ? ( - - ) : ( -
    -
    -
    - {contentConfig[currentStep]} -
    -
    + {intl.formatMessage({ + id: 'OBD.pages.components.Welcome.StartAnExperienceTour', + defaultMessage: '开启体验之旅', + })} + +
    - )} + + -
    - ); -} + ) +} \ No newline at end of file diff --git a/web/src/pages/type.ts b/web/src/pages/type.ts new file mode 100644 index 0000000..8b26cc3 --- /dev/null +++ b/web/src/pages/type.ts @@ -0,0 +1,8 @@ +// 通用type +export type PathType = + | 'configuration' + | 'ocpInstaller' + | 'guide' + | 'install' + | 'obdeploy' + | 'update'; diff --git a/web/src/services/ocp_installer_backend/Info.ts b/web/src/services/ocp_installer_backend/Info.ts new file mode 100644 index 0000000..8bfdf60 --- /dev/null +++ b/web/src/services/ocp_installer_backend/Info.ts @@ -0,0 +1,19 @@ +/* eslint-disable */ +// 该文件由 OneAPI 自动生成,请勿手动修改! +import { request } from 'umi'; + +/** get_server_info get server info GET /api/v1/info */ +export async function getServerInfo( + params: { + // path + /** deployment id */ + cluster_name?: string; + }, + options?: { [key: string]: any }, +) { + const { cluster_name } = params; + return request(`/api/v1/upgrade/info/${cluster_name}`, { + method: 'GET', + ...(options || {}), + }); +} diff --git a/web/src/services/ocp_installer_backend/Metadb.ts b/web/src/services/ocp_installer_backend/Metadb.ts new file mode 100644 index 0000000..94f49d4 --- /dev/null +++ b/web/src/services/ocp_installer_backend/Metadb.ts @@ -0,0 +1,427 @@ +/* eslint-disable */ +// 该文件由 OneAPI 自动生成,请勿手动修改! +import { request } from 'umi'; + +/** list_metadb_deployments list metadb deployments GET /api/v1/metadb/deployments */ +export async function listMetadbDeployments(options?: { [key: string]: any }) { + return request( + '/api/v1/metadb/deployments', + { + method: 'GET', + ...(options || {}), + }, + ); +} + +/** create_metadb_deployment create deployment for metadb POST /api/v1/metadb/deployments */ +export async function createMetadbDeployment( + body?: API.MetadbDeploymentConfig, + options?: { [key: string]: any }, +) { + return request( + '/api/v1/metadb/deployments', + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }, + ); +} + +/** get_metadb_deployment get metadb deployments GET /api/v1/metadb/deployments/${param0} */ +export async function getMetadbDeployment( + params: { + // path + /** deployment id */ + id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0 } = params; + return request( + `/api/v1/metadb/deployments/${param0}`, + { + method: 'GET', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** destroy_metadb destroy metadb DELETE /api/v1/metadb/deployments/${param0} */ +export async function destroyMetadb( + params: { + // path + id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0 } = params; + return request( + `/api/v1/metadb/deployments/${param0}`, + { + method: 'DELETE', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** check machine resource check path for check GET /api/v1/metadb/deployments/${param0}/resource_check */ +export async function checkMachineResource( + params: { + // path + /** deployment id */ + id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0 } = params; + return request( + `/api/v1/metadb/deployments/${param0}/resource_check`, + { + method: 'GET', + params: { ...params }, + ...(options || {}), + }, + ); +} + +export async function checkOperatingUser( + body?: API.OperatingUser, + options?: { [key: string]: any }, +) { + return request('/api/v1/machine/check/user', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }); +} + +/** get_metadb_deployment_resource get server resource for metadb deployment GET /api/v1/metadb/deployments/${param0}/resource */ +export async function getMetadbDeploymentResource( + params: { + // path + /** deployment id */ + id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0 } = params; + return request( + `/api/v1/metadb/deployments/${param0}/resource`, + { + method: 'GET', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** precheck_metadb_deployment precheck for metadb deployment POST /api/v1/metadb/deployments/${param0}/precheck */ +export async function precheckMetadbDeployment( + params: { + // path + id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0 } = params; + return request( + `/api/v1/metadb/deployments/${param0}/precheck`, + { + method: 'POST', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** get_metadb_precheck_task precheck for metadb deployment GET /api/v1/metadb/deployments/${param0}/precheck/${param1} */ +export async function getMetadbPrecheckTask( + params: { + // path + /** deployment id */ + id?: number; + /** task id */ + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0, task_id: param1 } = params; + return request( + `/api/v1/metadb/deployments/${param0}/precheck/${param1}`, + { + method: 'GET', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** recover_metadb_deployment recover metadb deployment config POST /api/v1/metadb/deployments/${param0}/recover */ +export async function recoverMetadbDeployment( + params: { + // path + /** deployment id */ + id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0 } = params; + return request( + `/api/v1/metadb/deployments/${param0}/recover`, + { + method: 'POST', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** install_metadb install metadb POST /api/v1/metadb/deployments/${param0}/install */ +export async function installMetadb( + params: { + // path + id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0 } = params; + return request( + `/api/v1/metadb/deployments/${param0}/install`, + { + method: 'POST', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** get_metadb_install_task get metadb install task GET /api/v1/metadb/deployments/${param0}/install/${param1} */ +export async function getMetadbInstallTask( + params: { + // path + /** deployment id */ + id?: number; + /** task id */ + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0, task_id: param1 } = params; + return request( + `/api/v1/metadb/deployments/${param0}/install/${param1}`, + { + method: 'GET', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** get_metadb_install_task_log get metadb install task log GET /api/v1/metadb/deployments/${param0}/install/${param1}/log */ +export async function getMetadbInstallTaskLog( + params: { + // query + /** offset to read task log */ + offset?: number; + // path + /** deployment id */ + id?: number; + /** task id */ + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0, task_id: param1, ...queryParams } = params; + return request( + `/api/v1/metadb/deployments/${param0}/install/${param1}/log`, + { + method: 'GET', + params: { + ...queryParams, + }, + ...(options || {}), + }, + ); +} + +/** reinstall_metadb reinstall metadb POST /api/v1/metadb/deployments/${param0}/reinstall */ +export async function reinstallMetadb( + params: { + // path + /** deployment id */ + id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0 } = params; + return request( + `/api/v1/metadb/deployments/${param0}/reinstall`, + { + method: 'POST', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** get_metadb_reinstall_task get metadb reinstall task GET /api/v1/metadb/deployments/${param0}/reinstall/${param1} */ +export async function getMetadbReinstallTask( + params: { + // path + /** deployment id */ + id?: number; + /** task id */ + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0, task_id: param1 } = params; + return request( + `/api/v1/metadb/deployments/${param0}/reinstall/${param1}`, + { + method: 'GET', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** get_metadb_reinstall_task_log get metadb reinstall task log GET /api/v1/metadb/deployments/${param0}/reinstall/${param1}/log */ +export async function getMetadbReinstallTaskLog( + params: { + // query + /** offset to read task log */ + offset?: number; + // path + /** deployment id */ + id?: number; + /** task id */ + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0, task_id: param1, ...queryParams } = params; + return request( + `/api/v1/metadb/deployments/${param0}/reinstall/${param1}/log`, + { + method: 'GET', + params: { + ...queryParams, + }, + ...(options || {}), + }, + ); +} + +/** get_metadb_reinstall_task_report get metadb reinstall task report GET /api/v1/metadb/deployments/${param0}/reinstall/${param1}/report */ +export async function getMetadbReinstallTaskReport( + params: { + // query + /** offset to read task log */ + offset?: number; + // path + /** deployment id */ + id?: number; + /** task id */ + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0, task_id: param1, ...queryParams } = params; + return request( + `/api/v1/metadb/deployments/${param0}/reinstall/${param1}/report`, + { + method: 'GET', + params: { + ...queryParams, + }, + ...(options || {}), + }, + ); +} + +/** get_metadb_destroy_task get metadb destroy task GET /api/v1/metadb/deployments/${param0}/destroy/${param1} */ +export async function getMetadbDestroyTask( + params: { + // path + id?: number; + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0, task_id: param1 } = params; + return request( + `/api/v1/metadb/deployments/${param0}/destroy/${param1}`, + { + method: 'GET', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** list_metadb_connection list metadb connection GET /api/v1/metadb/connections */ +export async function listMetadbConnection(options?: { [key: string]: any }) { + return request( + '/api/v1/metadb/connections', + { + method: 'GET', + ...(options || {}), + }, + ); +} + +/** create_metadb_connection create metadb connection POST /api/v1/metadb/connections */ +export async function createMetadbConnection( + params: { + // query + /** whether the incoming tenant is the sys tenant */ + sys?: boolean; + }, + body?: API.DatabaseConnection, + options?: { [key: string]: any }, +) { + return request( + '/api/v1/metadb/connections', + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + params: { + ...params, + }, + data: body, + ...(options || {}), + }, + ); +} + +/** get_metadb_connection get metadb connection GET /api/v1/metadb/connections/${param0} */ +export async function getMetadbConnection( + params: { + // path + /** connection id */ + id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0 } = params; + return request( + `/api/v1/metadb/connections/${param0}`, + { + method: 'GET', + params: { ...params }, + ...(options || {}), + }, + ); +} diff --git a/web/src/services/ocp_installer_backend/OCP.ts b/web/src/services/ocp_installer_backend/OCP.ts new file mode 100644 index 0000000..41f9eb3 --- /dev/null +++ b/web/src/services/ocp_installer_backend/OCP.ts @@ -0,0 +1,644 @@ +/* eslint-disable */ +// 该文件由 OneAPI 自动生成,请勿手动修改! +import { request } from 'umi'; + +/** get_installed_ocp_info get_installed_ocp_info GET /api/v1/ocp/info/${param0} */ +export async function getInstalledOcpInfo( + params: { + // path + /** deployment id */ + id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0 } = params; + return request( + `/api/v1/ocp/info/${param0}`, + { + method: 'GET', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** list_ocp_deployments list ocp deployments GET /api/v1/ocp/deployments */ +export async function listOcpDeployments(options?: { [key: string]: any }) { + return request( + '/api/v1/ocp/deployments', + { + method: 'GET', + ...(options || {}), + }, + ); +} + +/** create_ocp_deployment create deployment for ocp POST /api/v1/ocp/deployments */ +export async function createOcpDeployment( + body?: API.OcpDeploymentConfig, + options?: { [key: string]: any }, +) { + return request('/api/v1/ocp/deployments', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }); +} + +/** get_ocp_deployment get ocp deployment GET /api/v1/ocp/deployments/${param0} */ +export async function getOcpDeployment( + params: { + // path + /** deployment id */ + id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0 } = params; + return request( + `/api/v1/ocp/deployments/${param0}`, + { + method: 'GET', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** destroy_ocp destroy ocp DELETE /api/v1/ocp/deployments/${param0} */ +export async function destroyOcp( + params: { + // path + id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0 } = params; + return request( + `/api/v1/ocp/deployments/${param0}`, + { + method: 'DELETE', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** get_ocp_deployment_resource get server resource for ocp deployment GET /api/v1/ocp/deployments/${param0}/resource */ +export async function getOcpDeploymentResource( + params: { + // path + /** deployment id */ + id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0 } = params; + return request( + `/api/v1/ocp/deployments/${param0}/resource`, + { + method: 'GET', + params: { ...params }, + ...(options || {}), + }, + ); +} + +export async function createOcpDeploymentConfig( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.createDeploymentConfigParams, + body: API.DeploymentConfig, + options?: { [key: string]: any }, +) { + const { name: param0, ...queryParams } = params; + return request(`/api/v1/ocp_deployments/${param0}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + params: { ...queryParams }, + data: body, + ...(options || {}), + }); +} +/** precheck_ocp_deployment precheck for ocp deployment POST /api/v1/ocp/deployments/${param0}/precheck */ +export async function precheckOcpDeployment( + params: { + // path + /** deployment id */ + id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0 } = params; + return request( + `/api/v1/ocp/deployments/${param0}/precheck`, + { + method: 'POST', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** precheck_ocp precheck for ocp deployment GET /api/v1/ocp/deployments/${param0}/precheck/${param1} */ +export async function precheckOcp( + params: { + // path + /** deployment id */ + id?: number; + /** task id */ + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0, task_id: param1 } = params; + return request( + `/api/v1/ocp/deployments/${param0}/precheck/${param1}`, + { + method: 'GET', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** recover_ocp_deployment recover ocp deployment config POST /api/v1/ocp/deployments/${param0}/recover */ +export async function recoverOcpDeployment( + params: { + // path + /** deployment id */ + id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0 } = params; + return request( + `/api/v1/ocp/deployments/${param0}/recover`, + { + method: 'POST', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** install_ocp install ocp POST /api/v1/ocp/deployments/${param0}/install */ +export async function installOcp( + params: { + // path + /** deployment id */ + id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0 } = params; + return request( + `/api/v1/ocp/deployments/${param0}/install`, + { + method: 'POST', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** get_ocp_install_task get ocp install task GET /api/v1/ocp/deployments/${param0}/install/${param1} */ +export async function getOcpInstallTask( + params: { + // path + /** deployment id */ + id?: number; + /** task id */ + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0, task_id: param1 } = params; + return request( + `/api/v1/ocp/deployments/${param0}/install/${param1}`, + { + method: 'GET', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** get_ocp_install_task_log get ocp install task log GET /api/v1/ocp/deployments/${param0}/install/${param1}/log */ +export async function getOcpInstallTaskLog( + params: { + // query + /** offset to read task log */ + offset?: number; + // path + /** deployment id */ + id?: number; + /** task id */ + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0, task_id: param1, ...queryParams } = params; + return request( + `/api/v1/ocp/deployments/${param0}/install/${param1}/log`, + { + method: 'GET', + params: { + ...queryParams, + }, + ...(options || {}), + }, + ); +} + +/** get_ocp_install_task_report get ocp install task report GET /api/v1/ocp/deployments/${param0}/install/${param1}/report */ +export async function getOcpInstallTaskReport( + params: { + // query + /** offset to read task log */ + offset?: number; + // path + /** deployment id */ + id?: number; + /** task id */ + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0, task_id: param1, ...queryParams } = params; + return request( + `/api/v1/ocp/deployments/${param0}/install/${param1}/report`, + { + method: 'GET', + params: { + ...queryParams, + }, + ...(options || {}), + }, + ); +} + +/** reinstall_ocp reinstall ocp POST /api/v1/ocp/deployments/${param0}/reinstall */ +export async function reinstallOcp( + params: { + // path + /** deployment id */ + id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0 } = params; + return request( + `/api/v1/ocp/deployments/${param0}/reinstall`, + { + method: 'POST', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** get_ocp_reinstall_task get ocp reinstall task GET /api/v1/ocp/deployments/${param0}/reinstall/${param1} */ +export async function getOcpReinstallTask( + params: { + // path + /** deployment id */ + id?: number; + /** task id */ + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0, task_id: param1 } = params; + return request( + `/api/v1/ocp/deployments/${param0}/reinstall/${param1}`, + { + method: 'GET', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** get_ocp_reinstall_task_log get ocp reinstall task log GET /api/v1/ocp/deployments/${param0}/reinstall/${param1}/log */ +export async function getOcpReinstallTaskLog( + params: { + // query + /** offset to read task log */ + offset?: number; + // path + /** deployment id */ + id?: number; + /** task id */ + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0, task_id: param1, ...queryParams } = params; + return request( + `/api/v1/ocp/deployments/${param0}/reinstall/${param1}/log`, + { + method: 'GET', + params: { + ...queryParams, + }, + ...(options || {}), + }, + ); +} + +/** get_ocp_reinstall_task_report get ocp reinstall task report GET /api/v1/ocp/deployments/${param0}/reinstall/${param1}/report */ +export async function getOcpReinstallTaskReport( + params: { + // query + /** offset to read task log */ + offset?: number; + // path + /** deployment id */ + id?: number; + /** task id */ + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0, task_id: param1, ...queryParams } = params; + return request( + `/api/v1/ocp/deployments/${param0}/reinstall/${param1}/report`, + { + method: 'GET', + params: { + ...queryParams, + }, + ...(options || {}), + }, + ); +} + +/** get_ocp_destroy_task get ocp destroy task GET /api/v1/ocp/deployments/${param0}/destroy/${param1} */ +export async function getOcpDestroyTask( + params: { + // path + /** deployment id */ + id?: number; + /** task id */ + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0, task_id: param1 } = params; + return request( + `/api/v1/ocp/deployments/${param0}/destroy/${param1}`, + { + method: 'GET', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** create_ocp_info create ocp info POST /api/v1/ocp */ +export async function createOcpInfo( + body?: API.DatabaseConnection, + options?: { [key: string]: any }, +) { + return request('/api/v1/ocp', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }); +} + +/** get_ocp_info get ocp info GET /api/v1/ocp/${param0} */ +export async function getOcpInfo( + params: { + // path + /** ocp id */ + // id?: number; + cluster_name?: string; + }, + options?: { [key: string]: any }, +) { + const { cluster_name: param0 } = params; + return request(`/api/v1/ocp/${param0}`, { + method: 'GET', + params: { ...params }, + ...(options || {}), + }); +} + +/** precheck_ocp_upgrade post precheck for ocp upgrade POST /api/v1/ocp/${param0}/upgrade/precheck */ +export async function precheckOcpUpgrade( + params: { + // path + /** deployment id */ + // id?: number; + cluster_name?: string; + }, + options?: { [key: string]: any }, +) { + const { cluster_name: param0 } = params; + return request( + `/api/v1/ocp/${param0}/upgrade/precheck`, + { + method: 'POST', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** get_ocp_upgrade_precheck_task get precheck for ocp upgrade GET /api/v1/ocp/${param0}/upgrade/precheck/${param1} */ +export async function getOcpUpgradePrecheckTask( + params: { + // path + /** ocp id */ + // id?: number; + cluster_name: string; + /** task id */ + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { cluster_name: param0, task_id: param1 } = params; + return request( + `/api/v1/ocp/${param0}/upgrade/precheck/${param1}`, + { + method: 'GET', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** upgrade_ocp upgrade ocp POST /api/v1/ocp/${param0}/upgrade */ +export async function upgradeOcp( + params: { + // query + /** ocp upgrade version */ + version: string; + /** ocp upgrade hash */ + usable: string; + // path + // /** ocp id */ + // id?: number; + cluster_name?: string; + }, + options?: { [key: string]: any }, +) { + const { cluster_name: param0, ...queryParams } = params; + return request(`/api/v1/ocp/${param0}/upgrade`, { + method: 'POST', + params: { + ...queryParams, + }, + ...(options || {}), + }); +} + +/** get_ocp_upgrade_task get ocp upgrade task GET /api/v1/ocp/${param0}/upgrade/${param1} */ +export async function getOcpUpgradeTask( + params: { + // path + /** ocp id */ + cluster_name?: string; + /** task id */ + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { cluster_name: param0, task_id: param1 } = params; + return request( + `/api/v1/ocp/${param0}/upgrade/${param1}`, + { + method: 'GET', + params: { ...params }, + ...(options || {}), + }, + ); +} + +/** get_ocp_upgrade_task_log get ocp upgrade task log GET /api/v1/ocp/${param0}/upgrade/${param1}/log */ +export async function getOcpUpgradeTaskLog( + params: { + // query + /** offset to read task log */ + offset?: number; + // path + cluster_name?: string; + /** ocp id */ + // id?: number; + /** task id */ + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { cluster_name: param0, task_id: param1, ...queryParams } = params; + return request( + `/api/v1/ocp/${param0}/upgrade/${param1}/log`, + { + method: 'GET', + params: { + ...queryParams, + }, + ...(options || {}), + }, + ); +} + +/** get_ocp_upgrade_task_report get ocp upgrade task report GET /api/v1/ocp/${param0}/upgrade/${param1}/report */ +export async function getOcpUpgradeTaskReport( + params: { + // query + /** offset to read task log */ + offset?: number; + // path + /** ocp id */ + id?: number; + /** task id */ + task_id?: number; + }, + options?: { [key: string]: any }, +) { + const { id: param0, task_id: param1, ...queryParams } = params; + return request( + `/api/v1/ocp/${param0}/upgrade/${param1}/report`, + { + method: 'GET', + params: { + ...queryParams, + }, + ...(options || {}), + }, + ); +} + +/** get_ocp_not_upgrading_host get ocp not upgrading host GET /api/v1/ocp/upgraade/agent/hosts */ +export async function getOcpNotUpgradingHost(options?: { [key: string]: any }) { + return request( + '/api/v1/ocp/upgraade/agent/hosts', + { + method: 'GET', + ...(options || {}), + }, + ); +} + +export async function getClusterNames(options?: { [key: string]: any }) { + return request('/api/v1/deployment/names', { + method: 'GET', + ...(options || {}), + }); +} + +export async function getConnectInfo( + params: { + name?: number; + }, + options?: { [key: string]: any }, +) { + const { name } = params; + return request( + `/api/v1/deployment/metadb/connection?name=${name}`, + { + method: 'GET', + ...(options || {}), + }, + ); +} + +export async function connectMetaDB( + body?: API.DatabaseConnection, + options?: { [key: string]: any }, +) { + return request('/api/v1/deployment/ocp/agent/ip', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }); +} + +export async function createUpgradePrecheck( + params: { + name?: number; + }, + options?: { [key: string]: any }, +) { + const { name } = params; + return request(`/api/v1/deployment/upgrade/ocp?name=${name}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + ...(options || {}), + }); +} diff --git a/web/src/services/ocp_installer_backend/Process.ts b/web/src/services/ocp_installer_backend/Process.ts new file mode 100644 index 0000000..c7614df --- /dev/null +++ b/web/src/services/ocp_installer_backend/Process.ts @@ -0,0 +1,11 @@ +/* eslint-disable */ +// 该文件由 OneAPI 自动生成,请勿手动修改! +import { request } from 'umi'; + +/** exit after a while POST /api/v1/suicide */ +export async function suicide(options?: { [key: string]: any }) { + return request('/api/v1/suicide', { + method: 'POST', + ...(options || {}), + }); +} diff --git a/web/src/services/ocp_installer_backend/User.ts b/web/src/services/ocp_installer_backend/User.ts new file mode 100644 index 0000000..08e99c0 --- /dev/null +++ b/web/src/services/ocp_installer_backend/User.ts @@ -0,0 +1,11 @@ +/* eslint-disable */ +// 该文件由 OneAPI 自动生成,请勿手动修改! +import { request } from 'umi'; + +/** get system user GET /api/v1/get/user */ +export async function user(options?: { [key: string]: any }) { + return request('/api/v1/get/user', { + method: 'GET', + ...(options || {}), + }); +} diff --git a/web/src/services/ocp_installer_backend/index.ts b/web/src/services/ocp_installer_backend/index.ts new file mode 100644 index 0000000..196db53 --- /dev/null +++ b/web/src/services/ocp_installer_backend/index.ts @@ -0,0 +1,17 @@ +/* eslint-disable */ +// API 更新时间:2023-07-31 15:43:30 +// API 唯一标识:64c7660e3c810e1751cf56b3 +// 该文件由 OneAPI 自动生成,请勿手动修改! + +import * as OCP from './OCP'; +import * as Metadb from './Metadb'; +import * as Info from './Info'; +import * as Process from './Process'; +import * as User from './User'; +export default { + OCP, + Metadb, + Info, + Process, + User, +}; diff --git a/web/src/services/ocp_installer_backend/typings.d.ts b/web/src/services/ocp_installer_backend/typings.d.ts new file mode 100644 index 0000000..8da3841 --- /dev/null +++ b/web/src/services/ocp_installer_backend/typings.d.ts @@ -0,0 +1,680 @@ +/* eslint-disable */ +// 该文件由 OneAPI 自动生成,请勿手动修改! + +declare namespace API { + interface ComponentInfo { + /** Name ocp component */ + name?: string; + /** Ip server address */ + ip?: string; + } + + interface DataList_DatabaseConnection_ { + /** Total */ + total?: number; + /** Items */ + items?: Array; + } + + interface DataList_MetaDBResource_ { + /** Total */ + total?: number; + /** Items */ + items?: Array; + } + + interface DataList_MetadbDeploymentInfo_ { + /** Total */ + total?: number; + /** Items */ + items?: Array; + } + + interface DataList_OcpDeploymentInfo_ { + /** Total */ + total?: number; + /** Items */ + items?: Array; + } + + interface DataList_RecoverChangeParameter_ { + /** Total */ + total?: number; + /** Items */ + items?: Array; + } + + interface DataList_ResourceCheckResult_ { + /** Total */ + total?: number; + /** Items */ + items?: Array; + } + + interface DatabaseConnection { + /** Id id of the connection in installer */ + id?: number; + /** Host host */ + host: string; + /** Port port */ + port: number; + /** User user */ + user: string; + /** Password password */ + password: string; + /** Database database */ + database?: string; + cluster_name?: string; + } + + type DeploymentStatus = 'INIT' | 'DEPLOYING' | 'FINISHED'; + + interface Disk { + /** Path path */ + path: string; + /** Disk Info disk info */ + disk_info: any; + } + + interface DiskInfo { + /** Dev dev */ + dev: string; + /** Mount Path mount path */ + mount_path: string; + /** Total Size total size */ + total_size: string; + /** Free Size free size */ + free_size: string; + } + + interface HTTPValidationError { + /** Detail */ + detail?: Array; + } + + type InstallerMode = 'STANDARD' | 'COMPACT'; + + interface MetaDBResource { + /** Address server address */ + address: string; + /** Disk path: disk_info */ + disk: Array; + /** Memory Limit Lower Limit memory_limit lower limit */ + memory_limit_lower_limit: number; + /** Memory Limit Higher Limit memory_limit higher limit */ + memory_limit_higher_limit: number; + /** Memory Limit Default default memory_limit */ + memory_limit_default: number; + /** Data Size Default default data size */ + data_size_default: number; + /** Log Size Default default log size */ + log_size_default: number; + /** Flag which solution to use */ + flag: number; + } + + interface MetadbDeploymentConfig { + /** Auth ssh auth info */ + auth?: any; + /** Cluster Name cluster name */ + cluster_name?: string; + /** Servers servers to deploy */ + servers: Array; + /** Root Password password of user root@sys */ + root_password?: string; + /** Home Path home path to install */ + home_path?: string; + /** Data Dir data directory */ + data_dir?: string; + /** Log Dir log directory */ + log_dir?: string; + /** Sql Port sql port */ + sql_port?: number; + /** Rpc Port rpc port */ + rpc_port?: number; + /** Devname devname */ + devname?: string; + /** Parameters config parameter */ + parameters?: Array; + } + + interface MetadbDeploymentInfo { + /** Id metadb deployment id */ + id?: number; + /** metadb deployment status, ex: INIT, FINISHED */ + status?: any; + /** Config metadb deployment */ + config?: any; + /** Connection connection info of metadb */ + connection?: any; + } + + interface MetadbResource { + /** Servers observer resource */ + servers: Array; + } + + interface OBResponse { + /** Code */ + code?: number; + /** Data */ + data?: any; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_DataList_DatabaseConnection__ { + /** Code */ + code?: number; + data?: DataList_DatabaseConnection_; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_DataList_MetaDBResource__ { + /** Code */ + code?: number; + data?: DataList_MetaDBResource_; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_DataList_MetadbDeploymentInfo__ { + /** Code */ + code?: number; + data?: DataList_MetadbDeploymentInfo_; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_DataList_OcpDeploymentInfo__ { + /** Code */ + code?: number; + data?: DataList_OcpDeploymentInfo_; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_DataList_RecoverChangeParameter__ { + /** Code */ + code?: number; + data?: DataList_RecoverChangeParameter_; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_DataList_ResourceCheckResult__ { + /** Code */ + code?: number; + data?: DataList_ResourceCheckResult_; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_DatabaseConnection_ { + /** Code */ + code?: number; + data?: DatabaseConnection; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_MetadbDeploymentInfo_ { + /** Code */ + code?: number; + data?: MetadbDeploymentInfo; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_OperatingUser_ { + /** Code */ + code?: number; + data?: string; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_OcpDeploymentInfo_ { + /** Code */ + code?: number; + data?: OcpDeploymentInfo; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_OcpInfo_ { + /** Code */ + code?: number; + data?: OcpInfo; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface connectMetaDB_ { + /** Code */ + code?: number; + data?: connectMetaDB; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface createUpgradePrecheck_ { + /** Code */ + code?: number; + data?: string; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_OcpInstalledInfo_ { + /** Code */ + code?: number; + data?: OcpInstalledInfo; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_OcpResource_ { + /** Code */ + code?: number; + data?: OcpResource; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_OcpUpgradeLostAddress_ { + /** Code */ + code?: number; + data?: OcpUpgradeLostAddress; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface ClusterNames_ { + /** Code */ + code?: number; + data?: ClusterNames; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface ConnectInfo_ { + /** Code */ + code?: number; + data?: ConnectInfo; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_PrecheckTaskInfo_ { + /** Code */ + code?: number; + data?: PrecheckTaskInfo; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_ServerInfo_ { + /** Code */ + code?: number; + data?: ServerInfo; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_TaskInfo_ { + /** Code */ + code?: number; + data?: TaskInfo; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_TaskLog_ { + /** Code */ + code?: number; + data?: TaskLog; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface OBResponse_UserInfo_ { + /** Code */ + code?: number; + data?: UserInfo; + /** Msg */ + msg?: string; + /** Success */ + success?: boolean; + } + + interface ObserverResource { + /** Address observer address */ + address: string; + /** Cpu Total total cpu */ + cpu_total: number; + /** Cpu Free free cpu */ + cpu_free: number; + /** Memory Total total memory size */ + memory_total: number; + /** Memory Free free memory size */ + memory_free: number; + } + + interface OcpDeploymentConfig { + /** Auth ssh auth info */ + auth?: any; + /** Metadb connection info of metadb */ + metadb: any; + /** Meta Tenant meta tenant config */ + meta_tenant?: any; + /** Monitor Tenant monitor tenant config */ + monitor_tenant?: any; + /** Appname ocp app name */ + appname?: string; + /** Admin Password ocp login password */ + admin_password: string; + /** Servers servers to deploy */ + servers: Array; + /** Home Path home path to install */ + home_path?: string; + /** Server Port server port */ + server_port?: number; + /** Parameters */ + parameters?: Array; + } + + interface OcpDeploymentInfo { + /** Id metadb deployment id */ + id?: number; + /** ocp deployment status, ex: INIT, DEPLOYING, FINISHED */ + status?: any; + /** Config ocp deployment config */ + config: any; + /** Monitor Display monitor tenant configured */ + monitor_display?: boolean; + } + + interface OcpInfo { + /** Id ocp deployment id */ + id?: number; + /** ocp deployment status, ex:INIT, FINISHED */ + status?: any; + /** Current Version current ocp version */ + current_version: string; + /** Ocp Servers ocp servers */ + ocp_servers: Array; + /** Agent Servers servers deployed agent */ + agent_servers?: Array; + } + + interface connectMetaDB { + ocp_version: string; + component: any[]; + tips: boolean; + msg: string; + user:string; + } + + interface OcpInstalledInfo { + /** Url Access address, eq: ip:port */ + url: Array; + /** Account account */ + account?: string; + /** Password account password */ + password: string; + } + + interface OcpResource { + /** Servers server resource */ + servers: Array; + /** Metadb metadb resource */ + metadb: any; + } + + interface OcpUpgradeLostAddress { + /** Address lost ip address */ + address?: Array; + } + + interface ClusterNames { + name: string[]; + } + interface ConnectInfo { + host: string; + port: number; + user: string; + password: string; + database: string; + cluster_name: string; + } + + interface Parameter { + /** Name parameter name */ + name: string; + /** Value parameter value */ + value: string; + } + + interface PreCheckResult { + /** Name precheck event name */ + name: string; + /** Server precheck server */ + server?: string; + /** precheck event result */ + result?: any; + /** Recoverable precheck event recoverable */ + recoverable?: boolean; + /** Code error code */ + code?: string; + /** Advisement advisement of precheck event failure */ + advisement?: string; + } + + type PrecheckEventResult = 'PASSED' | 'FAILED' | 'RUNNING'; + + interface PrecheckTaskInfo { + /** Task Info task detailed info */ + task_info?: any; + /** Precheck Result precheck result */ + precheck_result?: Array; + } + + interface RecoverChangeParameter { + /** Name repaired item */ + name: string; + /** Old Value old value item */ + old_value?: string; + /** New Value new value item */ + new_value?: string; + } + + interface ResourceCheckResult { + /** Address server ip */ + address: string; + /** Name path */ + name: string; + /** Check Result check result, true/false */ + check_result?: boolean; + /** Error Message error message, eq path not enough */ + error_message?: Array; + } + + interface ServerInfo { + /** User username */ + user?: string; + /** Ocp Version ocp version with installer */ + ocp_version?: string; + /** Component component info */ + component?: Array; + /** server mode,ex:standard,compact */ + mode?: any; + metadb?: DatabaseConnection; + /** Msg failed message */ + msg?: string; + /** Status eq: 0, 1 */ + status?: number; + } + + interface ServerResource { + /** Address server address */ + address: string; + /** Cpu Total total cpu */ + cpu_total: number; + /** Cpu Free free cpu */ + cpu_free: number; + /** Memory Total total memory size */ + memory_total: string; + /** Memory Free free memory size */ + memory_free: string; + /** Disk disk info */ + disk: Array; + } + + interface SshAuth { + /** User username */ + user?: string; + /** auth method */ + auth_method?: any; + /** Password password */ + password?: string; + /** Private Key private key */ + private_key?: string; + /** Port ssh port */ + port?: number; + } + + type SshAuthMethod = 'PUBKEY' | 'PASSWORD'; + + interface TaskInfo { + /** Id task id */ + id: number; + /** task status */ + status: any; + /** task result */ + result: any; + /** Total total steps */ + total?: string; + /** Finished finished steps */ + finished?: string; + /** Current current step */ + current?: string; + /** Message task message */ + message?: string; + /** Info */ + info?: Array; + } + + interface TaskLog { + /** Log task log content */ + log?: string; + /** Offset offset of current log */ + offset?: number; + } + + type TaskResult = 'SUCCESSFUL' | 'FAILED' | 'RUNNING'; + + type TaskStatus = 'RUNNING' | 'FINISHED'; + + interface TaskStepInfo { + /** Name task step */ + name?: string; + /** task step status */ + status?: any; + /** task step result */ + result?: any; + } + + interface TenantConfig { + /** Name tenant name */ + name: any; + /** Password root password of the tenant */ + password?: string; + /** Resource tenant resource */ + resource?: any; + } + + interface TenantResource { + /** Cpu cpu resource of a tenant */ + cpu?: number; + /** Memory memory resource of a tenant in GB */ + memory?: number; + } + + interface TenantUser { + /** Tenant Name tenant name */ + tenant_name: string; + /** User Name user name */ + user_name?: string; + /** User Database user database */ + user_database?: string; + } + + interface UserInfo { + /** Username system user */ + username: string; + } + + interface ValidationError { + /** Location */ + loc: Array; + /** Message */ + msg: string; + /** Error Type */ + type: string; + } + + interface OperatingUser { + user: string; + password: string; + port: number; + servers: string[]; + } +} diff --git a/web/src/typings/global.d.ts b/web/src/typings/global.d.ts index 1de01b5..d1e94ff 100644 --- a/web/src/typings/global.d.ts +++ b/web/src/typings/global.d.ts @@ -21,12 +21,12 @@ declare namespace API { obproxy?: any; ocpexpress?: any; obagent?: any; + ocpserver?: any; } interface MoreParameter extends API.Parameter { description: string; auto: boolean; - } interface ParameterValue { @@ -58,4 +58,9 @@ declare namespace API { title: string; desc?: string; } + + interface StepProp { + setCurrent: React.Dispatch>; + current: number; + } } diff --git a/web/src/utils/helper.ts b/web/src/utils/helper.ts new file mode 100644 index 0000000..a09ce73 --- /dev/null +++ b/web/src/utils/helper.ts @@ -0,0 +1,18 @@ +//与UI无关的函数 + +// 不用navigator.clipboard.writeText的原因:该接口需要在HTTPS环境下才能使用 +export function copyText(text: string) { + let inputDom = document.createElement('input'); + inputDom.setAttribute('type', 'text'); + inputDom.value = text; + //需要将元素添加到文档中去才可以跟文档结构中的其他元素交互 + document.body.appendChild(inputDom); + inputDom.select(); + //返回false则浏览器不支持该api + let res = document.execCommand('copy'); + document.body.removeChild(inputDom) + return res +} +export function getTailPath(){ + return location.hash.split('/').pop()?.split('?')[0] +} diff --git a/web/src/utils/index.tsx b/web/src/utils/index.tsx index 50c0927..0ade460 100644 --- a/web/src/utils/index.tsx +++ b/web/src/utils/index.tsx @@ -1,7 +1,8 @@ import { intl } from '@/utils/intl'; -import { notification, Modal } from 'antd'; +import { notification, Modal, message } from 'antd'; import { ExclamationCircleOutlined } from '@ant-design/icons'; import RandExp from 'randexp'; +import { getLocale, history } from 'umi'; export const handleResponseError = (desc: any, msg?: string | undefined) => { notification.error({ @@ -15,7 +16,52 @@ export const handleResponseError = (desc: any, msg?: string | undefined) => { duration: null, }); }; +export function isEnglish() { + return getLocale() === 'en-US'; +} +export function isZhCN() { + return getLocale() === 'zh-CN'; +} +export function validatePassword(passed) { + return (rule, value, callback) => { + if (value && !passed) { + callback( + intl.formatMessage({ + id: 'ocp-express.src.util.ThePasswordDoesNotMeet', + defaultMessage: '密码设置不符合要求', + }), + ); + } + callback(); + }; +} +export const copyText = (text: string) => { + // navigator.clipboard 并不存在,可能被依赖库改写了 + if (navigator.clipboard) { + setTimeout(() => { + navigator.clipboard.writeText(text); + }, 100); + } else { + const textarea = document.createElement('textarea'); + document.body.appendChild(textarea); + // 隐藏此输入框 + textarea.style.position = 'fixed'; + textarea.style.clip = 'rect(0 0 0 0)'; + textarea.style.top = '10px'; + // 赋值 + textarea.value = text; + // 延迟一下复制操作,确保最终的值不会被其它操作覆盖剪贴板 + setTimeout(() => { + // 选中 + textarea.select(); + // 复制 + document.execCommand('copy', true); + // 移除输入框 + document.body.removeChild(textarea); + }, 100); + } +}; export const handleQuit = ( handleQuitProgress: () => void, setCurrentStep: (step: number) => void, @@ -109,3 +155,238 @@ export const getRandomPassword = (isToken?: boolean) => { } return getRandomPassword(isToken); }; + +// const statusCodeMessage = { +// 400: intl.formatMessage({ +// id: 'ocp-express.src.util.request.TheErrorOccurredInThe', +// defaultMessage: '发出的请求有错误,服务器没有进行新建或修改数据的操作。', +// }), + +// 401: intl.formatMessage({ +// id: 'ocp-express.src.util.request.TheUserIsNotLogged', +// defaultMessage: '用户未登录,或者登录使用的用户名和密码错误。', +// }), + +// 403: intl.formatMessage({ +// id: 'ocp-express.src.util.request.YouDoNotHaveThe', +// defaultMessage: '没有权限进行对应操作,请联系管理员。', +// }), + +// 404: intl.formatMessage({ +// id: 'ocp-express.src.util.request.TheRequestIsForA', +// defaultMessage: '发出的请求针对的是不存在的记录,服务器没有进行操作。', +// }), + +// 405: intl.formatMessage({ +// id: 'ocp-express.src.util.request.TheRequestMethodCannotBe', +// defaultMessage: '请求方法不能被用于请求相应的资源,或者请求路径不正确。', +// }), +// 406: intl.formatMessage({ +// id: 'ocp-express.src.util.request.TheRequestFormatIsNot', +// defaultMessage: '请求的格式不可得。', +// }), + +// 410: intl.formatMessage({ +// id: 'ocp-express.src.util.request.TheRequestedResourceIsPermanently', +// defaultMessage: '请求的资源被永久删除,且不会再得到的。', +// }), + +// 422: intl.formatMessage({ +// id: 'ocp-express.src.util.request.AValidationErrorOccursWhen', +// defaultMessage: '当创建一个对象时,发生一个验证错误。', +// }), + +// 500: intl.formatMessage({ +// id: 'ocp-express.src.util.request.AnErrorOccurredOnThe', +// defaultMessage: '服务器发生错误,请检查服务器。', +// }), + +// 502: intl.formatMessage({ +// id: 'ocp-express.src.util.request.GatewayError', +// defaultMessage: '网关错误。', +// }), +// 503: intl.formatMessage({ +// id: 'ocp-express.src.util.request.TheServiceIsUnavailableAnd', +// defaultMessage: '服务不可用,服务器暂时过载或维护。', +// }), + +// 504: intl.formatMessage({ +// id: 'ocp-express.src.util.request.TheGatewayTimedOut', +// defaultMessage: '网关超时。', +// }), +// }; + +/** + * 异常处理程序 + * response 为浏览器的 Response 对象,而 data 才是后端实际返回的响应数据 + */ +export const errorHandler = ({ response, data }) => { + const { status } = response || {}; + // 所有的 500 状态报错,报错信息结构一致 + if (status !== 500) { + // message.error(statusCodeMessage[status], 3); + } else if (status === 504) { + // dispatch({ + // type: 'global/update', + // payload: { + // installStatus: 'FINISHED', + // installResult: 'FAILED', + // }, + // }); + return; + } else { + const { detail } = data || {}; + // 错误展示一定要在 throw err 之前执行,否则抛错之后就无法展示了 + // 优先展示后端返回的错误信息,如果没有,则根据 status 进行展示 + const msg = detail; + // || statusCodeMessage[status]; + // 有对应的错误信息才进行展示,避免遇到 204 等状态码(退出登录) 时,报一个空错误 + if (msg) { + message.error(msg, 3); + } + // 403 状态为无权限情况,跳转到 403 页面 + if (status === 403) { + history.push('/error/403'); + } else if (status === 404) { + history.push('/error/404'); + } + return data; + } +}; + +//ip格式 +export const serverReg = + /^((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])?$/; +// 数据库名仅支持英文、数字,长度不超过20个字符 +// export const dbReg = /^[a-zA-Z0-9]{1,20}$/; +// 网站的地址:要求以http/https开始,包含VIP地址/域名/端口的网址,且结尾不含斜杠 / +export const siteReg = + /^(http|https):\/\/([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+(:[0-9]+)?(? { + let validtor = true; + if (value && value.length) { + value.some((item) => { + validtor = serverReg.test(item.trim()); + return !serverReg.test(item.trim()); + }); + } + if (validtor) { + return Promise.resolve(); + } + return Promise.reject( + new Error( + intl.formatMessage({ + id: 'OBD.src.utils.SelectTheCorrectOcpNode', + defaultMessage: '请选择正确的 OCP 节点', + }), + ), + ); +}; + +export function generateRandomPassword() { + const length = Math.floor(Math.random() * 25) + 8; // 生成8到32之间的随机长度 + const characters = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~!@#%^&*_-+=`|(){}[]:;',.?/"; // 可用字符集合 + + let password = ''; + let countUppercase = 0; // 大写字母计数器 + let countLowercase = 0; // 小写字母计数器 + let countNumber = 0; // 数字计数器 + let countSpecialChar = 0; // 特殊字符计数器 + + // 生成随机密码 + for (let i = 0; i < length; i++) { + const randomIndex = Math.floor(Math.random() * characters.length); + const randomChar = characters[randomIndex]; + password += randomChar; + + // 判断字符类型并增加相应计数器 + if (/[A-Z]/.test(randomChar)) { + countUppercase++; + } else if (/[a-z]/.test(randomChar)) { + countLowercase++; + } else if (/[0-9]/.test(randomChar)) { + countNumber++; + } else { + countSpecialChar++; + } + } + + // 检查计数器是否满足要求 + if ( + countUppercase < 2 || + countLowercase < 2 || + countNumber < 2 || + countSpecialChar < 2 + ) { + return generateRandomPassword(); // 重新生成密码 + } + + return password; +} +export const passwordRules = [ + { + required: true, + message: intl.formatMessage({ + id: 'OBD.src.utils.EnterAPassword', + defaultMessage: '请输入密码', + }), + }, + () => ({ + validator(_: any, value: string) { + if (value.length >= 8 && value.length <= 32) { + return Promise.resolve(); + } + return Promise.reject( + new Error( + intl.formatMessage({ + id: 'OBD.src.utils.TheLengthShouldBeTo', + defaultMessage: '长度应为 8~32 个字符', + }), + ), + ); + }, + }), + () => ({ + validator(_: any, value: string) { + const regex = /^[A-Za-z\d~!@#%^&*_\-+=`|(){}[\]:;',.?/]*$/; + if (regex.test(value)) { + return Promise.resolve(); + } + return Promise.reject( + new Error( + intl.formatMessage({ + id: 'OBD.src.utils.CanOnlyContainLettersNumbers.2', + defaultMessage: + "只能包含字母、数字和特殊字符~!@#%^&*_-+=`|(){}[]:;',.?/", + }), + ), + ); + }, + }), + () => ({ + validator(_: any, value: string) { + if ( + /^(?=.*[A-Z].*[A-Z])(?=.*[a-z].*[a-z])(?=.*\d.*\d)(?=.*[~!@#%^&*_\-+=`|(){}[\]:;',.?/].*[~!@#%^&*_\-+=`|(){}[\]:;',.?/])[A-Za-z\d~!@#%^&*_\-+=`|(){}[\]:;',.?/]{8,32}$/.test( + value, + ) + ) { + return Promise.resolve(); + } + return Promise.reject( + new Error( + intl.formatMessage({ + id: 'OBD.src.utils.AtLeastUppercaseAndLowercase', + defaultMessage: '大小写字母、数字和特殊字符都至少包含 2 个', + }), + ), + ); + }, + }), +]; diff --git a/web/yarn.lock b/web/yarn.lock index fe8975e..d2fc032 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -2,9 +2,9 @@ # yarn lockfile v1 -"@ahooksjs/use-request@^2.0.0": +"@ahooksjs/use-request@^2.0.0", "@ahooksjs/use-request@^2.8.14": version "2.8.15" - resolved "https://registry.npm.alibaba-inc.com/@ahooksjs/use-request/download/@ahooksjs/use-request-2.8.15.tgz#daa32a8395ba75e8deb9f4fde4e221a4a8f525db" + resolved "https://registry.npmjs.org/@ahooksjs/use-request/-/use-request-2.8.15.tgz" integrity sha512-xhVaM4fyIiAMdVFuuU5i3CFUdFa/IblF+fvITVMFaUEO3w/V5tVCAF6WIA3T03n1/RPuzRkA7Ao1PFtSGtGelw== dependencies: lodash.debounce "^4.0.8" @@ -12,22 +12,51 @@ "@ampproject/remapping@^2.1.0": version "2.2.0" - resolved "https://registry.npm.alibaba-inc.com/@ampproject/remapping/download/@ampproject/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" + resolved "https://registry.npm.alibaba-inc.com/@ampproject/remapping/download/@ampproject/remapping-2.2.0.tgz" integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== dependencies: "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" +"@ant-design/colors@^4.0.5": + version "4.0.5" + resolved "https://registry.npmjs.org/@ant-design/colors/-/colors-4.0.5.tgz" + integrity sha512-3mnuX2prnWOWvpFTS2WH2LoouWlOgtnIpc6IarWN6GOzzLF8dW/U8UctuvIPhoboETehZfJ61XP+CGakBEPJ3Q== + dependencies: + tinycolor2 "^1.4.1" + "@ant-design/colors@^6.0.0": version "6.0.0" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/colors/download/@ant-design/colors-6.0.0.tgz#9b9366257cffcc47db42b9d0203bb592c13c0298" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/colors/download/@ant-design/colors-6.0.0.tgz" integrity sha1-m5NmJXz/zEfbQrnQIDu1ksE8Apg= dependencies: "@ctrl/tinycolor" "^3.4.0" +"@ant-design/colors@^7.0.0": + version "7.0.0" + resolved "https://registry.npmjs.org/@ant-design/colors/-/colors-7.0.0.tgz" + integrity sha512-iVm/9PfGCbC0dSMBrz7oiEXZaaGH7ceU40OJEfKmyuzR9R5CRimJYPlRiFtMQGQcbNMea/ePcoIebi4ASGYXtg== + dependencies: + "@ctrl/tinycolor" "^3.4.0" + +"@ant-design/compatible@^1.0.5": + version "1.1.2" + resolved "https://registry.npmjs.org/@ant-design/compatible/-/compatible-1.1.2.tgz" + integrity sha512-Qsx5Qw97eiSgcxyQDlY45QSbvGn0gUdpX8XFImPvzZpKwabqQ2HnXXuUlb8RbrkURswaPIoyLEGKDPeogIaURA== + dependencies: + "@ant-design/icons" "^4.0.0" + classnames "^2.2.6" + lodash.camelcase "^4.3.0" + lodash.upperfirst "^4.3.1" + omit.js "^1.0.2" + rc-animate "^2.10.2" + rc-editor-mention "^1.1.13" + rc-form "^2.4.10" + rc-util "^4.10.0" + "@ant-design/cssinjs@^0.0.0-alpha.38": version "0.0.0-alpha.60" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/cssinjs/download/@ant-design/cssinjs-0.0.0-alpha.60.tgz#17998ea8da0ca734747876045e455e0c28f19a97" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/cssinjs/download/@ant-design/cssinjs-0.0.0-alpha.60.tgz" integrity sha512-EQlU5f20flZMQ9XDbR/RL5MhQedgkHXR6o4pfbe6cMv0YMXK/jv669++N8msC7ZoNnGf2OxbmGRkvVS0OqG3iw== dependencies: "@babel/runtime" "^7.11.1" @@ -40,7 +69,7 @@ "@ant-design/cssinjs@^1.0.0": version "1.6.1" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/cssinjs/download/@ant-design/cssinjs-1.6.1.tgz#334706fe18dd14f319918d701931d92ecacda7e5" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/cssinjs/download/@ant-design/cssinjs-1.6.1.tgz" integrity sha512-35+1e5h1HzPt7d7NjXTG5yg/OQY85YcOIpb3peB3/eKri7+0mW9c+WZB3In7yMscBzvxQREOR5pxNDbqMcI42w== dependencies: "@babel/runtime" "^7.11.1" @@ -51,14 +80,32 @@ rc-util "^5.27.0" stylis "^4.0.13" +"@ant-design/cssinjs@^1.11.1", "@ant-design/cssinjs@^1.16.0", "@ant-design/cssinjs@^1.17.0": + version "1.17.0" + resolved "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.17.0.tgz" + integrity sha512-MgGCZ6sfD3yQB0XW0hN4jgixMxApTlDYyct+pc7fRZNO4CaqWWm/9iXkkljNR27lyWLZmm+XiDfcIOo1bnrnMA== + dependencies: + "@babel/runtime" "^7.11.1" + "@emotion/hash" "^0.8.0" + "@emotion/unitless" "^0.7.5" + classnames "^2.3.1" + csstype "^3.0.10" + rc-util "^5.35.0" + stylis "^4.0.13" + "@ant-design/icons-svg@^4.2.1": version "4.2.1" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/icons-svg/download/@ant-design/icons-svg-4.2.1.tgz#8630da8eb4471a4aabdaed7d1ff6a97dcb2cf05a" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/icons-svg/download/@ant-design/icons-svg-4.2.1.tgz" integrity sha1-hjDajrRHGkqr2u19H/apfcss8Fo= +"@ant-design/icons-svg@^4.3.0": + version "4.3.1" + resolved "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.3.1.tgz" + integrity sha512-4QBZg8ccyC6LPIRii7A0bZUk3+lEDCLnhB+FVsflGdcWPPmV+j3fire4AwwoqHV/BibgvBmR9ZIo4s867smv+g== + "@ant-design/icons@4.8.0", "@ant-design/icons@^4.0.0", "@ant-design/icons@^4.1.0", "@ant-design/icons@^4.2.1", "@ant-design/icons@^4.3.0", "@ant-design/icons@^4.7.0": version "4.8.0" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/icons/download/@ant-design/icons-4.8.0.tgz#3084e2bb494cac3dad6c0392f77c1efc90ee1fa4" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/icons/download/@ant-design/icons-4.8.0.tgz" integrity sha512-T89P2jG2vM7OJ0IfGx2+9FC5sQjtTzRSz+mCHTXkFn/ELZc2YpfStmYHmqzq2Jx55J0F7+O6i5/ZKFSVNWCKNg== dependencies: "@ant-design/colors" "^6.0.0" @@ -67,9 +114,25 @@ classnames "^2.2.6" rc-util "^5.9.4" +"@ant-design/icons@^5.0.0", "@ant-design/icons@^5.2.2", "@ant-design/icons@^5.2.6": + version "5.2.6" + resolved "https://registry.npmjs.org/@ant-design/icons/-/icons-5.2.6.tgz" + integrity sha512-4wn0WShF43TrggskBJPRqCD0fcHbzTYjnaoskdiJrVHg86yxoZ8ZUqsXvyn4WUqehRiFKnaclOhqk9w4Ui2KVw== + dependencies: + "@ant-design/colors" "^7.0.0" + "@ant-design/icons-svg" "^4.3.0" + "@babel/runtime" "^7.11.2" + classnames "^2.2.6" + rc-util "^5.31.1" + +"@ant-design/moment-webpack-plugin@^0.0.4": + version "0.0.4" + resolved "https://registry.yarnpkg.com/@ant-design/moment-webpack-plugin/-/moment-webpack-plugin-0.0.4.tgz#7c48a1a7d3a9fcee3c1fc91463a41c562c6106b1" + integrity sha512-qZe5lakKA9DhyEzmv8gJ8xgDSaVYQG5YuHdxSbXIkrT7L0kTgfuVBBLuPJAqmBBgjW/x3QIlM/Hsd5T6/4GHVw== + "@ant-design/pro-card@2.0.27": version "2.0.27" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-card/download/@ant-design/pro-card-2.0.27.tgz#75574de8c22e93304b38515fe944b639e77ef57c" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-card/download/@ant-design/pro-card-2.0.27.tgz" integrity sha512-Wr8HErUv/yxBL32EshSHkpT4MXhITPxOLDLzYJ3zY+mUBgbpPbQjCDhwnmqH7D+WE6Yv0e+5A+ZTfE8wXxC9XQ== dependencies: "@ant-design/icons" "^4.2.1" @@ -80,9 +143,23 @@ omit.js "^2.0.2" rc-util "^5.4.0" +"@ant-design/pro-card@2.5.15": + version "2.5.15" + resolved "https://registry.npmjs.org/@ant-design/pro-card/-/pro-card-2.5.15.tgz" + integrity sha512-LJhyPDVbRRJaBw14kTHab3lduWWKmM2T/Ga253Yqp2n1YT3638g6brtk4lVdw10XqEY113DFjN/kZri0efgNhg== + dependencies: + "@ant-design/icons" "^5.0.0" + "@ant-design/pro-provider" "2.12.3" + "@ant-design/pro-utils" "2.14.3" + "@babel/runtime" "^7.18.0" + classnames "^2.3.2" + omit.js "^2.0.2" + rc-resize-observer "^1.0.0" + rc-util "^5.4.0" + "@ant-design/pro-components@2.3.34": version "2.3.34" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-components/download/@ant-design/pro-components-2.3.34.tgz#b4733b7b9ffb0639d48a62fbe8242f353ed4f972" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-components/download/@ant-design/pro-components-2.3.34.tgz" integrity sha512-Zi83lb8vsJ/nUJyZY3rve0fAxj2EdGJtFt1OrZ55XIdrKLeBVcthxLbXLB3rXJkXrJs3R6KsiolAGPP2UcQqaQ== dependencies: "@ant-design/pro-card" "2.0.27" @@ -97,9 +174,26 @@ "@ant-design/pro-utils" "2.3.5" "@babel/runtime" "^7.16.3" +"@ant-design/pro-components@^2.6.16": + version "2.6.18" + resolved "https://registry.npmjs.org/@ant-design/pro-components/-/pro-components-2.6.18.tgz" + integrity sha512-qXJHeMhUZyCKLASYxD3BD8h38F0q2+8DLig6GR0vytsdUSMJbPXcj4KIJ9bdR0sXzu3vLosoxNeNV2Fkx1QcGQ== + dependencies: + "@ant-design/pro-card" "2.5.15" + "@ant-design/pro-descriptions" "2.5.4" + "@ant-design/pro-field" "2.12.4" + "@ant-design/pro-form" "2.18.6" + "@ant-design/pro-layout" "7.16.13" + "@ant-design/pro-list" "2.5.18" + "@ant-design/pro-provider" "2.12.3" + "@ant-design/pro-skeleton" "2.1.7" + "@ant-design/pro-table" "3.12.3" + "@ant-design/pro-utils" "2.14.3" + "@babel/runtime" "^7.16.3" + "@ant-design/pro-descriptions@2.0.30": version "2.0.30" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-descriptions/download/@ant-design/pro-descriptions-2.0.30.tgz#e94370e040b3d4cb9a9e3044bb2dbb5ca56049a6" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-descriptions/download/@ant-design/pro-descriptions-2.0.30.tgz" integrity sha512-anx9L4NnrXLSkFnqdAPkB0ag2ZWKGRhvYez98CyFZcNZ2TPR8HLlJkwNqclgElrkEUiDENXhPsBY16brLn+LtQ== dependencies: "@ant-design/pro-field" "2.1.22" @@ -110,9 +204,22 @@ rc-util "^5.0.6" use-json-comparison "^1.0.5" +"@ant-design/pro-descriptions@2.5.4": + version "2.5.4" + resolved "https://registry.npmjs.org/@ant-design/pro-descriptions/-/pro-descriptions-2.5.4.tgz" + integrity sha512-KzDjzNHFZetb9GKr0bbxDlrvHFdaHvIyGqaPau65Dwj+BWaoJq4QD/4Lh6d9j4f2UJ0NE1a6tXdDuYMkV6FzfA== + dependencies: + "@ant-design/pro-field" "2.12.4" + "@ant-design/pro-form" "2.18.6" + "@ant-design/pro-skeleton" "2.1.7" + "@ant-design/pro-utils" "2.14.3" + "@babel/runtime" "^7.18.0" + rc-resize-observer "^0.2.3" + rc-util "^5.0.6" + "@ant-design/pro-field@2.1.22": version "2.1.22" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-field/download/@ant-design/pro-field-2.1.22.tgz#1d06c22f102526fd27efc30ee8fae512c3c2689d" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-field/download/@ant-design/pro-field-2.1.22.tgz" integrity sha512-4PkmM9PuFt1ztexDWBxwWOzAxvz+qeiYlLPQ9HJ4JPca+8Ctr+VtFoM5gbj+5Fsw3SIYey/BXzT8VbDa0aFTEg== dependencies: "@ant-design/icons" "^4.2.1" @@ -127,9 +234,44 @@ rc-util "^5.4.0" swr "^1.2.0" +"@ant-design/pro-field@2.12.4": + version "2.12.4" + resolved "https://registry.npmjs.org/@ant-design/pro-field/-/pro-field-2.12.4.tgz" + integrity sha512-kN+isiCzE1SBUF5XHIQS3vfynY87x5Y8XMX4ZZVHKUqvSHNe9veU5L2FZuy9mgJA3X7crvGCaiQWLGHo2bh1kA== + dependencies: + "@ant-design/icons" "^5.0.0" + "@ant-design/pro-provider" "2.12.3" + "@ant-design/pro-utils" "2.14.3" + "@babel/runtime" "^7.18.0" + "@chenshuai2144/sketch-color" "^1.0.8" + classnames "^2.3.2" + dayjs "^1.11.9" + lodash.tonumber "^4.0.3" + omit.js "^2.0.2" + rc-util "^5.4.0" + swr "^2.0.0" + +"@ant-design/pro-form@2.18.6": + version "2.18.6" + resolved "https://registry.npmjs.org/@ant-design/pro-form/-/pro-form-2.18.6.tgz" + integrity sha512-o8d9PdLIvuCWatCFuMeoUEGNGS5lLrrHZ3H5Q/RYrF8ZD9tApIU27NBjAL3vh0s+XGIS+mBsvU49OiAg2WloBw== + dependencies: + "@ant-design/icons" "^5.0.0" + "@ant-design/pro-field" "2.12.4" + "@ant-design/pro-provider" "2.12.3" + "@ant-design/pro-utils" "2.14.3" + "@babel/runtime" "^7.18.0" + "@chenshuai2144/sketch-color" "^1.0.7" + "@umijs/use-params" "^1.0.9" + classnames "^2.3.2" + lodash.merge "^4.6.2" + omit.js "^2.0.2" + rc-resize-observer "^1.1.0" + rc-util "^5.0.6" + "@ant-design/pro-form@2.3.2": version "2.3.2" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-form/download/@ant-design/pro-form-2.3.2.tgz#7ead7eef7800fe73790bb839b66235ef234f1d93" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-form/download/@ant-design/pro-form-2.3.2.tgz" integrity sha512-mRm7HRe+O/A1KVALjavhWfVKfvfMS3zEcl+HcltiGioQ7hNR6nX5C6OQX/bfSrm0P2UaUANwqAs/3WI6/XjlbA== dependencies: "@ant-design/icons" "^4.2.1" @@ -148,7 +290,7 @@ "@ant-design/pro-layout@6.5.0": version "6.5.0" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-layout/download/@ant-design/pro-layout-6.5.0.tgz#078ce732f56bdea73258df05b2fee33ff62fdb36" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-layout/download/@ant-design/pro-layout-6.5.0.tgz" integrity sha1-B4znMvVr3qcyWN8Fsv7jP/Yv2zY= dependencies: "@ant-design/icons" "^4.0.0" @@ -170,9 +312,29 @@ use-media-antd-query "^1.0.3" warning "^4.0.3" +"@ant-design/pro-layout@7.16.13": + version "7.16.13" + resolved "https://registry.npmjs.org/@ant-design/pro-layout/-/pro-layout-7.16.13.tgz" + integrity sha512-uq+yT7EbqRqLEn+g2LCIll3sbbfjG+UN/yiONhitX/cYZ1tW7Pm62TPkfSdMXOmHNvrTw/khAFg+XrW7apJyag== + dependencies: + "@ant-design/icons" "^5.0.0" + "@ant-design/pro-provider" "2.12.3" + "@ant-design/pro-utils" "2.14.3" + "@babel/runtime" "^7.18.0" + "@umijs/route-utils" "^4.0.0" + "@umijs/use-params" "^1.0.9" + classnames "^2.3.2" + lodash.merge "^4.6.2" + omit.js "^2.0.2" + path-to-regexp "2.4.0" + rc-resize-observer "^1.1.0" + rc-util "^5.0.6" + swr "^2.0.0" + warning "^4.0.3" + "@ant-design/pro-layout@7.2.5": version "7.2.5" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-layout/download/@ant-design/pro-layout-7.2.5.tgz#bb43046f2828c1612bceae6bad393182930d95fa" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-layout/download/@ant-design/pro-layout-7.2.5.tgz" integrity sha512-0lox30B+6zB3IZ7h00Yw5QwrJe0OR21yiV6goGJZ2pHmdCGFaBQNWirkKFeb4OPdrRG9U5e8AtaihQVx/oyPNQ== dependencies: "@ant-design/icons" "^4.0.0" @@ -196,7 +358,7 @@ "@ant-design/pro-list@2.0.31": version "2.0.31" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-list/download/@ant-design/pro-list-2.0.31.tgz#ef19e464a32f92c80b7d873d9330f80de6d44a58" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-list/download/@ant-design/pro-list-2.0.31.tgz" integrity sha512-BPVR1ZgCwLvbookAEbAkETutWhAiEaFx6MQVkdC6fVS2U1JuAm7oHvygsbbxC/X5ENVOZJZFSuNQPWMQh95UCA== dependencies: "@ant-design/icons" "^4.0.0" @@ -211,16 +373,32 @@ unstated-next "^1.1.0" use-media-antd-query "^1.1.0" +"@ant-design/pro-list@2.5.18": + version "2.5.18" + resolved "https://registry.npmjs.org/@ant-design/pro-list/-/pro-list-2.5.18.tgz" + integrity sha512-LpOFmUtj7aGD/7fyq8IPlH7JhHKTvikNgo70D0MgFtrgOISKmrM0YP5xxZish6agNnXAnfUilXw8JNl2EVf0xw== + dependencies: + "@ant-design/icons" "^5.0.0" + "@ant-design/pro-card" "2.5.15" + "@ant-design/pro-field" "2.12.4" + "@ant-design/pro-table" "3.12.3" + "@ant-design/pro-utils" "2.14.3" + "@babel/runtime" "^7.18.0" + classnames "^2.3.2" + dayjs "^1.11.9" + rc-resize-observer "^1.0.0" + rc-util "^4.19.0" + "@ant-design/pro-provider@0.2.1": version "0.2.1" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-provider/download/@ant-design/pro-provider-0.2.1.tgz#afc80e17830b23f6386ed63565ffa574c3c317cc" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-provider/download/@ant-design/pro-provider-0.2.1.tgz" integrity sha1-r8gOF4MLI/Y4btY1Zf+ldMPDF8w= dependencies: rc-util "^5.0.1" "@ant-design/pro-provider@2.0.17": version "2.0.17" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-provider/download/@ant-design/pro-provider-2.0.17.tgz#d00d698dde7596973ca90d2e019f5823c33d0975" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-provider/download/@ant-design/pro-provider-2.0.17.tgz" integrity sha512-DIxoaeLxPZTJFRqVtsRkpvfnDNuhzWHD54m9iWDRgRxQumJEzY9lhAzRZHby5Wp/QRbsf+pg6rM/zqLaLLM5WA== dependencies: "@ant-design/cssinjs" "^0.0.0-alpha.38" @@ -229,17 +407,35 @@ rc-util "^5.0.1" swr "^1.2.0" +"@ant-design/pro-provider@2.12.3": + version "2.12.3" + resolved "https://registry.npmjs.org/@ant-design/pro-provider/-/pro-provider-2.12.3.tgz" + integrity sha512-DlrZ1HYApd1CSh2kyqWZLcvnt1VWYQ5X0Y1xDNnBEYGD7Y0+1K6NsZ7C+CRz51OBhf3ht79nqL9ng6qQdR97aw== + dependencies: + "@ant-design/cssinjs" "^1.11.1" + "@babel/runtime" "^7.18.0" + "@ctrl/tinycolor" "^3.4.0" + rc-util "^5.0.1" + swr "^2.0.0" + "@ant-design/pro-skeleton@2.0.6": version "2.0.6" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-skeleton/download/@ant-design/pro-skeleton-2.0.6.tgz#bef94d543d115c4df25e87c419ab90606e28474a" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-skeleton/download/@ant-design/pro-skeleton-2.0.6.tgz" integrity sha512-cQcsD4zSBBoLh+OROxh0V2Bmmn5Y38HxMZp47+ZWAP4IUOABS2uDcE/s/zDD0f7XB6LzJ8W+xHguS8XKGWOBvQ== dependencies: "@babel/runtime" "^7.18.0" use-media-antd-query "^1.1.0" +"@ant-design/pro-skeleton@2.1.7": + version "2.1.7" + resolved "https://registry.npmjs.org/@ant-design/pro-skeleton/-/pro-skeleton-2.1.7.tgz" + integrity sha512-5DLD319GTEfxe/GW/Pgja+QjWp89J1DJlKrKvjfQu9z5SCekKPxqG9KmB1F55/eHow1Oe+YjkaqSF55i0xK79Q== + dependencies: + "@babel/runtime" "^7.18.0" + "@ant-design/pro-table@3.1.8": version "3.1.8" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-table/download/@ant-design/pro-table-3.1.8.tgz#7c04a7eda11ea397b7c3e932238dfdb0b7e57862" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-table/download/@ant-design/pro-table-3.1.8.tgz" integrity sha512-88gxnhd968MoROHVKcEATUvvdCeqlg/TmaioM8b9HcZ1wowapXKEUm1aFSCNZRNdVRIdIDWxgaU2gs+KDcZeZQ== dependencies: "@ant-design/icons" "^4.1.0" @@ -258,18 +454,55 @@ use-json-comparison "^1.0.5" use-media-antd-query "^1.1.0" +"@ant-design/pro-table@3.12.3": + version "3.12.3" + resolved "https://registry.npmjs.org/@ant-design/pro-table/-/pro-table-3.12.3.tgz" + integrity sha512-tPcpvw+A/nC+ZM5sMX7IkS6bwHu1tyMWULz6mHAkpTf58BDh+86HQAArwKfcc24hnRkqL8tKiSNyegIGAXeJGw== + dependencies: + "@ant-design/icons" "^5.0.0" + "@ant-design/pro-card" "2.5.15" + "@ant-design/pro-field" "2.12.4" + "@ant-design/pro-form" "2.18.6" + "@ant-design/pro-provider" "2.12.3" + "@ant-design/pro-utils" "2.14.3" + "@babel/runtime" "^7.18.0" + "@dnd-kit/core" "^6.0.8" + "@dnd-kit/modifiers" "^6.0.1" + "@dnd-kit/sortable" "^7.0.2" + "@dnd-kit/utilities" "^3.2.1" + classnames "^2.3.2" + dayjs "^1.11.9" + omit.js "^2.0.2" + rc-resize-observer "^1.0.0" + rc-util "^5.0.1" + "@ant-design/pro-utils@0.5.0": version "0.5.0" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-utils/download/@ant-design/pro-utils-0.5.0.tgz#ca337b4146562dc72c6e796dab265509050665e6" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-utils/download/@ant-design/pro-utils-0.5.0.tgz" integrity sha1-yjN7QUZWLccsbnltqyZVCQUGZeY= dependencies: "@ant-design/pro-provider" "0.2.1" fast-deep-equal "^3.1.3" rc-util "^5.0.6" +"@ant-design/pro-utils@2.14.3": + version "2.14.3" + resolved "https://registry.npmjs.org/@ant-design/pro-utils/-/pro-utils-2.14.3.tgz" + integrity sha512-bbIgvkXTPXblyZelY/aJlZlL+GfFkM5LOS+rnZVhgqoB04isRFBx4BtjE6jcp++mxgA+EV0NZ95wWpeys6C8Jg== + dependencies: + "@ant-design/icons" "^5.0.0" + "@ant-design/pro-provider" "2.12.3" + "@babel/runtime" "^7.18.0" + classnames "^2.3.2" + dayjs "^1.11.9" + lodash.merge "^4.6.2" + rc-util "^5.0.6" + safe-stable-stringify "^2.4.3" + swr "^2.0.0" + "@ant-design/pro-utils@2.3.5": version "2.3.5" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-utils/download/@ant-design/pro-utils-2.3.5.tgz#5b89aebe78c959ec2468bf90d25f7a864774034e" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/pro-utils/download/@ant-design/pro-utils-2.3.5.tgz" integrity sha512-OWYqN4yIyF9jpLtC1Re51slfplM9gi5M/1FKxb3G0Kr7QeP7lpQ5dwKNshWsgVI7ufL5vGERDyrNB2ZTSWfFwQ== dependencies: "@ant-design/icons" "^4.3.0" @@ -283,7 +516,7 @@ "@ant-design/react-slick@~0.29.1": version "0.29.2" - resolved "https://registry.npm.alibaba-inc.com/@ant-design/react-slick/download/@ant-design/react-slick-0.29.2.tgz#53e6a7920ea3562eebb304c15a7fc2d7e619d29c" + resolved "https://registry.npm.alibaba-inc.com/@ant-design/react-slick/download/@ant-design/react-slick-0.29.2.tgz" integrity sha512-kgjtKmkGHa19FW21lHnAfyyH9AAoh35pBdcJ53rHmQ3O+cfFHGHnUbj/HFrRNJ5vIts09FKJVAD8RpaC+RaWfA== dependencies: "@babel/runtime" "^7.10.4" @@ -292,28 +525,293 @@ lodash "^4.17.21" resize-observer-polyfill "^1.5.1" +"@ant-design/react-slick@~1.0.0": + version "1.0.2" + resolved "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.0.2.tgz" + integrity sha512-Wj8onxL/T8KQLFFiCA4t8eIRGpRR+UPgOdac2sYzonv+i0n3kXHmvHLLiOYL655DQx2Umii9Y9nNgL7ssu5haQ== + dependencies: + "@babel/runtime" "^7.10.4" + classnames "^2.2.5" + json2mq "^0.2.0" + resize-observer-polyfill "^1.5.1" + throttle-debounce "^5.0.0" + +"@antv/algorithm@^0.1.8": + version "0.1.26" + resolved "https://registry.npmjs.org/@antv/algorithm/-/algorithm-0.1.26.tgz" + integrity sha512-DVhcFSQ8YQnMNW34Mk8BSsfc61iC1sAnmcfYoXTAshYHuU50p/6b7x3QYaGctDNKWGvi1ub7mPcSY0bK+aN0qg== + dependencies: + "@antv/util" "^2.0.13" + tslib "^2.0.0" + +"@antv/dom-util@^2.0.1", "@antv/dom-util@^2.0.2": + version "2.0.4" + resolved "https://registry.npmjs.org/@antv/dom-util/-/dom-util-2.0.4.tgz" + integrity sha512-2shXUl504fKwt82T3GkuT4Uoc6p9qjCKnJ8gXGLSW4T1W37dqf9AV28aCfoVPHp2BUXpSsB+PAJX2rG/jLHsLQ== + dependencies: + tslib "^2.0.3" + +"@antv/event-emitter@^0.1.1", "@antv/event-emitter@~0.1.0": + version "0.1.3" + resolved "https://registry.npmjs.org/@antv/event-emitter/-/event-emitter-0.1.3.tgz" + integrity sha512-4ddpsiHN9Pd4UIlWuKVK1C4IiZIdbwQvy9i7DUSI3xNJ89FPUFt8lxDYj8GzzfdllV0NkJTRxnG+FvLk0llidg== + +"@antv/g-base@^0.5.1", "@antv/g-base@^0.5.12": + version "0.5.15" + resolved "https://registry.npmjs.org/@antv/g-base/-/g-base-0.5.15.tgz" + integrity sha512-QOtq50QpnKez9J75/Z8j2yZ7QDQdk8R8mVQJiHtaEO5eI7DM4ZbrsWff/Ew26JYmPWdq7nbRuARMAD4PX9uuLA== + dependencies: + "@antv/event-emitter" "^0.1.1" + "@antv/g-math" "^0.1.9" + "@antv/matrix-util" "^3.1.0-beta.1" + "@antv/path-util" "~2.0.5" + "@antv/util" "~2.0.13" + "@types/d3-timer" "^2.0.0" + d3-ease "^1.0.5" + d3-interpolate "^3.0.1" + d3-timer "^1.0.9" + detect-browser "^5.1.0" + tslib "^2.0.3" + +"@antv/g-canvas@^0.5.2": + version "0.5.14" + resolved "https://registry.npmjs.org/@antv/g-canvas/-/g-canvas-0.5.14.tgz" + integrity sha512-IUGLEMIMAUYgaBMT8h3FTmYQYz7sjQkKWwh6Psqx+UPK86fySa+G8fMRrh1EqAL07jVB+GRnn6Ym+3FoFUgeFg== + dependencies: + "@antv/g-base" "^0.5.12" + "@antv/g-math" "^0.1.9" + "@antv/matrix-util" "^3.1.0-beta.1" + "@antv/path-util" "~2.0.5" + "@antv/util" "~2.0.0" + gl-matrix "^3.0.0" + tslib "^2.0.3" + +"@antv/g-math@^0.1.1", "@antv/g-math@^0.1.9": + version "0.1.9" + resolved "https://registry.npmjs.org/@antv/g-math/-/g-math-0.1.9.tgz" + integrity sha512-KHMSfPfZ5XHM1PZnG42Q2gxXfOitYveNTA7L61lR6mhZ8Y/aExsYmHqaKBsSarU0z+6WLrl9C07PQJZaw0uljQ== + dependencies: + "@antv/util" "~2.0.0" + gl-matrix "^3.0.0" + +"@antv/g-svg@^0.5.1", "@antv/g-svg@^0.5.2": + version "0.5.7" + resolved "https://registry.npmjs.org/@antv/g-svg/-/g-svg-0.5.7.tgz" + integrity sha512-jUbWoPgr4YNsOat2Y/rGAouNQYGpw4R0cvlN0YafwOyacFFYy2zC8RslNd6KkPhhR3XHNSqJOuCYZj/YmLUwYw== + dependencies: + "@antv/g-base" "^0.5.12" + "@antv/g-math" "^0.1.9" + "@antv/util" "~2.0.0" + detect-browser "^5.0.0" + tslib "^2.0.3" + +"@antv/g-webgpu-core@^0.7.2": + version "0.7.2" + resolved "https://registry.npmjs.org/@antv/g-webgpu-core/-/g-webgpu-core-0.7.2.tgz" + integrity sha512-xUMmop7f3Rs34zFYKXLqHhDR1CQTeDl/7vI7Sn3X/73BqJc3X3HIIRvm83Fg2CjVACaOzw4WeLRXNaOCp9fz9w== + dependencies: + eventemitter3 "^4.0.0" + gl-matrix "^3.1.0" + lodash "^4.17.15" + probe.gl "^3.1.1" + +"@antv/g-webgpu-engine@^0.7.2": + version "0.7.2" + resolved "https://registry.npmjs.org/@antv/g-webgpu-engine/-/g-webgpu-engine-0.7.2.tgz" + integrity sha512-lx8Y93IW2cnJvdoDRKyMmTdYqSC1pOmF0nyG3PGGyA0NI9vBYVgO0KTF6hkyWjdTWVq7XDZyf/h8CJridLh3lg== + dependencies: + "@antv/g-webgpu-core" "^0.7.2" + gl-matrix "^3.1.0" + lodash "^4.17.15" + regl "^1.3.11" + +"@antv/g-webgpu@0.7.2": + version "0.7.2" + resolved "https://registry.npmjs.org/@antv/g-webgpu/-/g-webgpu-0.7.2.tgz" + 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.1.0" + gl-vec2 "^1.3.0" + lodash "^4.17.15" + +"@antv/g6-core@0.8.22", "@antv/g6-core@^0.8.22": + version "0.8.22" + resolved "https://registry.npmjs.org/@antv/g6-core/-/g6-core-0.8.22.tgz" + integrity sha512-tH7fO/xCZQnkMqc3N3mkMMpYbOTrcnZChDoSCdDM8ttQ1imK0anObnhdnVkjess7zJ230ySsX8UaE+lzoKFSbg== + dependencies: + "@antv/algorithm" "^0.1.8" + "@antv/dom-util" "^2.0.1" + "@antv/event-emitter" "~0.1.0" + "@antv/g-base" "^0.5.1" + "@antv/g-math" "^0.1.1" + "@antv/matrix-util" "^3.1.0-beta.3" + "@antv/path-util" "^2.0.3" + "@antv/util" "~2.0.5" + ml-matrix "^6.5.0" + tslib "^2.1.0" + +"@antv/g6-element@0.8.22": + version "0.8.22" + resolved "https://registry.npmjs.org/@antv/g6-element/-/g6-element-0.8.22.tgz" + integrity sha512-rTJgaFDeaiHEF5d+hdJEGbh+Z272bi+Zzu5aTDWCtFFgxtosdeOQGWdyhIEeLCstRvlP3RaaztBIsSZm5BWFsA== + dependencies: + "@antv/g-base" "^0.5.1" + "@antv/g6-core" "0.8.22" + "@antv/util" "~2.0.5" + +"@antv/g6-pc@0.8.22": + version "0.8.22" + resolved "https://registry.npmjs.org/@antv/g6-pc/-/g6-pc-0.8.22.tgz" + integrity sha512-sG17yhA4lXyiLddL/IlCqysbxw3pRspukwaxJ6W5tfDAdM2o04Odf60ppvPekQh/EF6nIZ95qcDl03v3z6NXZw== + dependencies: + "@ant-design/colors" "^4.0.5" + "@antv/algorithm" "^0.1.8" + "@antv/dom-util" "^2.0.1" + "@antv/event-emitter" "~0.1.0" + "@antv/g-base" "^0.5.1" + "@antv/g-canvas" "^0.5.2" + "@antv/g-math" "^0.1.1" + "@antv/g-svg" "^0.5.1" + "@antv/g6-core" "^0.8.22" + "@antv/g6-element" "0.8.22" + "@antv/g6-plugin" "0.8.22" + "@antv/hierarchy" "^0.6.10" + "@antv/layout" "^0.3.0" + "@antv/matrix-util" "^3.1.0-beta.3" + "@antv/path-util" "^2.0.3" + "@antv/util" "~2.0.5" + color "^3.1.3" + d3-force "^2.0.1" + dagre "^0.8.5" + insert-css "^2.0.0" + ml-matrix "^6.5.0" + +"@antv/g6-plugin@0.8.22": + version "0.8.22" + resolved "https://registry.npmjs.org/@antv/g6-plugin/-/g6-plugin-0.8.22.tgz" + integrity sha512-3Z9hnNYwkJ7BAMLRoymWgrgTRXG7EDC2OlDAoRBSUvv/0sLVu7/kvobN3cY3rJF5rNwYmyTYb43ZfbK2UV4GVQ== + dependencies: + "@antv/dom-util" "^2.0.2" + "@antv/g-base" "^0.5.1" + "@antv/g-canvas" "^0.5.2" + "@antv/g-svg" "^0.5.2" + "@antv/g6-core" "0.8.22" + "@antv/g6-element" "0.8.22" + "@antv/matrix-util" "^3.1.0-beta.3" + "@antv/path-util" "^2.0.3" + "@antv/scale" "^0.3.4" + "@antv/util" "^2.0.9" + insert-css "^2.0.0" + +"@antv/g6@^4.8.22": + version "4.8.22" + resolved "https://registry.npmjs.org/@antv/g6/-/g6-4.8.22.tgz" + integrity sha512-ZbfmaK5H5vULGJUWZLIBJSorF3kSSeSZvvxbOJzzfB72zJ+Pjjtviq2BeiVV+HAZ3Ux7ogvIH6zcwRb1JrIO8g== + dependencies: + "@antv/g6-pc" "0.8.22" + +"@antv/graphlib@^1.0.0": + version "1.2.0" + resolved "https://registry.npmjs.org/@antv/graphlib/-/graphlib-1.2.0.tgz" + integrity sha512-hhJOMThec51nU4Fe5p/viLlNIL71uDEgYFzKPajWjr2715SFG1HAgiP6AVylIeqBcAZ04u3Lw7usjl/TuI5RuQ== + +"@antv/hierarchy@^0.6.10": + version "0.6.11" + resolved "https://registry.npmjs.org/@antv/hierarchy/-/hierarchy-0.6.11.tgz" + integrity sha512-RJVhEMCuu4vj+Dt25lXIiNdd7jaqm/fqWGYikiELha4S5tnzdJoTUaUvvpfWlxLx4B0RsS9XRwBs1bOKN71TKg== + dependencies: + "@antv/util" "^2.0.7" + +"@antv/layout@^0.3.0": + version "0.3.23" + resolved "https://registry.npmjs.org/@antv/layout/-/layout-0.3.23.tgz" + integrity sha512-F/CyfQuc1WSgCVemX0jA3pE3XuDRbDJmMueY1cL8WgL6nhdzm3/jg5UPamwbBVnhLk+rzNUDYdEIyX+RJbpcMA== + dependencies: + "@antv/g-webgpu" "0.7.2" + "@antv/graphlib" "^1.0.0" + "@antv/util" "^3.3.2" + d3-force "^2.1.1" + d3-quadtree "^2.0.0" + dagre-compound "^0.0.11" + ml-matrix "^6.5.0" + +"@antv/matrix-util@^3.0.4": + version "3.0.4" + resolved "https://registry.npmjs.org/@antv/matrix-util/-/matrix-util-3.0.4.tgz" + integrity sha512-BAPyu6dUliHcQ7fm9hZSGKqkwcjEDVLVAstlHULLvcMZvANHeLXgHEgV7JqcAV/GIhIz8aZChIlzM1ZboiXpYQ== + dependencies: + "@antv/util" "^2.0.9" + gl-matrix "^3.3.0" + tslib "^2.0.3" + +"@antv/matrix-util@^3.1.0-beta.1", "@antv/matrix-util@^3.1.0-beta.3": + version "3.1.0-beta.3" + resolved "https://registry.npmjs.org/@antv/matrix-util/-/matrix-util-3.1.0-beta.3.tgz" + integrity sha512-W2R6Za3A6CmG51Y/4jZUM/tFgYSq7vTqJL1VD9dKrvwxS4sE0ZcXINtkp55CdyBwJ6Cwm8pfoRpnD4FnHahN0A== + dependencies: + "@antv/util" "^2.0.9" + gl-matrix "^3.4.3" + tslib "^2.0.3" + +"@antv/path-util@^2.0.3", "@antv/path-util@~2.0.5": + version "2.0.15" + resolved "https://registry.npmjs.org/@antv/path-util/-/path-util-2.0.15.tgz" + integrity sha512-R2VLZ5C8PLPtr3VciNyxtjKqJ0XlANzpFb5sE9GE61UQqSRuSVSzIakMxjEPrpqbgc+s+y8i+fmc89Snu7qbNw== + dependencies: + "@antv/matrix-util" "^3.0.4" + "@antv/util" "^2.0.9" + tslib "^2.0.3" + +"@antv/scale@^0.3.4": + version "0.3.18" + resolved "https://registry.npmjs.org/@antv/scale/-/scale-0.3.18.tgz" + integrity sha512-GHwE6Lo7S/Q5fgaLPaCsW+CH+3zl4aXpnN1skOiEY0Ue9/u+s2EySv6aDXYkAqs//i0uilMDD/0/4n8caX9U9w== + dependencies: + "@antv/util" "~2.0.3" + fecha "~4.2.0" + tslib "^2.0.0" + +"@antv/util@^2.0.13", "@antv/util@^2.0.7", "@antv/util@^2.0.9", "@antv/util@~2.0.0", "@antv/util@~2.0.13", "@antv/util@~2.0.3", "@antv/util@~2.0.5": + version "2.0.17" + resolved "https://registry.npmjs.org/@antv/util/-/util-2.0.17.tgz" + integrity sha512-o6I9hi5CIUvLGDhth0RxNSFDRwXeywmt6ExR4+RmVAzIi48ps6HUy+svxOCayvrPBN37uE6TAc2KDofRo0nK9Q== + dependencies: + csstype "^3.0.8" + tslib "^2.0.3" + +"@antv/util@^3.3.2": + version "3.3.4" + resolved "https://registry.npmjs.org/@antv/util/-/util-3.3.4.tgz" + integrity sha512-NGRjPCPje8GIC14Ye7sjebamFIjxoZ+mCIqfXz6wD/M6fA9SgJivzmLB3Ry01Wq8PI36oOVv9BwrAGV1JD8vjA== + dependencies: + fast-deep-equal "^3.1.3" + gl-matrix "^3.3.0" + tslib "^2.3.1" + "@babel/code-frame@7.12.11": version "7.12.11" - resolved "https://registry.npm.alibaba-inc.com/@babel/code-frame/download/@babel/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + resolved "https://registry.npm.alibaba-inc.com/@babel/code-frame/download/@babel/code-frame-7.12.11.tgz" integrity sha1-9K1DWqJj25NbjxDyxVLSP7cWpj8= dependencies: "@babel/highlight" "^7.10.4" "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/code-frame/download/@babel/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + resolved "https://registry.npm.alibaba-inc.com/@babel/code-frame/download/@babel/code-frame-7.18.6.tgz" integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== dependencies: "@babel/highlight" "^7.18.6" "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.0", "@babel/compat-data@^7.20.1": version "7.20.1" - resolved "https://registry.npm.alibaba-inc.com/@babel/compat-data/download/@babel/compat-data-7.20.1.tgz#f2e6ef7790d8c8dbf03d379502dcc246dcce0b30" + resolved "https://registry.npm.alibaba-inc.com/@babel/compat-data/download/@babel/compat-data-7.20.1.tgz" integrity sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ== "@babel/core@7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/core/download/@babel/core-7.18.6.tgz#54a107a3c298aee3fe5e1947a6464b9b6faca03d" + resolved "https://registry.npm.alibaba-inc.com/@babel/core/download/@babel/core-7.18.6.tgz" integrity sha512-cQbWBpxcbbs/IUredIPkHiAGULLV8iwgNRMFzvbhEXISp4f3rUUXE5+TIw6KwUWUR3DwyI6gmBRnmAtYaWehwQ== dependencies: "@ampproject/remapping" "^2.1.0" @@ -334,7 +832,7 @@ "@babel/core@^7.1.0", "@babel/core@^7.12.10", "@babel/core@^7.12.16", "@babel/core@^7.12.3", "@babel/core@^7.17.9", "@babel/core@^7.7.5": version "7.20.2" - resolved "https://registry.npm.alibaba-inc.com/@babel/core/download/@babel/core-7.20.2.tgz#8dc9b1620a673f92d3624bd926dc49a52cf25b92" + resolved "https://registry.npm.alibaba-inc.com/@babel/core/download/@babel/core-7.20.2.tgz" integrity sha512-w7DbG8DtMrJcFOi4VrLm+8QM4az8Mo+PuLBKLp2zrYRCow8W/f9xiXm5sN53C8HksCyDQwCKha9JiDoIyPjT2g== dependencies: "@ampproject/remapping" "^2.1.0" @@ -355,7 +853,7 @@ "@babel/eslint-parser@^7.12.1", "@babel/eslint-parser@^7.12.16": version "7.19.1" - resolved "https://registry.npm.alibaba-inc.com/@babel/eslint-parser/download/@babel/eslint-parser-7.19.1.tgz#4f68f6b0825489e00a24b41b6a1ae35414ecd2f4" + resolved "https://registry.npm.alibaba-inc.com/@babel/eslint-parser/download/@babel/eslint-parser-7.19.1.tgz" integrity sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ== dependencies: "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" @@ -364,7 +862,7 @@ "@babel/generator@^7.18.6", "@babel/generator@^7.20.1", "@babel/generator@^7.20.2": version "7.20.4" - resolved "https://registry.npm.alibaba-inc.com/@babel/generator/download/@babel/generator-7.20.4.tgz#4d9f8f0c30be75fd90a0562099a26e5839602ab8" + resolved "https://registry.npm.alibaba-inc.com/@babel/generator/download/@babel/generator-7.20.4.tgz" integrity sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA== dependencies: "@babel/types" "^7.20.2" @@ -373,14 +871,14 @@ "@babel/helper-annotate-as-pure@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-annotate-as-pure/download/@babel/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-annotate-as-pure/download/@babel/helper-annotate-as-pure-7.18.6.tgz" integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== dependencies: "@babel/types" "^7.18.6" "@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": version "7.18.9" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-builder-binary-assignment-operator-visitor/download/@babel/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-builder-binary-assignment-operator-visitor/download/@babel/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz" integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw== dependencies: "@babel/helper-explode-assignable-expression" "^7.18.6" @@ -388,7 +886,7 @@ "@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.6", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.20.0": version "7.20.0" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-compilation-targets/download/@babel/helper-compilation-targets-7.20.0.tgz#6bf5374d424e1b3922822f1d9bdaa43b1a139d0a" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-compilation-targets/download/@babel/helper-compilation-targets-7.20.0.tgz" integrity sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ== dependencies: "@babel/compat-data" "^7.20.0" @@ -398,7 +896,7 @@ "@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.20.2": version "7.20.2" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-create-class-features-plugin/download/@babel/helper-create-class-features-plugin-7.20.2.tgz#3c08a5b5417c7f07b5cf3dfb6dc79cbec682e8c2" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-create-class-features-plugin/download/@babel/helper-create-class-features-plugin-7.20.2.tgz" integrity sha512-k22GoYRAHPYr9I+Gvy2ZQlAe5mGy8BqWst2wRt8cwIufWTxrsVshhIBvYNqC80N0GSFWTsqRVexOtfzlgOEDvA== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -411,7 +909,7 @@ "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.19.0": version "7.19.0" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-create-regexp-features-plugin/download/@babel/helper-create-regexp-features-plugin-7.19.0.tgz#7976aca61c0984202baca73d84e2337a5424a41b" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-create-regexp-features-plugin/download/@babel/helper-create-regexp-features-plugin-7.19.0.tgz" integrity sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -419,7 +917,7 @@ "@babel/helper-define-polyfill-provider@^0.3.3": version "0.3.3" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-define-polyfill-provider/download/@babel/helper-define-polyfill-provider-0.3.3.tgz#8612e55be5d51f0cd1f36b4a5a83924e89884b7a" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-define-polyfill-provider/download/@babel/helper-define-polyfill-provider-0.3.3.tgz" integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww== dependencies: "@babel/helper-compilation-targets" "^7.17.7" @@ -431,19 +929,19 @@ "@babel/helper-environment-visitor@^7.18.9": version "7.18.9" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-environment-visitor/download/@babel/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-environment-visitor/download/@babel/helper-environment-visitor-7.18.9.tgz" integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== "@babel/helper-explode-assignable-expression@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-explode-assignable-expression/download/@babel/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-explode-assignable-expression/download/@babel/helper-explode-assignable-expression-7.18.6.tgz" integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== dependencies: "@babel/types" "^7.18.6" "@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0": version "7.19.0" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-function-name/download/@babel/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-function-name/download/@babel/helper-function-name-7.19.0.tgz" integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== dependencies: "@babel/template" "^7.18.10" @@ -451,28 +949,28 @@ "@babel/helper-hoist-variables@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-hoist-variables/download/@babel/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-hoist-variables/download/@babel/helper-hoist-variables-7.18.6.tgz" integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== dependencies: "@babel/types" "^7.18.6" "@babel/helper-member-expression-to-functions@^7.18.9": version "7.18.9" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-member-expression-to-functions/download/@babel/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-member-expression-to-functions/download/@babel/helper-member-expression-to-functions-7.18.9.tgz" integrity sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg== dependencies: "@babel/types" "^7.18.9" "@babel/helper-module-imports@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-module-imports/download/@babel/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-module-imports/download/@babel/helper-module-imports-7.18.6.tgz" integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== dependencies: "@babel/types" "^7.18.6" "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.6", "@babel/helper-module-transforms@^7.20.2": version "7.20.2" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-module-transforms/download/@babel/helper-module-transforms-7.20.2.tgz#ac53da669501edd37e658602a21ba14c08748712" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-module-transforms/download/@babel/helper-module-transforms-7.20.2.tgz" integrity sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA== dependencies: "@babel/helper-environment-visitor" "^7.18.9" @@ -486,19 +984,19 @@ "@babel/helper-optimise-call-expression@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-optimise-call-expression/download/@babel/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-optimise-call-expression/download/@babel/helper-optimise-call-expression-7.18.6.tgz" integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== dependencies: "@babel/types" "^7.18.6" "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.20.2" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-plugin-utils/download/@babel/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-plugin-utils/download/@babel/helper-plugin-utils-7.20.2.tgz" integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== "@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9": version "7.18.9" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-remap-async-to-generator/download/@babel/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-remap-async-to-generator/download/@babel/helper-remap-async-to-generator-7.18.9.tgz" integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -508,7 +1006,7 @@ "@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.19.1": version "7.19.1" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-replace-supers/download/@babel/helper-replace-supers-7.19.1.tgz#e1592a9b4b368aa6bdb8784a711e0bcbf0612b78" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-replace-supers/download/@babel/helper-replace-supers-7.19.1.tgz" integrity sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw== dependencies: "@babel/helper-environment-visitor" "^7.18.9" @@ -519,43 +1017,43 @@ "@babel/helper-simple-access@^7.19.4", "@babel/helper-simple-access@^7.20.2": version "7.20.2" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-simple-access/download/@babel/helper-simple-access-7.20.2.tgz#0ab452687fe0c2cfb1e2b9e0015de07fc2d62dd9" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-simple-access/download/@babel/helper-simple-access-7.20.2.tgz" integrity sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA== dependencies: "@babel/types" "^7.20.2" "@babel/helper-skip-transparent-expression-wrappers@^7.18.9": version "7.20.0" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-skip-transparent-expression-wrappers/download/@babel/helper-skip-transparent-expression-wrappers-7.20.0.tgz#fbe4c52f60518cab8140d77101f0e63a8a230684" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-skip-transparent-expression-wrappers/download/@babel/helper-skip-transparent-expression-wrappers-7.20.0.tgz" integrity sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg== dependencies: "@babel/types" "^7.20.0" "@babel/helper-split-export-declaration@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-split-export-declaration/download/@babel/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-split-export-declaration/download/@babel/helper-split-export-declaration-7.18.6.tgz" integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== dependencies: "@babel/types" "^7.18.6" "@babel/helper-string-parser@^7.19.4": version "7.19.4" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-string-parser/download/@babel/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-string-parser/download/@babel/helper-string-parser-7.19.4.tgz" integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": version "7.19.1" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-validator-identifier/download/@babel/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-validator-identifier/download/@babel/helper-validator-identifier-7.19.1.tgz" integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== "@babel/helper-validator-option@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-validator-option/download/@babel/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-validator-option/download/@babel/helper-validator-option-7.18.6.tgz" integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== "@babel/helper-wrap-function@^7.18.9": version "7.19.0" - resolved "https://registry.npm.alibaba-inc.com/@babel/helper-wrap-function/download/@babel/helper-wrap-function-7.19.0.tgz#89f18335cff1152373222f76a4b37799636ae8b1" + resolved "https://registry.npm.alibaba-inc.com/@babel/helper-wrap-function/download/@babel/helper-wrap-function-7.19.0.tgz" integrity sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg== dependencies: "@babel/helper-function-name" "^7.19.0" @@ -565,7 +1063,7 @@ "@babel/helpers@^7.18.6", "@babel/helpers@^7.20.1": version "7.20.1" - resolved "https://registry.npm.alibaba-inc.com/@babel/helpers/download/@babel/helpers-7.20.1.tgz#2ab7a0fcb0a03b5bf76629196ed63c2d7311f4c9" + resolved "https://registry.npm.alibaba-inc.com/@babel/helpers/download/@babel/helpers-7.20.1.tgz" integrity sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg== dependencies: "@babel/template" "^7.18.10" @@ -574,7 +1072,7 @@ "@babel/highlight@^7.10.4", "@babel/highlight@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/highlight/download/@babel/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + resolved "https://registry.npm.alibaba-inc.com/@babel/highlight/download/@babel/highlight-7.18.6.tgz" integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== dependencies: "@babel/helper-validator-identifier" "^7.18.6" @@ -583,19 +1081,19 @@ "@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.18.10", "@babel/parser@^7.18.6", "@babel/parser@^7.20.1", "@babel/parser@^7.20.2": version "7.20.3" - resolved "https://registry.npm.alibaba-inc.com/@babel/parser/download/@babel/parser-7.20.3.tgz#5358cf62e380cf69efcb87a7bb922ff88bfac6e2" + resolved "https://registry.npm.alibaba-inc.com/@babel/parser/download/@babel/parser-7.20.3.tgz" integrity sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/download/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/download/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz" integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9": version "7.18.9" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/download/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz#a11af19aa373d68d561f08e0a57242350ed0ec50" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/download/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz" integrity sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg== dependencies: "@babel/helper-plugin-utils" "^7.18.9" @@ -604,7 +1102,7 @@ "@babel/plugin-proposal-async-generator-functions@^7.20.1": version "7.20.1" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-async-generator-functions/download/@babel/plugin-proposal-async-generator-functions-7.20.1.tgz#352f02baa5d69f4e7529bdac39aaa02d41146af9" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-async-generator-functions/download/@babel/plugin-proposal-async-generator-functions-7.20.1.tgz" integrity sha512-Gh5rchzSwE4kC+o/6T8waD0WHEQIsDmjltY8WnWRXHUdH8axZhuH86Ov9M72YhJfDrZseQwuuWaaIT/TmePp3g== dependencies: "@babel/helper-environment-visitor" "^7.18.9" @@ -614,7 +1112,7 @@ "@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-class-properties/download/@babel/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-class-properties/download/@babel/plugin-proposal-class-properties-7.18.6.tgz" integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== dependencies: "@babel/helper-create-class-features-plugin" "^7.18.6" @@ -622,7 +1120,7 @@ "@babel/plugin-proposal-class-static-block@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-class-static-block/download/@babel/plugin-proposal-class-static-block-7.18.6.tgz#8aa81d403ab72d3962fc06c26e222dacfc9b9020" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-class-static-block/download/@babel/plugin-proposal-class-static-block-7.18.6.tgz" integrity sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw== dependencies: "@babel/helper-create-class-features-plugin" "^7.18.6" @@ -631,7 +1129,7 @@ "@babel/plugin-proposal-decorators@^7.13.5": version "7.20.2" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-decorators/download/@babel/plugin-proposal-decorators-7.20.2.tgz#1c6c32b2a44b154ebeec2bb534f9eaebdb541fb6" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-decorators/download/@babel/plugin-proposal-decorators-7.20.2.tgz" integrity sha512-nkBH96IBmgKnbHQ5gXFrcmez+Z9S2EIDKDQGp005ROqBigc88Tky4rzCnlP/lnlj245dCEQl4/YyV0V1kYh5dw== dependencies: "@babel/helper-create-class-features-plugin" "^7.20.2" @@ -642,7 +1140,7 @@ "@babel/plugin-proposal-dynamic-import@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-dynamic-import/download/@babel/plugin-proposal-dynamic-import-7.18.6.tgz#72bcf8d408799f547d759298c3c27c7e7faa4d94" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-dynamic-import/download/@babel/plugin-proposal-dynamic-import-7.18.6.tgz" integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -650,7 +1148,7 @@ "@babel/plugin-proposal-export-namespace-from@^7.18.9": version "7.18.9" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-export-namespace-from/download/@babel/plugin-proposal-export-namespace-from-7.18.9.tgz#5f7313ab348cdb19d590145f9247540e94761203" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-export-namespace-from/download/@babel/plugin-proposal-export-namespace-from-7.18.9.tgz" integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA== dependencies: "@babel/helper-plugin-utils" "^7.18.9" @@ -658,7 +1156,7 @@ "@babel/plugin-proposal-json-strings@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-json-strings/download/@babel/plugin-proposal-json-strings-7.18.6.tgz#7e8788c1811c393aff762817e7dbf1ebd0c05f0b" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-json-strings/download/@babel/plugin-proposal-json-strings-7.18.6.tgz" integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -666,7 +1164,7 @@ "@babel/plugin-proposal-logical-assignment-operators@^7.18.9": version "7.18.9" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-logical-assignment-operators/download/@babel/plugin-proposal-logical-assignment-operators-7.18.9.tgz#8148cbb350483bf6220af06fa6db3690e14b2e23" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-logical-assignment-operators/download/@babel/plugin-proposal-logical-assignment-operators-7.18.9.tgz" integrity sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q== dependencies: "@babel/helper-plugin-utils" "^7.18.9" @@ -674,7 +1172,7 @@ "@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-nullish-coalescing-operator/download/@babel/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-nullish-coalescing-operator/download/@babel/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz" integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -682,7 +1180,7 @@ "@babel/plugin-proposal-numeric-separator@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-numeric-separator/download/@babel/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-numeric-separator/download/@babel/plugin-proposal-numeric-separator-7.18.6.tgz" integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -690,7 +1188,7 @@ "@babel/plugin-proposal-object-rest-spread@^7.20.2": version "7.20.2" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-object-rest-spread/download/@babel/plugin-proposal-object-rest-spread-7.20.2.tgz#a556f59d555f06961df1e572bb5eca864c84022d" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-object-rest-spread/download/@babel/plugin-proposal-object-rest-spread-7.20.2.tgz" integrity sha512-Ks6uej9WFK+fvIMesSqbAto5dD8Dz4VuuFvGJFKgIGSkJuRGcrwGECPA1fDgQK3/DbExBJpEkTeYeB8geIFCSQ== dependencies: "@babel/compat-data" "^7.20.1" @@ -701,7 +1199,7 @@ "@babel/plugin-proposal-optional-catch-binding@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-optional-catch-binding/download/@babel/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-optional-catch-binding/download/@babel/plugin-proposal-optional-catch-binding-7.18.6.tgz" integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -709,7 +1207,7 @@ "@babel/plugin-proposal-optional-chaining@^7.18.9": version "7.18.9" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-optional-chaining/download/@babel/plugin-proposal-optional-chaining-7.18.9.tgz#e8e8fe0723f2563960e4bf5e9690933691915993" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-optional-chaining/download/@babel/plugin-proposal-optional-chaining-7.18.9.tgz" integrity sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w== dependencies: "@babel/helper-plugin-utils" "^7.18.9" @@ -718,7 +1216,7 @@ "@babel/plugin-proposal-private-methods@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-private-methods/download/@babel/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-private-methods/download/@babel/plugin-proposal-private-methods-7.18.6.tgz" integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== dependencies: "@babel/helper-create-class-features-plugin" "^7.18.6" @@ -726,7 +1224,7 @@ "@babel/plugin-proposal-private-property-in-object@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-private-property-in-object/download/@babel/plugin-proposal-private-property-in-object-7.18.6.tgz#a64137b232f0aca3733a67eb1a144c192389c503" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-private-property-in-object/download/@babel/plugin-proposal-private-property-in-object-7.18.6.tgz" integrity sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -736,7 +1234,7 @@ "@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-unicode-property-regex/download/@babel/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-proposal-unicode-property-regex/download/@babel/plugin-proposal-unicode-property-regex-7.18.6.tgz" integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.18.6" @@ -744,154 +1242,154 @@ "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-async-generators/download/@babel/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-async-generators/download/@babel/plugin-syntax-async-generators-7.8.4.tgz" integrity sha1-qYP7Gusuw/btBCohD2QOkOeG/g0= dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-bigint@^7.8.3": version "7.8.3" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-bigint/download/@babel/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-bigint/download/@babel/plugin-syntax-bigint-7.8.3.tgz" integrity sha1-TJpvZp9dDN8bkKFnHpoUa+UwDOo= dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3": version "7.12.13" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-class-properties/download/@babel/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-class-properties/download/@babel/plugin-syntax-class-properties-7.12.13.tgz" integrity sha1-tcmHJ0xKOoK4lxR5aTGmtTVErhA= dependencies: "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-class-static-block@^7.14.5": version "7.14.5" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-class-static-block/download/@babel/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-class-static-block/download/@babel/plugin-syntax-class-static-block-7.14.5.tgz" integrity sha1-GV34mxRrS3izv4l/16JXyEZZ1AY= dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-decorators@^7.19.0": version "7.19.0" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-decorators/download/@babel/plugin-syntax-decorators-7.19.0.tgz#5f13d1d8fce96951bea01a10424463c9a5b3a599" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-decorators/download/@babel/plugin-syntax-decorators-7.19.0.tgz" integrity sha512-xaBZUEDntt4faL1yN8oIFlhfXeQAWJW7CLKYsHTUqriCUbj8xOra8bfxxKGi/UwExPFBuPdH4XfHc9rGQhrVkQ== dependencies: "@babel/helper-plugin-utils" "^7.19.0" "@babel/plugin-syntax-dynamic-import@^7.8.3": version "7.8.3" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-dynamic-import/download/@babel/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-dynamic-import/download/@babel/plugin-syntax-dynamic-import-7.8.3.tgz" integrity sha1-Yr+Ysto80h1iYVT8lu5bPLaOrLM= dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-export-namespace-from@^7.8.3": version "7.8.3" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-export-namespace-from/download/@babel/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-export-namespace-from/download/@babel/plugin-syntax-export-namespace-from-7.8.3.tgz" integrity sha1-AolkqbqA28CUyRXEh618TnpmRlo= dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-import-assertions@^7.20.0": version "7.20.0" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-import-assertions/download/@babel/plugin-syntax-import-assertions-7.20.0.tgz#bb50e0d4bea0957235390641209394e87bdb9cc4" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-import-assertions/download/@babel/plugin-syntax-import-assertions-7.20.0.tgz" integrity sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ== dependencies: "@babel/helper-plugin-utils" "^7.19.0" "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-import-meta/download/@babel/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-import-meta/download/@babel/plugin-syntax-import-meta-7.10.4.tgz" integrity sha1-7mATSMNw+jNNIge+FYd3SWUh/VE= dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-json-strings/download/@babel/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-json-strings/download/@babel/plugin-syntax-json-strings-7.8.3.tgz" integrity sha1-AcohtmjNghjJ5kDLbdiMVBKyyWo= dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-jsx@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-jsx/download/@babel/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-jsx/download/@babel/plugin-syntax-jsx-7.18.6.tgz" integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-logical-assignment-operators/download/@babel/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-logical-assignment-operators/download/@babel/plugin-syntax-logical-assignment-operators-7.10.4.tgz" integrity sha1-ypHvRjA1MESLkGZSusLp/plB9pk= dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-nullish-coalescing-operator/download/@babel/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-nullish-coalescing-operator/download/@babel/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" integrity sha1-Fn7XA2iIYIH3S1w2xlqIwDtm0ak= dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.3": version "7.10.4" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-numeric-separator/download/@babel/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-numeric-separator/download/@babel/plugin-syntax-numeric-separator-7.10.4.tgz" integrity sha1-ubBws+M1cM2f0Hun+pHA3Te5r5c= dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-object-rest-spread/download/@babel/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-object-rest-spread/download/@babel/plugin-syntax-object-rest-spread-7.8.3.tgz" integrity sha1-YOIl7cvZimQDMqLnLdPmbxr1WHE= dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding@^7.8.3": version "7.8.3" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-optional-catch-binding/download/@babel/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-optional-catch-binding/download/@babel/plugin-syntax-optional-catch-binding-7.8.3.tgz" integrity sha1-YRGiZbz7Ag6579D9/X0mQCue1sE= dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-chaining@^7.8.3": version "7.8.3" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-optional-chaining/download/@babel/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-optional-chaining/download/@babel/plugin-syntax-optional-chaining-7.8.3.tgz" integrity sha1-T2nCq5UWfgGAzVM2YT+MV4j31Io= dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-private-property-in-object@^7.14.5": version "7.14.5" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-private-property-in-object/download/@babel/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-private-property-in-object/download/@babel/plugin-syntax-private-property-in-object-7.14.5.tgz" integrity sha1-DcZnHsDqIrbpShEU+FeXDNOd4a0= dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-top-level-await@^7.14.5", "@babel/plugin-syntax-top-level-await@^7.8.3": version "7.14.5" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-top-level-await/download/@babel/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-top-level-await/download/@babel/plugin-syntax-top-level-await-7.14.5.tgz" integrity sha1-wc/a3DWmRiQAAfBhOCR7dBw02Uw= dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.20.0": version "7.20.0" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-typescript/download/@babel/plugin-syntax-typescript-7.20.0.tgz#4e9a0cfc769c85689b77a2e642d24e9f697fc8c7" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-syntax-typescript/download/@babel/plugin-syntax-typescript-7.20.0.tgz" integrity sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ== dependencies: "@babel/helper-plugin-utils" "^7.19.0" "@babel/plugin-transform-arrow-functions@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-arrow-functions/download/@babel/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-arrow-functions/download/@babel/plugin-transform-arrow-functions-7.18.6.tgz" integrity sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-async-to-generator@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-async-to-generator/download/@babel/plugin-transform-async-to-generator-7.18.6.tgz#ccda3d1ab9d5ced5265fdb13f1882d5476c71615" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-async-to-generator/download/@babel/plugin-transform-async-to-generator-7.18.6.tgz" integrity sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag== dependencies: "@babel/helper-module-imports" "^7.18.6" @@ -900,21 +1398,21 @@ "@babel/plugin-transform-block-scoped-functions@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-block-scoped-functions/download/@babel/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-block-scoped-functions/download/@babel/plugin-transform-block-scoped-functions-7.18.6.tgz" integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-block-scoping@^7.20.2": version "7.20.2" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-block-scoping/download/@babel/plugin-transform-block-scoping-7.20.2.tgz#f59b1767e6385c663fd0bce655db6ca9c8b236ed" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-block-scoping/download/@babel/plugin-transform-block-scoping-7.20.2.tgz" integrity sha512-y5V15+04ry69OV2wULmwhEA6jwSWXO1TwAtIwiPXcvHcoOQUqpyMVd2bDsQJMW8AurjulIyUV8kDqtjSwHy1uQ== dependencies: "@babel/helper-plugin-utils" "^7.20.2" "@babel/plugin-transform-classes@^7.20.2": version "7.20.2" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-classes/download/@babel/plugin-transform-classes-7.20.2.tgz#c0033cf1916ccf78202d04be4281d161f6709bb2" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-classes/download/@babel/plugin-transform-classes-7.20.2.tgz" integrity sha512-9rbPp0lCVVoagvtEyQKSo5L8oo0nQS/iif+lwlAz29MccX2642vWDlSZK+2T2buxbopotId2ld7zZAzRfz9j1g== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -929,21 +1427,21 @@ "@babel/plugin-transform-computed-properties@^7.18.9": version "7.18.9" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-computed-properties/download/@babel/plugin-transform-computed-properties-7.18.9.tgz#2357a8224d402dad623caf6259b611e56aec746e" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-computed-properties/download/@babel/plugin-transform-computed-properties-7.18.9.tgz" integrity sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-destructuring@^7.20.2": version "7.20.2" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-destructuring/download/@babel/plugin-transform-destructuring-7.20.2.tgz#c23741cfa44ddd35f5e53896e88c75331b8b2792" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-destructuring/download/@babel/plugin-transform-destructuring-7.20.2.tgz" integrity sha512-mENM+ZHrvEgxLTBXUiQ621rRXZes3KWUv6NdQlrnr1TkWVw+hUjQBZuP2X32qKlrlG2BzgR95gkuCRSkJl8vIw== dependencies: "@babel/helper-plugin-utils" "^7.20.2" "@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-dotall-regex/download/@babel/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-dotall-regex/download/@babel/plugin-transform-dotall-regex-7.18.6.tgz" integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.18.6" @@ -951,14 +1449,14 @@ "@babel/plugin-transform-duplicate-keys@^7.18.9": version "7.18.9" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-duplicate-keys/download/@babel/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-duplicate-keys/download/@babel/plugin-transform-duplicate-keys-7.18.9.tgz" integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-exponentiation-operator@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-exponentiation-operator/download/@babel/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-exponentiation-operator/download/@babel/plugin-transform-exponentiation-operator-7.18.6.tgz" integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== dependencies: "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" @@ -966,14 +1464,14 @@ "@babel/plugin-transform-for-of@^7.18.8": version "7.18.8" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-for-of/download/@babel/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-for-of/download/@babel/plugin-transform-for-of-7.18.8.tgz" integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-function-name@^7.18.9": version "7.18.9" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-function-name/download/@babel/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-function-name/download/@babel/plugin-transform-function-name-7.18.9.tgz" integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ== dependencies: "@babel/helper-compilation-targets" "^7.18.9" @@ -982,21 +1480,21 @@ "@babel/plugin-transform-literals@^7.18.9": version "7.18.9" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-literals/download/@babel/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-literals/download/@babel/plugin-transform-literals-7.18.9.tgz" integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-member-expression-literals@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-member-expression-literals/download/@babel/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-member-expression-literals/download/@babel/plugin-transform-member-expression-literals-7.18.6.tgz" integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-modules-amd@^7.19.6": version "7.19.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-modules-amd/download/@babel/plugin-transform-modules-amd-7.19.6.tgz#aca391801ae55d19c4d8d2ebfeaa33df5f2a2cbd" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-modules-amd/download/@babel/plugin-transform-modules-amd-7.19.6.tgz" integrity sha512-uG3od2mXvAtIFQIh0xrpLH6r5fpSQN04gIVovl+ODLdUMANokxQLZnPBHcjmv3GxRjnqwLuHvppjjcelqUFZvg== dependencies: "@babel/helper-module-transforms" "^7.19.6" @@ -1004,7 +1502,7 @@ "@babel/plugin-transform-modules-commonjs@^7.19.6": version "7.19.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-modules-commonjs/download/@babel/plugin-transform-modules-commonjs-7.19.6.tgz#25b32feef24df8038fc1ec56038917eacb0b730c" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-modules-commonjs/download/@babel/plugin-transform-modules-commonjs-7.19.6.tgz" integrity sha512-8PIa1ym4XRTKuSsOUXqDG0YaOlEuTVvHMe5JCfgBMOtHvJKw/4NGovEGN33viISshG/rZNVrACiBmPQLvWN8xQ== dependencies: "@babel/helper-module-transforms" "^7.19.6" @@ -1013,7 +1511,7 @@ "@babel/plugin-transform-modules-systemjs@^7.19.6": version "7.19.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-modules-systemjs/download/@babel/plugin-transform-modules-systemjs-7.19.6.tgz#59e2a84064b5736a4471b1aa7b13d4431d327e0d" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-modules-systemjs/download/@babel/plugin-transform-modules-systemjs-7.19.6.tgz" integrity sha512-fqGLBepcc3kErfR9R3DnVpURmckXP7gj7bAlrTQyBxrigFqszZCkFkcoxzCp2v32XmwXLvbw+8Yq9/b+QqksjQ== dependencies: "@babel/helper-hoist-variables" "^7.18.6" @@ -1023,7 +1521,7 @@ "@babel/plugin-transform-modules-umd@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-modules-umd/download/@babel/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-modules-umd/download/@babel/plugin-transform-modules-umd-7.18.6.tgz" integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ== dependencies: "@babel/helper-module-transforms" "^7.18.6" @@ -1031,7 +1529,7 @@ "@babel/plugin-transform-named-capturing-groups-regex@^7.19.1": version "7.19.1" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-named-capturing-groups-regex/download/@babel/plugin-transform-named-capturing-groups-regex-7.19.1.tgz#ec7455bab6cd8fb05c525a94876f435a48128888" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-named-capturing-groups-regex/download/@babel/plugin-transform-named-capturing-groups-regex-7.19.1.tgz" integrity sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.19.0" @@ -1039,14 +1537,14 @@ "@babel/plugin-transform-new-target@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-new-target/download/@babel/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-new-target/download/@babel/plugin-transform-new-target-7.18.6.tgz" integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-object-super@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-object-super/download/@babel/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-object-super/download/@babel/plugin-transform-object-super-7.18.6.tgz" integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -1054,35 +1552,35 @@ "@babel/plugin-transform-parameters@^7.20.1": version "7.20.3" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-parameters/download/@babel/plugin-transform-parameters-7.20.3.tgz#7b3468d70c3c5b62e46be0a47b6045d8590fb748" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-parameters/download/@babel/plugin-transform-parameters-7.20.3.tgz" integrity sha512-oZg/Fpx0YDrj13KsLyO8I/CX3Zdw7z0O9qOd95SqcoIzuqy/WTGWvePeHAnZCN54SfdyjHcb1S30gc8zlzlHcA== dependencies: "@babel/helper-plugin-utils" "^7.20.2" "@babel/plugin-transform-property-literals@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-property-literals/download/@babel/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-property-literals/download/@babel/plugin-transform-property-literals-7.18.6.tgz" integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-react-display-name@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-react-display-name/download/@babel/plugin-transform-react-display-name-7.18.6.tgz#8b1125f919ef36ebdfff061d664e266c666b9415" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-react-display-name/download/@babel/plugin-transform-react-display-name-7.18.6.tgz" integrity sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-react-jsx-development@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-react-jsx-development/download/@babel/plugin-transform-react-jsx-development-7.18.6.tgz#dbe5c972811e49c7405b630e4d0d2e1380c0ddc5" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-react-jsx-development/download/@babel/plugin-transform-react-jsx-development-7.18.6.tgz" integrity sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA== dependencies: "@babel/plugin-transform-react-jsx" "^7.18.6" "@babel/plugin-transform-react-jsx@^7.18.6": version "7.19.0" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-react-jsx/download/@babel/plugin-transform-react-jsx-7.19.0.tgz#b3cbb7c3a00b92ec8ae1027910e331ba5c500eb9" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-react-jsx/download/@babel/plugin-transform-react-jsx-7.19.0.tgz" integrity sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -1093,7 +1591,7 @@ "@babel/plugin-transform-react-pure-annotations@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-react-pure-annotations/download/@babel/plugin-transform-react-pure-annotations-7.18.6.tgz#561af267f19f3e5d59291f9950fd7b9663d0d844" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-react-pure-annotations/download/@babel/plugin-transform-react-pure-annotations-7.18.6.tgz" integrity sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -1101,7 +1599,7 @@ "@babel/plugin-transform-regenerator@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-regenerator/download/@babel/plugin-transform-regenerator-7.18.6.tgz#585c66cb84d4b4bf72519a34cfce761b8676ca73" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-regenerator/download/@babel/plugin-transform-regenerator-7.18.6.tgz" integrity sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -1109,21 +1607,21 @@ "@babel/plugin-transform-reserved-words@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-reserved-words/download/@babel/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-reserved-words/download/@babel/plugin-transform-reserved-words-7.18.6.tgz" integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-shorthand-properties@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-shorthand-properties/download/@babel/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-shorthand-properties/download/@babel/plugin-transform-shorthand-properties-7.18.6.tgz" integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-spread@^7.19.0": version "7.19.0" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-spread/download/@babel/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-spread/download/@babel/plugin-transform-spread-7.19.0.tgz" integrity sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w== dependencies: "@babel/helper-plugin-utils" "^7.19.0" @@ -1131,28 +1629,28 @@ "@babel/plugin-transform-sticky-regex@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-sticky-regex/download/@babel/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-sticky-regex/download/@babel/plugin-transform-sticky-regex-7.18.6.tgz" integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-template-literals@^7.18.9": version "7.18.9" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-template-literals/download/@babel/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-template-literals/download/@babel/plugin-transform-template-literals-7.18.9.tgz" integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-typeof-symbol@^7.18.9": version "7.18.9" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-typeof-symbol/download/@babel/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-typeof-symbol/download/@babel/plugin-transform-typeof-symbol-7.18.9.tgz" integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-typescript@^7.18.6": version "7.20.2" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-typescript/download/@babel/plugin-transform-typescript-7.20.2.tgz#91515527b376fc122ba83b13d70b01af8fe98f3f" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-typescript/download/@babel/plugin-transform-typescript-7.20.2.tgz" integrity sha512-jvS+ngBfrnTUBfOQq8NfGnSbF9BrqlR6hjJ2yVxMkmO5nL/cdifNbI30EfjRlN4g5wYWNnMPyj5Sa6R1pbLeag== dependencies: "@babel/helper-create-class-features-plugin" "^7.20.2" @@ -1161,14 +1659,14 @@ "@babel/plugin-transform-unicode-escapes@^7.18.10": version "7.18.10" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-unicode-escapes/download/@babel/plugin-transform-unicode-escapes-7.18.10.tgz#1ecfb0eda83d09bbcb77c09970c2dd55832aa246" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-unicode-escapes/download/@babel/plugin-transform-unicode-escapes-7.18.10.tgz" integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-unicode-regex@^7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-unicode-regex/download/@babel/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" + resolved "https://registry.npm.alibaba-inc.com/@babel/plugin-transform-unicode-regex/download/@babel/plugin-transform-unicode-regex-7.18.6.tgz" integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.18.6" @@ -1176,7 +1674,7 @@ "@babel/preset-env@^7.12.11": version "7.20.2" - resolved "https://registry.npm.alibaba-inc.com/@babel/preset-env/download/@babel/preset-env-7.20.2.tgz#9b1642aa47bb9f43a86f9630011780dab7f86506" + resolved "https://registry.npm.alibaba-inc.com/@babel/preset-env/download/@babel/preset-env-7.20.2.tgz" integrity sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg== dependencies: "@babel/compat-data" "^7.20.1" @@ -1257,7 +1755,7 @@ "@babel/preset-modules@^0.1.5": version "0.1.5" - resolved "https://registry.npm.alibaba-inc.com/@babel/preset-modules/download/@babel/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" + resolved "https://registry.npm.alibaba-inc.com/@babel/preset-modules/download/@babel/preset-modules-0.1.5.tgz" integrity sha1-75Odbn8miCfhhBY43G/5VRXhFdk= dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -1268,7 +1766,7 @@ "@babel/preset-react@^7.12.10": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/preset-react/download/@babel/preset-react-7.18.6.tgz#979f76d6277048dc19094c217b507f3ad517dd2d" + resolved "https://registry.npm.alibaba-inc.com/@babel/preset-react/download/@babel/preset-react-7.18.6.tgz" integrity sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -1280,7 +1778,7 @@ "@babel/preset-typescript@^7.12.7": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/preset-typescript/download/@babel/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399" + resolved "https://registry.npm.alibaba-inc.com/@babel/preset-typescript/download/@babel/preset-typescript-7.18.6.tgz" integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -1289,28 +1787,42 @@ "@babel/runtime@7.18.6": version "7.18.6" - resolved "https://registry.npm.alibaba-inc.com/@babel/runtime/download/@babel/runtime-7.18.6.tgz#6a1ef59f838debd670421f8c7f2cbb8da9751580" + resolved "https://registry.npm.alibaba-inc.com/@babel/runtime/download/@babel/runtime-7.18.6.tgz" integrity sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ== dependencies: regenerator-runtime "^0.13.4" "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.16.7", "@babel/runtime@^7.18.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.2.0", "@babel/runtime@^7.20.0", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": version "7.20.1" - resolved "https://registry.npm.alibaba-inc.com/@babel/runtime/download/@babel/runtime-7.20.1.tgz#1148bb33ab252b165a06698fde7576092a78b4a9" + resolved "https://registry.npm.alibaba-inc.com/@babel/runtime/download/@babel/runtime-7.20.1.tgz" integrity sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg== dependencies: regenerator-runtime "^0.13.10" -"@babel/runtime@^7.20.6", "@babel/runtime@^7.5.5": +"@babel/runtime@^7.20.13", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.5": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz" + integrity sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/runtime@^7.23.2": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.4.tgz#36fa1d2b36db873d25ec631dcc4923fdc1cf2e2e" + integrity sha512-2Yv65nlWnWlSpe3fXEyX5i7fx5kIKo4Qbcj+hMO0odwaneFjfXw5fdum+4yL20O0QiaHpia0cYQ9xpNMqrBwHg== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/runtime@^7.5.5": version "7.21.0" - resolved "https://registry.npm.alibaba-inc.com/@babel/runtime/download/@babel/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673" + resolved "https://registry.npm.alibaba-inc.com/@babel/runtime/download/@babel/runtime-7.21.0.tgz" integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw== dependencies: regenerator-runtime "^0.13.11" "@babel/template@^7.18.10", "@babel/template@^7.18.6", "@babel/template@^7.3.3": version "7.18.10" - resolved "https://registry.npm.alibaba-inc.com/@babel/template/download/@babel/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" + resolved "https://registry.npm.alibaba-inc.com/@babel/template/download/@babel/template-7.18.10.tgz" integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== dependencies: "@babel/code-frame" "^7.18.6" @@ -1319,7 +1831,7 @@ "@babel/traverse@^7.1.0", "@babel/traverse@^7.18.6", "@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.20.1": version "7.20.1" - resolved "https://registry.npm.alibaba-inc.com/@babel/traverse/download/@babel/traverse-7.20.1.tgz#9b15ccbf882f6d107eeeecf263fbcdd208777ec8" + resolved "https://registry.npm.alibaba-inc.com/@babel/traverse/download/@babel/traverse-7.20.1.tgz" integrity sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA== dependencies: "@babel/code-frame" "^7.18.6" @@ -1335,7 +1847,7 @@ "@babel/types@^7.0.0", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": version "7.20.2" - resolved "https://registry.npm.alibaba-inc.com/@babel/types/download/@babel/types-7.20.2.tgz#67ac09266606190f496322dbaff360fdaa5e7842" + resolved "https://registry.npm.alibaba-inc.com/@babel/types/download/@babel/types-7.20.2.tgz" integrity sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog== dependencies: "@babel/helper-string-parser" "^7.19.4" @@ -1344,17 +1856,25 @@ "@bcoe/v8-coverage@^0.2.3": version "0.2.3" - resolved "https://registry.npm.alibaba-inc.com/@bcoe/v8-coverage/download/@bcoe/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + resolved "https://registry.npm.alibaba-inc.com/@bcoe/v8-coverage/download/@bcoe/v8-coverage-0.2.3.tgz" integrity sha1-daLotRy3WKdVPWgEpZMteqznXDk= "@bloomberg/record-tuple-polyfill@0.0.3": version "0.0.3" - resolved "https://registry.npm.alibaba-inc.com/@bloomberg/record-tuple-polyfill/download/@bloomberg/record-tuple-polyfill-0.0.3.tgz#0b03d18b88a30894caab14abd669b1cbbf47b843" + resolved "https://registry.npm.alibaba-inc.com/@bloomberg/record-tuple-polyfill/download/@bloomberg/record-tuple-polyfill-0.0.3.tgz" integrity sha1-CwPRi4ijCJTKqxSr1mmxy79HuEM= +"@chenshuai2144/sketch-color@^1.0.7": + version "1.0.9" + resolved "https://registry.npmjs.org/@chenshuai2144/sketch-color/-/sketch-color-1.0.9.tgz" + integrity sha512-obzSy26cb7Pm7OprWyVpgMpIlrZpZ0B7vbrU0RMbvRg0YAI890S5Xy02Aj1Nhl4+KTbi1lVYHt6HQP8Hm9s+1w== + dependencies: + reactcss "^1.2.3" + tinycolor2 "^1.4.2" + "@chenshuai2144/sketch-color@^1.0.8": version "1.0.8" - resolved "https://registry.npm.alibaba-inc.com/@chenshuai2144/sketch-color/download/@chenshuai2144/sketch-color-1.0.8.tgz#5cde7ac1dae5687223a8f751b0e4f77a5776d566" + resolved "https://registry.npm.alibaba-inc.com/@chenshuai2144/sketch-color/download/@chenshuai2144/sketch-color-1.0.8.tgz" integrity sha512-dPAzzWc+w7zyTAi71WXYZpiTYyIS80MxYyy2E/7jufhnJI1Z29wCPL35VvuJ/gs5zYpF2+w/B7BizWa2zKXpGw== dependencies: reactcss "^1.2.3" @@ -1362,7 +1882,7 @@ "@cnakazawa/watch@^1.0.3": version "1.0.4" - resolved "https://registry.npm.alibaba-inc.com/@cnakazawa/watch/download/@cnakazawa/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" + resolved "https://registry.npm.alibaba-inc.com/@cnakazawa/watch/download/@cnakazawa/watch-1.0.4.tgz" integrity sha1-+GSuhQBND8q29QvpFBxNo2jRZWo= dependencies: exec-sh "^0.3.2" @@ -1370,27 +1890,71 @@ "@csstools/convert-colors@^1.4.0": version "1.4.0" - resolved "https://registry.npm.alibaba-inc.com/@csstools/convert-colors/download/@csstools/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" + resolved "https://registry.npm.alibaba-inc.com/@csstools/convert-colors/download/@csstools/convert-colors-1.4.0.tgz" integrity sha1-rUldxBsS511YjG24uYNPCPoTHrc= "@ctrl/tinycolor@^3.4.0": version "3.4.1" - resolved "https://registry.npm.alibaba-inc.com/@ctrl/tinycolor/download/@ctrl/tinycolor-3.4.1.tgz#75b4c27948c81e88ccd3a8902047bcd797f38d32" + resolved "https://registry.npm.alibaba-inc.com/@ctrl/tinycolor/download/@ctrl/tinycolor-3.4.1.tgz" integrity sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw== +"@ctrl/tinycolor@^3.6.0": + version "3.6.1" + resolved "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz" + integrity sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA== + +"@dnd-kit/accessibility@^3.0.0": + version "3.0.1" + resolved "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.0.1.tgz" + integrity sha512-HXRrwS9YUYQO9lFRc/49uO/VICbM+O+ZRpFDe9Pd1rwVv2PCNkRiTZRdxrDgng/UkvdC3Re9r2vwPpXXrWeFzg== + dependencies: + tslib "^2.0.0" + +"@dnd-kit/core@^6.0.8": + version "6.0.8" + resolved "https://registry.npmjs.org/@dnd-kit/core/-/core-6.0.8.tgz" + integrity sha512-lYaoP8yHTQSLlZe6Rr9qogouGUz9oRUj4AHhDQGQzq/hqaJRpFo65X+JKsdHf8oUFBzx5A+SJPUvxAwTF2OabA== + dependencies: + "@dnd-kit/accessibility" "^3.0.0" + "@dnd-kit/utilities" "^3.2.1" + tslib "^2.0.0" + +"@dnd-kit/modifiers@^6.0.1": + version "6.0.1" + resolved "https://registry.npmjs.org/@dnd-kit/modifiers/-/modifiers-6.0.1.tgz" + integrity sha512-rbxcsg3HhzlcMHVHWDuh9LCjpOVAgqbV78wLGI8tziXY3+qcMQ61qVXIvNKQFuhj75dSfD+o+PYZQ/NUk2A23A== + dependencies: + "@dnd-kit/utilities" "^3.2.1" + tslib "^2.0.0" + +"@dnd-kit/sortable@^7.0.2": + version "7.0.2" + resolved "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-7.0.2.tgz" + integrity sha512-wDkBHHf9iCi1veM834Gbk1429bd4lHX4RpAwT0y2cHLf246GAvU2sVw/oxWNpPKQNQRQaeGXhAVgrOl1IT+iyA== + dependencies: + "@dnd-kit/utilities" "^3.2.0" + tslib "^2.0.0" + +"@dnd-kit/utilities@^3.2.0", "@dnd-kit/utilities@^3.2.1": + version "3.2.1" + resolved "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.1.tgz" + integrity sha512-OOXqISfvBw/1REtkSK2N3Fi2EQiLMlWUlqnOK/UpOISqBZPWpE6TqL+jcPtMOkE8TqYGiURvRdPSI9hltNUjEA== + dependencies: + tslib "^2.0.0" + "@emotion/hash@^0.8.0": version "0.8.0" - resolved "https://registry.npm.alibaba-inc.com/@emotion/hash/download/@emotion/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" + resolved "https://registry.npm.alibaba-inc.com/@emotion/hash/download/@emotion/hash-0.8.0.tgz" integrity sha1-u7/2iXj+/b5ozLUzvIy+HRr7VBM= "@emotion/unitless@^0.7.5": version "0.7.5" - resolved "https://registry.npm.alibaba-inc.com/@emotion/unitless/download/@emotion/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" + resolved "https://registry.npm.alibaba-inc.com/@emotion/unitless/download/@emotion/unitless-0.7.5.tgz" integrity sha1-dyESkcGQCnALinjPr9oxYNdpSe0= "@eslint/eslintrc@^0.4.3": version "0.4.3" - resolved "https://registry.npm.alibaba-inc.com/@eslint/eslintrc/download/@eslint/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" + resolved "https://registry.npm.alibaba-inc.com/@eslint/eslintrc/download/@eslint/eslintrc-0.4.3.tgz" integrity sha1-nkKYHvA1vrPdSa3ResuW6P9vOUw= dependencies: ajv "^6.12.4" @@ -1405,12 +1969,12 @@ "@exodus/schemasafe@^1.0.0-rc.2": version "1.0.0-rc.9" - resolved "https://registry.npm.alibaba-inc.com/@exodus/schemasafe/download/@exodus/schemasafe-1.0.0-rc.9.tgz#56b9c6df627190f2dcda15f81f25d68826d9be4d" + resolved "https://registry.npm.alibaba-inc.com/@exodus/schemasafe/download/@exodus/schemasafe-1.0.0-rc.9.tgz" integrity sha512-dGGHpb61hLwifAu7sotuHFDBw6GTdpG8aKC0fsK17EuTzMRvUrH7lEAr6LTJ+sx3AZYed9yZ77rltVDHyg2hRg== "@formatjs/ecma402-abstract@1.14.3": version "1.14.3" - resolved "https://registry.npm.alibaba-inc.com/@formatjs/ecma402-abstract/download/@formatjs/ecma402-abstract-1.14.3.tgz#6428f243538a11126180d121ce8d4b2f17465738" + resolved "https://registry.npm.alibaba-inc.com/@formatjs/ecma402-abstract/download/@formatjs/ecma402-abstract-1.14.3.tgz" integrity sha512-SlsbRC/RX+/zg4AApWIFNDdkLtFbkq3LNoZWXZCE/nHVKqoIJyaoQyge/I0Y38vLxowUn9KTtXgusLD91+orbg== dependencies: "@formatjs/intl-localematcher" "0.2.32" @@ -1418,14 +1982,14 @@ "@formatjs/fast-memoize@2.0.1": version "2.0.1" - resolved "https://registry.npm.alibaba-inc.com/@formatjs/fast-memoize/download/@formatjs/fast-memoize-2.0.1.tgz#f15aaa73caad5562899c69bdcad8db82adcd3b0b" + resolved "https://registry.npm.alibaba-inc.com/@formatjs/fast-memoize/download/@formatjs/fast-memoize-2.0.1.tgz" integrity sha512-M2GgV+qJn5WJQAYewz7q2Cdl6fobQa69S1AzSM2y0P68ZDbK5cWrJIcPCO395Of1ksftGZoOt4LYCO/j9BKBSA== dependencies: tslib "^2.4.0" "@formatjs/icu-messageformat-parser@2.3.1": version "2.3.1" - resolved "https://registry.npm.alibaba-inc.com/@formatjs/icu-messageformat-parser/download/@formatjs/icu-messageformat-parser-2.3.1.tgz#953080ea5c053bc73bdf55d0a524a3c3c133ae6b" + resolved "https://registry.npm.alibaba-inc.com/@formatjs/icu-messageformat-parser/download/@formatjs/icu-messageformat-parser-2.3.1.tgz" integrity sha512-knF2AkAKN4Upv4oIiKY4Wd/dLH68TNMPgV/tJMu/T6FP9aQwbv8fpj7U3lkyniPaNVxvia56Gxax8MKOjtxLSQ== dependencies: "@formatjs/ecma402-abstract" "1.14.3" @@ -1434,7 +1998,7 @@ "@formatjs/icu-skeleton-parser@1.3.18": version "1.3.18" - resolved "https://registry.npm.alibaba-inc.com/@formatjs/icu-skeleton-parser/download/@formatjs/icu-skeleton-parser-1.3.18.tgz#7aed3d60e718c8ad6b0e64820be44daa1e29eeeb" + resolved "https://registry.npm.alibaba-inc.com/@formatjs/icu-skeleton-parser/download/@formatjs/icu-skeleton-parser-1.3.18.tgz" integrity sha512-ND1ZkZfmLPcHjAH1sVpkpQxA+QYfOX3py3SjKWMUVGDow18gZ0WPqz3F+pJLYQMpS2LnnQ5zYR2jPVYTbRwMpg== dependencies: "@formatjs/ecma402-abstract" "1.14.3" @@ -1442,7 +2006,7 @@ "@formatjs/intl-displaynames@6.3.1": version "6.3.1" - resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl-displaynames/download/@formatjs/intl-displaynames-6.3.1.tgz#6dcea7cb801460e2a8fa63eb38c54aa1b24f92c0" + resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl-displaynames/download/@formatjs/intl-displaynames-6.3.1.tgz" integrity sha512-TlxguMDUbnFrJ4NA8fSyqXC62M7czvlRJ5mrJgtB91JVA+QPjjNdcRm1qPIC/DcU/pGUDcEzThn/x5A+jp15gg== dependencies: "@formatjs/ecma402-abstract" "1.14.3" @@ -1451,14 +2015,14 @@ "@formatjs/intl-displaynames@^1.2.0": version "1.2.10" - resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl-displaynames/download/@formatjs/intl-displaynames-1.2.10.tgz#bb9625cca90b099978cd967c6a98aaf4e23fc878" + resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl-displaynames/download/@formatjs/intl-displaynames-1.2.10.tgz" integrity sha1-u5YlzKkLCZl4zZZ8apiq9OI/yHg= dependencies: "@formatjs/intl-utils" "^2.3.0" "@formatjs/intl-listformat@7.2.1": version "7.2.1" - resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl-listformat/download/@formatjs/intl-listformat-7.2.1.tgz#874eddc7d53ba2e3fd911bf30efc459fc99f08db" + resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl-listformat/download/@formatjs/intl-listformat-7.2.1.tgz" integrity sha512-fRJFWLrGa7d25I4JSxNjKX29oXGcIXx8fJjgURnvs2C3ijS4gurUgFrUwLbv/2KfPfyJ5g567pz2INelNJZBdw== dependencies: "@formatjs/ecma402-abstract" "1.14.3" @@ -1467,47 +2031,47 @@ "@formatjs/intl-listformat@^1.4.1": version "1.4.8" - resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl-listformat/download/@formatjs/intl-listformat-1.4.8.tgz#70b81005e7dcf74329cb5b314a940ce5fce36cd0" + resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl-listformat/download/@formatjs/intl-listformat-1.4.8.tgz" integrity sha1-cLgQBefc90Mpy1sxSpQM5fzjbNA= dependencies: "@formatjs/intl-utils" "^2.3.0" "@formatjs/intl-localematcher@0.2.32": version "0.2.32" - resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl-localematcher/download/@formatjs/intl-localematcher-0.2.32.tgz#00d4d307cd7d514b298e15a11a369b86c8933ec1" + resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl-localematcher/download/@formatjs/intl-localematcher-0.2.32.tgz" integrity sha512-k/MEBstff4sttohyEpXxCmC3MqbUn9VvHGlZ8fauLzkbwXmVrEeyzS+4uhrvAk9DWU9/7otYWxyDox4nT/KVLQ== dependencies: tslib "^2.4.0" "@formatjs/intl-pluralrules@^1.5.0": version "1.5.9" - resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl-pluralrules/download/@formatjs/intl-pluralrules-1.5.9.tgz#c363c833c0ccde11eb508de4c09d3eaa232e819a" + resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl-pluralrules/download/@formatjs/intl-pluralrules-1.5.9.tgz" integrity sha1-w2PIM8DM3hHrUI3kwJ0+qiMugZo= dependencies: "@formatjs/intl-utils" "^2.3.0" "@formatjs/intl-relativetimeformat@^4.5.7", "@formatjs/intl-relativetimeformat@^4.5.9": version "4.5.16" - resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl-relativetimeformat/download/@formatjs/intl-relativetimeformat-4.5.16.tgz#7449cef3213dd66d25924ca41f125f87b58df95a" + resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl-relativetimeformat/download/@formatjs/intl-relativetimeformat-4.5.16.tgz" integrity sha1-dEnO8yE91m0lkkykHxJfh7WN+Vo= dependencies: "@formatjs/intl-utils" "^2.3.0" "@formatjs/intl-unified-numberformat@^3.2.0": version "3.3.7" - resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl-unified-numberformat/download/@formatjs/intl-unified-numberformat-3.3.7.tgz#9995a24568908188e716d81a1de5b702b2ee00e2" + resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl-unified-numberformat/download/@formatjs/intl-unified-numberformat-3.3.7.tgz" integrity sha1-mZWiRWiQgYjnFtgaHeW3ArLuAOI= dependencies: "@formatjs/intl-utils" "^2.3.0" "@formatjs/intl-utils@^2.2.0", "@formatjs/intl-utils@^2.3.0": version "2.3.0" - resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl-utils/download/@formatjs/intl-utils-2.3.0.tgz#2dc8c57044de0340eb53a7ba602e59abf80dc799" + resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl-utils/download/@formatjs/intl-utils-2.3.0.tgz" integrity sha1-LcjFcETeA0DrU6e6YC5Zq/gNx5k= "@formatjs/intl@2.7.1": version "2.7.1" - resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl/download/@formatjs/intl-2.7.1.tgz#f7e052ff09e9fe019ad83d4139af0de40084a2ae" + resolved "https://registry.npm.alibaba-inc.com/@formatjs/intl/download/@formatjs/intl-2.7.1.tgz" integrity sha512-se6vxidsN3PCmzqTsDd3YDT4IX9ZySPy39LYhF7x2ssNvlGMOuW3umkrIhKkXB7ZskqsJGY53LVCdiHsSwhGng== dependencies: "@formatjs/ecma402-abstract" "1.14.3" @@ -1520,7 +2084,7 @@ "@humanwhocodes/config-array@^0.5.0": version "0.5.0" - resolved "https://registry.npm.alibaba-inc.com/@humanwhocodes/config-array/download/@humanwhocodes/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" + resolved "https://registry.npm.alibaba-inc.com/@humanwhocodes/config-array/download/@humanwhocodes/config-array-0.5.0.tgz" integrity sha1-FAeWfUxu7Nc4j4Os8er00Mbljvk= dependencies: "@humanwhocodes/object-schema" "^1.2.0" @@ -1529,12 +2093,12 @@ "@humanwhocodes/object-schema@^1.2.0": version "1.2.1" - resolved "https://registry.npm.alibaba-inc.com/@humanwhocodes/object-schema/download/@humanwhocodes/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + resolved "https://registry.npm.alibaba-inc.com/@humanwhocodes/object-schema/download/@humanwhocodes/object-schema-1.2.1.tgz" integrity sha1-tSBSnsIdjllFoYUd/Rwy6U45/0U= "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/@istanbuljs/load-nyc-config/download/@istanbuljs/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + resolved "https://registry.npm.alibaba-inc.com/@istanbuljs/load-nyc-config/download/@istanbuljs/load-nyc-config-1.1.0.tgz" integrity sha1-/T2x1Z7PfPEh6AZQu4ZxL5tV7O0= dependencies: camelcase "^5.3.1" @@ -1545,12 +2109,12 @@ "@istanbuljs/schema@^0.1.2": version "0.1.3" - resolved "https://registry.npm.alibaba-inc.com/@istanbuljs/schema/download/@istanbuljs/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + resolved "https://registry.npm.alibaba-inc.com/@istanbuljs/schema/download/@istanbuljs/schema-0.1.3.tgz" integrity sha1-5F44TkuOwWvOL9kDr3hFD2v37Jg= "@jest/console@^26.6.2": version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/@jest/console/download/@jest/console-26.6.2.tgz#4e04bc464014358b03ab4937805ee36a0aeb98f2" + resolved "https://registry.npm.alibaba-inc.com/@jest/console/download/@jest/console-26.6.2.tgz" integrity sha1-TgS8RkAUNYsDq0k3gF7jagrrmPI= dependencies: "@jest/types" "^26.6.2" @@ -1562,7 +2126,7 @@ "@jest/core@^26.6.3": version "26.6.3" - resolved "https://registry.npm.alibaba-inc.com/@jest/core/download/@jest/core-26.6.3.tgz#7639fcb3833d748a4656ada54bde193051e45fad" + resolved "https://registry.npm.alibaba-inc.com/@jest/core/download/@jest/core-26.6.3.tgz" integrity sha1-djn8s4M9dIpGVq2lS94ZMFHkX60= dependencies: "@jest/console" "^26.6.2" @@ -1596,7 +2160,7 @@ "@jest/environment@^26.6.2": version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/@jest/environment/download/@jest/environment-26.6.2.tgz#ba364cc72e221e79cc8f0a99555bf5d7577cf92c" + resolved "https://registry.npm.alibaba-inc.com/@jest/environment/download/@jest/environment-26.6.2.tgz" integrity sha1-ujZMxy4iHnnMjwqZVVv111d8+Sw= dependencies: "@jest/fake-timers" "^26.6.2" @@ -1606,7 +2170,7 @@ "@jest/fake-timers@^26.6.2": version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/@jest/fake-timers/download/@jest/fake-timers-26.6.2.tgz#459c329bcf70cee4af4d7e3f3e67848123535aad" + resolved "https://registry.npm.alibaba-inc.com/@jest/fake-timers/download/@jest/fake-timers-26.6.2.tgz" integrity sha1-RZwym89wzuSvTX4/PmeEgSNTWq0= dependencies: "@jest/types" "^26.6.2" @@ -1618,7 +2182,7 @@ "@jest/globals@^26.6.2": version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/@jest/globals/download/@jest/globals-26.6.2.tgz#5b613b78a1aa2655ae908eba638cc96a20df720a" + resolved "https://registry.npm.alibaba-inc.com/@jest/globals/download/@jest/globals-26.6.2.tgz" integrity sha1-W2E7eKGqJlWukI66Y4zJaiDfcgo= dependencies: "@jest/environment" "^26.6.2" @@ -1627,7 +2191,7 @@ "@jest/reporters@^26.6.2": version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/@jest/reporters/download/@jest/reporters-26.6.2.tgz#1f518b99637a5f18307bd3ecf9275f6882a667f6" + resolved "https://registry.npm.alibaba-inc.com/@jest/reporters/download/@jest/reporters-26.6.2.tgz" integrity sha1-H1GLmWN6Xxgwe9Ps+SdfaIKmZ/Y= dependencies: "@bcoe/v8-coverage" "^0.2.3" @@ -1659,7 +2223,7 @@ "@jest/source-map@^26.6.2": version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/@jest/source-map/download/@jest/source-map-26.6.2.tgz#29af5e1e2e324cafccc936f218309f54ab69d535" + resolved "https://registry.npm.alibaba-inc.com/@jest/source-map/download/@jest/source-map-26.6.2.tgz" integrity sha1-Ka9eHi4yTK/MyTbyGDCfVKtp1TU= dependencies: callsites "^3.0.0" @@ -1668,7 +2232,7 @@ "@jest/test-result@^26.6.2": version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/@jest/test-result/download/@jest/test-result-26.6.2.tgz#55da58b62df134576cc95476efa5f7949e3f5f18" + resolved "https://registry.npm.alibaba-inc.com/@jest/test-result/download/@jest/test-result-26.6.2.tgz" integrity sha1-VdpYti3xNFdsyVR276X3lJ4/Xxg= dependencies: "@jest/console" "^26.6.2" @@ -1678,7 +2242,7 @@ "@jest/test-sequencer@^26.6.3": version "26.6.3" - resolved "https://registry.npm.alibaba-inc.com/@jest/test-sequencer/download/@jest/test-sequencer-26.6.3.tgz#98e8a45100863886d074205e8ffdc5a7eb582b17" + resolved "https://registry.npm.alibaba-inc.com/@jest/test-sequencer/download/@jest/test-sequencer-26.6.3.tgz" integrity sha1-mOikUQCGOIbQdCBej/3Fp+tYKxc= dependencies: "@jest/test-result" "^26.6.2" @@ -1689,7 +2253,7 @@ "@jest/transform@^26.6.2": version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/@jest/transform/download/@jest/transform-26.6.2.tgz#5ac57c5fa1ad17b2aae83e73e45813894dcf2e4b" + resolved "https://registry.npm.alibaba-inc.com/@jest/transform/download/@jest/transform-26.6.2.tgz" integrity sha1-WsV8X6GtF7Kq6D5z5FgTiU3PLks= dependencies: "@babel/core" "^7.1.0" @@ -1710,7 +2274,7 @@ "@jest/types@^26.6.2": version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/@jest/types/download/@jest/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" + resolved "https://registry.npm.alibaba-inc.com/@jest/types/download/@jest/types-26.6.2.tgz" integrity sha1-vvWlMgMOHYii9abZM/hOlyJu1I4= dependencies: "@types/istanbul-lib-coverage" "^2.0.0" @@ -1721,7 +2285,7 @@ "@jridgewell/gen-mapping@^0.1.0": version "0.1.1" - resolved "https://registry.npm.alibaba-inc.com/@jridgewell/gen-mapping/download/@jridgewell/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" + resolved "https://registry.npm.alibaba-inc.com/@jridgewell/gen-mapping/download/@jridgewell/gen-mapping-0.1.1.tgz" integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== dependencies: "@jridgewell/set-array" "^1.0.0" @@ -1729,7 +2293,7 @@ "@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": version "0.3.2" - resolved "https://registry.npm.alibaba-inc.com/@jridgewell/gen-mapping/download/@jridgewell/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + resolved "https://registry.npm.alibaba-inc.com/@jridgewell/gen-mapping/download/@jridgewell/gen-mapping-0.3.2.tgz" integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== dependencies: "@jridgewell/set-array" "^1.0.1" @@ -1738,17 +2302,17 @@ "@jridgewell/resolve-uri@3.1.0": version "3.1.0" - resolved "https://registry.npm.alibaba-inc.com/@jridgewell/resolve-uri/download/@jridgewell/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + resolved "https://registry.npm.alibaba-inc.com/@jridgewell/resolve-uri/download/@jridgewell/resolve-uri-3.1.0.tgz" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== "@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": version "1.1.2" - resolved "https://registry.npm.alibaba-inc.com/@jridgewell/set-array/download/@jridgewell/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + resolved "https://registry.npm.alibaba-inc.com/@jridgewell/set-array/download/@jridgewell/set-array-1.1.2.tgz" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== "@jridgewell/source-map@^0.3.2": version "0.3.2" - resolved "https://registry.npm.alibaba-inc.com/@jridgewell/source-map/download/@jridgewell/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + resolved "https://registry.npm.alibaba-inc.com/@jridgewell/source-map/download/@jridgewell/source-map-0.3.2.tgz" integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== dependencies: "@jridgewell/gen-mapping" "^0.3.0" @@ -1756,27 +2320,35 @@ "@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.14" - resolved "https://registry.npm.alibaba-inc.com/@jridgewell/sourcemap-codec/download/@jridgewell/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + resolved "https://registry.npm.alibaba-inc.com/@jridgewell/sourcemap-codec/download/@jridgewell/sourcemap-codec-1.4.14.tgz" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== "@jridgewell/trace-mapping@^0.3.9": version "0.3.17" - resolved "https://registry.npm.alibaba-inc.com/@jridgewell/trace-mapping/download/@jridgewell/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + resolved "https://registry.npm.alibaba-inc.com/@jridgewell/trace-mapping/download/@jridgewell/trace-mapping-0.3.17.tgz" integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== dependencies: "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" +"@mrmlnc/readdir-enhanced@^2.2.1": + version "2.2.1" + resolved "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz" + integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== + dependencies: + call-me-maybe "^1.0.1" + glob-to-regexp "^0.3.0" + "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": version "5.1.1-v1" - resolved "https://registry.npm.alibaba-inc.com/@nicolo-ribaudo/eslint-scope-5-internals/download/@nicolo-ribaudo/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" + resolved "https://registry.npm.alibaba-inc.com/@nicolo-ribaudo/eslint-scope-5-internals/download/@nicolo-ribaudo/eslint-scope-5-internals-5.1.1-v1.tgz" integrity sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg== dependencies: eslint-scope "5.1.1" "@nodelib/fs.scandir@2.1.5": version "2.1.5" - resolved "https://registry.npm.alibaba-inc.com/@nodelib/fs.scandir/download/@nodelib/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + resolved "https://registry.npm.alibaba-inc.com/@nodelib/fs.scandir/download/@nodelib/fs.scandir-2.1.5.tgz" integrity sha1-dhnC6yGyVIP20WdUi0z9WnSIw9U= dependencies: "@nodelib/fs.stat" "2.0.5" @@ -1784,41 +2356,186 @@ "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" - resolved "https://registry.npm.alibaba-inc.com/@nodelib/fs.stat/download/@nodelib/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + resolved "https://registry.npm.alibaba-inc.com/@nodelib/fs.stat/download/@nodelib/fs.stat-2.0.5.tgz" integrity sha1-W9Jir5Tp0lvR5xsF3u1Eh2oiLos= +"@nodelib/fs.stat@^1.1.2": + version "1.1.3" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz" + integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== + "@nodelib/fs.walk@^1.2.3": version "1.2.8" - resolved "https://registry.npm.alibaba-inc.com/@nodelib/fs.walk/download/@nodelib/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + resolved "https://registry.npm.alibaba-inc.com/@nodelib/fs.walk/download/@nodelib/fs.walk-1.2.8.tgz" integrity sha1-6Vc36LtnRt3t9pxVaVNJTxlv5po= dependencies: "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@oceanbase/design@^0.2.16", "@oceanbase/design@^0.2.2": + version "0.2.16" + resolved "https://registry.yarnpkg.com/@oceanbase/design/-/design-0.2.16.tgz#8ec998b4c42ecdfa7dfb19e7d90247c09119709c" + integrity sha512-eNvfPEcuYNUkBUYPvzvTStfuGCYqf/0J7nV4S+Ob8aiqge2Z4r1GwX0ppyHAsc1ayytIT8M7TeiJEi2XlG70WQ== + dependencies: + "@ant-design/cssinjs" "^1.17.0" + "@oceanbase/icons" "^0.2.5" + "@oceanbase/util" "^0.2.7" + ahooks "^2.10.14" + antd "^5.9.0" + classnames "^2.3.2" + lodash "^4.17.21" + lottie-web "^5.12.2" + rc-util "^5.37.0" + react-sticky-mouse-tooltip "^0.0.1" + +"@oceanbase/icons-svg@^1.0.4": + version "1.0.4" + resolved "https://registry.npmjs.org/@oceanbase/icons-svg/-/icons-svg-1.0.4.tgz" + integrity sha512-//eUuFLR6+re1Ch0vit/3zoJ1jlygAQQOeRxjx3hDsfAV2QuBp5XlR9LjWAOsqIe6TyT6cnVC++nbWp/3Xc6Mg== + dependencies: + "@rgrove/parse-xml" "^2.0.2" + chalk "^4.1.0" + cpy "^8.1.2" + globby "^11.0.0" + insert-css "^2.0.0" + lodash.camelcase "^4.3.0" + lodash.template "^4.5.0" + lodash.upperfirst "^4.3.1" + ramda "^0.27.0" + svgo "^1.3.2" + yargs "^17.0.0-candidate.0" + +"@oceanbase/icons@^0.2.0", "@oceanbase/icons@^0.2.5": + version "0.2.5" + resolved "https://registry.npmjs.org/@oceanbase/icons/-/icons-0.2.5.tgz" + integrity sha512-99Gi/IN9BDICaHv0axDi0CqjOpIAhzjRB0hsX0JIBqqvhVxp5qavRF+M00cySDjXwVfwVqKu59ZeZL2sMb/tVg== + dependencies: + "@ant-design/colors" "^7.0.0" + "@ant-design/icons" "^5.2.6" + "@oceanbase/icons-svg" "^1.0.4" + +"@oceanbase/ui@^0.2.2": + version "0.2.17" + resolved "https://registry.yarnpkg.com/@oceanbase/ui/-/ui-0.2.17.tgz#424d75eaf7b05f2ec8f521e1f295ed4660fdb2a0" + integrity sha512-dNw0ILafHxolnK2Dz1WlsjvdqyEwOnhcu5fe2TUIFkRX8OlSrM5RcNfCWV/v5f3V6LFKZ3X3zSmXzM6t0cIpqg== + dependencies: + "@ant-design/cssinjs" "^1.17.0" + "@ant-design/pro-components" "^2.6.16" + "@oceanbase/design" "^0.2.16" + "@oceanbase/icons" "^0.2.5" + "@oceanbase/util" "^0.2.7" + ahooks "^2.10.14" + classnames "^2.3.2" + dayjs "^1.11.9" + diff "^5.1.0" + highlight.js "^11.8.0" + highlightjs-solidity "^2.0.6" + hoist-non-react-statics "^3.3.2" + lodash "^4.17.21" + lottie-web "^5.12.2" + moment "^2.29.4" + path-to-regexp "^6.2.1" + randexp "^0.5.3" + rc-util "^5.37.0" + react-copy-to-clipboard "^5.1.0" + react-json-view "^1.21.3" + react-split-pane "^0.1.92" + screenfull "^6.0.2" + +"@oceanbase/util@^0.2.1", "@oceanbase/util@^0.2.7": + version "0.2.7" + resolved "https://registry.npmjs.org/@oceanbase/util/-/util-0.2.7.tgz" + integrity sha512-w3OlF3i6eBt7Kx/dny2D6BKfpPBP0ko1Nj6Lu81yR3f9I2wQIk6GPewyjqYWYfY0YKv2LzlUUaOYmOWSIB45uA== + dependencies: + ahooks "^2.10.14" + filesize "^10.0.12" + is-url "^1.2.4" + lodash "^4.17.21" + moment "^2.29.4" + query-string "^8.1.0" + +"@probe.gl/env@3.6.0": + version "3.6.0" + resolved "https://registry.npmjs.org/@probe.gl/env/-/env-3.6.0.tgz" + integrity sha512-4tTZYUg/8BICC3Yyb9rOeoKeijKbZHRXBEKObrfPmX4sQmYB15ZOUpoVBhAyJkOYVAM8EkPci6Uw5dLCwx2BEQ== + dependencies: + "@babel/runtime" "^7.0.0" + +"@probe.gl/log@3.6.0": + version "3.6.0" + resolved "https://registry.npmjs.org/@probe.gl/log/-/log-3.6.0.tgz" + integrity sha512-hjpyenpEvOdowgZ1qMeCJxfRD4JkKdlXz0RC14m42Un62NtOT+GpWyKA4LssT0+xyLULCByRAtG2fzZorpIAcA== + dependencies: + "@babel/runtime" "^7.0.0" + "@probe.gl/env" "3.6.0" + +"@probe.gl/stats@3.6.0": + version "3.6.0" + resolved "https://registry.npmjs.org/@probe.gl/stats/-/stats-3.6.0.tgz" + integrity sha512-JdALQXB44OP4kUBN/UrQgzbJe4qokbVF4Y8lkIA8iVCFnjVowWIgkD/z/0QO65yELT54tTrtepw1jScjKB+rhQ== + dependencies: + "@babel/runtime" "^7.0.0" + "@qixian.cs/path-to-regexp@^6.1.0": version "6.1.0" - resolved "https://registry.npm.alibaba-inc.com/@qixian.cs/path-to-regexp/download/@qixian.cs/path-to-regexp-6.1.0.tgz#6b84ad01596332aba95fa29d2e70104698cd5c45" + resolved "https://registry.npm.alibaba-inc.com/@qixian.cs/path-to-regexp/download/@qixian.cs/path-to-regexp-6.1.0.tgz" integrity sha1-a4StAVljMqupX6KdLnAQRpjNXEU= +"@rc-component/color-picker@~1.4.1": + version "1.4.1" + resolved "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-1.4.1.tgz" + integrity sha512-vh5EWqnsayZa/JwUznqDaPJz39jznx/YDbyBuVJntv735tKXKwEUZZb2jYEldOg+NKWZwtALjGMrNeGBmqFoEw== + dependencies: + "@babel/runtime" "^7.10.1" + "@ctrl/tinycolor" "^3.6.0" + classnames "^2.2.6" + rc-util "^5.30.0" + +"@rc-component/context@^1.4.0": + version "1.4.0" + resolved "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz" + integrity sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w== + dependencies: + "@babel/runtime" "^7.10.1" + rc-util "^5.27.0" + "@rc-component/mini-decimal@^1.0.1": version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/@rc-component/mini-decimal/download/@rc-component/mini-decimal-1.0.1.tgz#e5dbc20a6a5b0e234d279bc71ce730ab865d3910" + resolved "https://registry.npm.alibaba-inc.com/@rc-component/mini-decimal/download/@rc-component/mini-decimal-1.0.1.tgz" integrity sha512-9N8nRk0oKj1qJzANKl+n9eNSMUGsZtjwNuDCiZ/KA+dt1fE3zq5x2XxclRcAbOIXnZcJ53ozP2Pa60gyELXagA== dependencies: "@babel/runtime" "^7.18.0" +"@rc-component/mutate-observer@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz" + integrity sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw== + dependencies: + "@babel/runtime" "^7.18.0" + classnames "^2.3.2" + rc-util "^5.24.4" + "@rc-component/portal@^1.0.0-6", "@rc-component/portal@^1.0.0-8", "@rc-component/portal@^1.0.0-9", "@rc-component/portal@^1.0.2": version "1.0.3" - resolved "https://registry.npm.alibaba-inc.com/@rc-component/portal/download/@rc-component/portal-1.0.3.tgz#3aa2c229a7a20ac2412d864e8977e6377973416e" + resolved "https://registry.npm.alibaba-inc.com/@rc-component/portal/download/@rc-component/portal-1.0.3.tgz" integrity sha512-rG9j7OMiI9eLFLF6G0B4OcfLac9W8Z7Vjeizbjt/A6R+zzw7vhHbJ4GIkrDpUqXDvFdEEzdxfICpb8/noLwG+w== dependencies: "@babel/runtime" "^7.18.0" classnames "^2.3.2" rc-util "^5.24.4" +"@rc-component/portal@^1.1.0", "@rc-component/portal@^1.1.1": + version "1.1.2" + resolved "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz" + integrity sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg== + dependencies: + "@babel/runtime" "^7.18.0" + classnames "^2.3.2" + rc-util "^5.24.4" + "@rc-component/tour@~1.0.1-2": version "1.0.1-2" - resolved "https://registry.npm.alibaba-inc.com/@rc-component/tour/download/@rc-component/tour-1.0.1-2.tgz#4f1be395b586bcbd9fbb29919c100932f7e355e6" + resolved "https://registry.npm.alibaba-inc.com/@rc-component/tour/download/@rc-component/tour-1.0.1-2.tgz" integrity sha512-vnCkEO46mmrkgZZZz1cOm61PyNeTc1JaJYKXx/HnrxIcfZiPQgL0jmSoXENBlMWQeJMZvbH+LwEZmLqSnjl3jg== dependencies: "@babel/runtime" "^7.18.0" @@ -1827,30 +2544,59 @@ rc-motion "^2.6.2" rc-util "^5.24.4" +"@rc-component/tour@~1.10.0": + version "1.10.0" + resolved "https://registry.npmjs.org/@rc-component/tour/-/tour-1.10.0.tgz" + integrity sha512-voV0BKaTJbewB9LLgAHQ7tAGG7rgDkKQkZo82xw2gIk542hY+o7zwoqdN16oHhIKk7eG/xi+mdXrONT62Dt57A== + dependencies: + "@babel/runtime" "^7.18.0" + "@rc-component/portal" "^1.0.0-9" + "@rc-component/trigger" "^1.3.6" + classnames "^2.3.2" + rc-util "^5.24.4" + +"@rc-component/trigger@^1.0.4", "@rc-component/trigger@^1.15.6", "@rc-component/trigger@^1.3.6", "@rc-component/trigger@^1.5.0", "@rc-component/trigger@^1.6.2", "@rc-component/trigger@^1.7.0": + version "1.15.6" + resolved "https://registry.npmjs.org/@rc-component/trigger/-/trigger-1.15.6.tgz" + integrity sha512-Tl19KaGsShf4yzqxumsXVT4c7j0l20Dxe5hgP5S0HmxyhCg3oKen28ntGavRCIPW7cl7wgsGotntqcIokgDHzg== + dependencies: + "@babel/runtime" "^7.18.3" + "@rc-component/portal" "^1.1.0" + classnames "^2.3.2" + rc-align "^4.0.0" + rc-motion "^2.0.0" + rc-resize-observer "^1.3.1" + rc-util "^5.33.0" + +"@rgrove/parse-xml@^2.0.2": + version "2.0.4" + resolved "https://registry.npmjs.org/@rgrove/parse-xml/-/parse-xml-2.0.4.tgz" + integrity sha512-344bRXnUMu1tWqq1GJO2nCSqJRGTzcNLErcG2HZbVhUo90R5xQ6YdsCqtuT0KaFyN/mlxWqt2SdHSRNzwDvT5g== + "@sinonjs/commons@^1.7.0": version "1.8.5" - resolved "https://registry.npm.alibaba-inc.com/@sinonjs/commons/download/@sinonjs/commons-1.8.5.tgz#e280c94c95f206dcfd5aca00a43f2156b758c764" + resolved "https://registry.npm.alibaba-inc.com/@sinonjs/commons/download/@sinonjs/commons-1.8.5.tgz" integrity sha512-rTpCA0wG1wUxglBSFdMMY0oTrKYvgf4fNgv/sXbfCVAdf+FnPBdKJR/7XbpTCwbCrvCbdPYnlWaUUYz4V2fPDA== dependencies: type-detect "4.0.8" "@sinonjs/fake-timers@^6.0.1": version "6.0.1" - resolved "https://registry.npm.alibaba-inc.com/@sinonjs/fake-timers/download/@sinonjs/fake-timers-6.0.1.tgz#293674fccb3262ac782c7aadfdeca86b10c75c40" + resolved "https://registry.npm.alibaba-inc.com/@sinonjs/fake-timers/download/@sinonjs/fake-timers-6.0.1.tgz" integrity sha1-KTZ0/MsyYqx4LHqt/eyoaxDHXEA= dependencies: "@sinonjs/commons" "^1.7.0" "@stylelint/postcss-css-in-js@^0.37.2": version "0.37.3" - resolved "https://registry.npm.alibaba-inc.com/@stylelint/postcss-css-in-js/download/@stylelint/postcss-css-in-js-0.37.3.tgz#d149a385e07ae365b0107314c084cb6c11adbf49" + resolved "https://registry.npm.alibaba-inc.com/@stylelint/postcss-css-in-js/download/@stylelint/postcss-css-in-js-0.37.3.tgz" integrity sha512-scLk3cSH1H9KggSniseb2KNAU5D9FWc3H7BxCSAIdtU9OWIyw0zkEZ9qEKHryRM+SExYXRKNb7tOOVNAsQ3iwg== dependencies: "@babel/core" "^7.17.9" "@stylelint/postcss-markdown@^0.36.2": version "0.36.2" - resolved "https://registry.npm.alibaba-inc.com/@stylelint/postcss-markdown/download/@stylelint/postcss-markdown-0.36.2.tgz#0a540c4692f8dcdfc13c8e352c17e7bfee2bb391" + resolved "https://registry.npm.alibaba-inc.com/@stylelint/postcss-markdown/download/@stylelint/postcss-markdown-0.36.2.tgz" integrity sha1-ClQMRpL43N/BPI41LBfnv+4rs5E= dependencies: remark "^13.0.0" @@ -1858,12 +2604,12 @@ "@tootallnate/once@1": version "1.1.2" - resolved "https://registry.npm.alibaba-inc.com/@tootallnate/once/download/@tootallnate/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" + resolved "https://registry.npm.alibaba-inc.com/@tootallnate/once/download/@tootallnate/once-1.1.2.tgz" integrity sha1-zLkURTYBeaBOf+av94wA/8Hur4I= "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": version "7.1.20" - resolved "https://registry.npm.alibaba-inc.com/@types/babel__core/download/@types/babel__core-7.1.20.tgz#e168cdd612c92a2d335029ed62ac94c95b362359" + resolved "https://registry.npm.alibaba-inc.com/@types/babel__core/download/@types/babel__core-7.1.20.tgz" integrity sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ== dependencies: "@babel/parser" "^7.1.0" @@ -1874,14 +2620,14 @@ "@types/babel__generator@*": version "7.6.4" - resolved "https://registry.npm.alibaba-inc.com/@types/babel__generator/download/@types/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" + resolved "https://registry.npm.alibaba-inc.com/@types/babel__generator/download/@types/babel__generator-7.6.4.tgz" integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== dependencies: "@babel/types" "^7.0.0" "@types/babel__template@*": version "7.4.1" - resolved "https://registry.npm.alibaba-inc.com/@types/babel__template/download/@types/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" + resolved "https://registry.npm.alibaba-inc.com/@types/babel__template/download/@types/babel__template-7.4.1.tgz" integrity sha1-PRpI/Z1sDt/Vby/1eNrtSPNsiWk= dependencies: "@babel/parser" "^7.1.0" @@ -1889,14 +2635,19 @@ "@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6": version "7.18.2" - resolved "https://registry.npm.alibaba-inc.com/@types/babel__traverse/download/@types/babel__traverse-7.18.2.tgz#235bf339d17185bdec25e024ca19cce257cc7309" + resolved "https://registry.npm.alibaba-inc.com/@types/babel__traverse/download/@types/babel__traverse-7.18.2.tgz" integrity sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg== dependencies: "@babel/types" "^7.3.0" +"@types/d3-timer@^2.0.0": + version "2.0.1" + resolved "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-2.0.1.tgz" + integrity sha512-TF8aoF5cHcLO7W7403blM7L1T+6NF3XMyN3fxyUolq2uOcFeicG/khQg/dGxiCJWoAcmYulYN7LYSRKO54IXaA== + "@types/eslint@^7.2.13": version "7.29.0" - resolved "https://registry.npm.alibaba-inc.com/@types/eslint/download/@types/eslint-7.29.0.tgz#e56ddc8e542815272720bb0b4ccc2aff9c3e1c78" + resolved "https://registry.npm.alibaba-inc.com/@types/eslint/download/@types/eslint-7.29.0.tgz" integrity sha1-5W3cjlQoFScnILsLTMwq/5w+HHg= dependencies: "@types/estree" "*" @@ -1904,12 +2655,12 @@ "@types/estree@*": version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/@types/estree/download/@types/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + resolved "https://registry.npm.alibaba-inc.com/@types/estree/download/@types/estree-1.0.0.tgz" integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== "@types/glob@^7.1.1": version "7.2.0" - resolved "https://registry.npm.alibaba-inc.com/@types/glob/download/@types/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" + resolved "https://registry.npm.alibaba-inc.com/@types/glob/download/@types/glob-7.2.0.tgz" integrity sha1-vBtb86qS8lvV3TnzXFc2G9zlsus= dependencies: "@types/minimatch" "*" @@ -1917,26 +2668,26 @@ "@types/graceful-fs@^4.1.2": version "4.1.5" - resolved "https://registry.npm.alibaba-inc.com/@types/graceful-fs/download/@types/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" + resolved "https://registry.npm.alibaba-inc.com/@types/graceful-fs/download/@types/graceful-fs-4.1.5.tgz" integrity sha1-If+6DZjaQ1DbZIkfkqnl2zzbThU= dependencies: "@types/node" "*" "@types/history@*": version "5.0.0" - resolved "https://registry.npm.alibaba-inc.com/@types/history/download/@types/history-5.0.0.tgz#29f919f0c8e302763798118f45b19cab4a886f14" + resolved "https://registry.npm.alibaba-inc.com/@types/history/download/@types/history-5.0.0.tgz" integrity sha512-hy8b7Y1J8OGe6LbAjj3xniQrj3v6lsivCcrmf4TzSgPzLkhIeKgc5IZnT7ReIqmEuodjfO8EYAuoFvIrHi/+jQ== dependencies: history "*" "@types/history@^4.7.11": version "4.7.11" - resolved "https://registry.npm.alibaba-inc.com/@types/history/download/@types/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64" + resolved "https://registry.npm.alibaba-inc.com/@types/history/download/@types/history-4.7.11.tgz" integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA== "@types/hoist-non-react-statics@^3.3.0", "@types/hoist-non-react-statics@^3.3.1": version "3.3.1" - resolved "https://registry.npm.alibaba-inc.com/@types/hoist-non-react-statics/download/@types/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" + resolved "https://registry.npm.alibaba-inc.com/@types/hoist-non-react-statics/download/@types/hoist-non-react-statics-3.3.1.tgz" integrity sha1-ESSq/lEYy1kZd66xzqrtEHDrA58= dependencies: "@types/react" "*" @@ -1944,104 +2695,128 @@ "@types/invariant@^2.2.31": version "2.2.35" - resolved "https://registry.npm.alibaba-inc.com/@types/invariant/download/@types/invariant-2.2.35.tgz#cd3ebf581a6557452735688d8daba6cf0bd5a3be" + resolved "https://registry.npm.alibaba-inc.com/@types/invariant/download/@types/invariant-2.2.35.tgz" integrity sha1-zT6/WBplV0UnNWiNjaumzwvVo74= "@types/isomorphic-fetch@^0.0.35": version "0.0.35" - resolved "https://registry.npm.alibaba-inc.com/@types/isomorphic-fetch/download/@types/isomorphic-fetch-0.0.35.tgz#c1c0d402daac324582b6186b91f8905340ea3361" + resolved "https://registry.npm.alibaba-inc.com/@types/isomorphic-fetch/download/@types/isomorphic-fetch-0.0.35.tgz" integrity sha1-wcDUAtqsMkWCthhrkfiQU0DqM2E= "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.4" - resolved "https://registry.npm.alibaba-inc.com/@types/istanbul-lib-coverage/download/@types/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + resolved "https://registry.npm.alibaba-inc.com/@types/istanbul-lib-coverage/download/@types/istanbul-lib-coverage-2.0.4.tgz" integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== "@types/istanbul-lib-report@*": version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/@types/istanbul-lib-report/download/@types/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + resolved "https://registry.npm.alibaba-inc.com/@types/istanbul-lib-report/download/@types/istanbul-lib-report-3.0.0.tgz" integrity sha1-wUwk8Y6oGQwRjudWK3/5mjZVJoY= dependencies: "@types/istanbul-lib-coverage" "*" "@types/istanbul-reports@^3.0.0": version "3.0.1" - resolved "https://registry.npm.alibaba-inc.com/@types/istanbul-reports/download/@types/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + resolved "https://registry.npm.alibaba-inc.com/@types/istanbul-reports/download/@types/istanbul-reports-3.0.1.tgz" integrity sha1-kVP+mLuivVZaY63ZQ21vDX+EaP8= dependencies: "@types/istanbul-lib-report" "*" +"@types/js-cookie@^2.2.6": + version "2.2.7" + resolved "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz" + integrity sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA== + +"@types/jsdom@^21.1.2": + version "21.1.2" + resolved "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.2.tgz" + integrity sha512-bGj+7TaCkOwkJfx7HtS9p22Ij0A2aKMuz8a1+owpkxa1wU/HUBy/WAXhdv90uDdVI9rSjGvUrXmLSeA9VP3JeA== + dependencies: + "@types/node" "*" + "@types/tough-cookie" "*" + parse5 "^7.0.0" + "@types/json-schema@*", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.11" - resolved "https://registry.npm.alibaba-inc.com/@types/json-schema/download/@types/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + resolved "https://registry.npm.alibaba-inc.com/@types/json-schema/download/@types/json-schema-7.0.11.tgz" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== +"@types/lodash@^4.14.198": + version "4.14.198" + resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.198.tgz" + integrity sha512-trNJ/vtMZYMLhfN45uLq4ShQSw0/S7xCTLLVM+WM1rmFpba/VS42jVUgaO3w/NOLiWR/09lnYk0yMaA/atdIsg== + "@types/mdast@^3.0.0": version "3.0.10" - resolved "https://registry.npm.alibaba-inc.com/@types/mdast/download/@types/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" + resolved "https://registry.npm.alibaba-inc.com/@types/mdast/download/@types/mdast-3.0.10.tgz" integrity sha1-RyQkSoKkWYiEy76bz9c9/5J+6K8= dependencies: "@types/unist" "*" "@types/minimatch@*": version "5.1.2" - resolved "https://registry.npm.alibaba-inc.com/@types/minimatch/download/@types/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" + resolved "https://registry.npm.alibaba-inc.com/@types/minimatch/download/@types/minimatch-5.1.2.tgz" integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== "@types/minimist@^1.2.0": version "1.2.2" - resolved "https://registry.npm.alibaba-inc.com/@types/minimist/download/@types/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" + resolved "https://registry.npm.alibaba-inc.com/@types/minimist/download/@types/minimist-1.2.2.tgz" integrity sha1-7nceK6Sz3Fs3KTXVSf2WF780W4w= "@types/node@*": version "18.11.9" - resolved "https://registry.npm.alibaba-inc.com/@types/node/download/@types/node-18.11.9.tgz#02d013de7058cea16d36168ef2fc653464cfbad4" + resolved "https://registry.npm.alibaba-inc.com/@types/node/download/@types/node-18.11.9.tgz" integrity sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg== "@types/normalize-package-data@^2.4.0": version "2.4.1" - resolved "https://registry.npm.alibaba-inc.com/@types/normalize-package-data/download/@types/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" + resolved "https://registry.npm.alibaba-inc.com/@types/normalize-package-data/download/@types/normalize-package-data-2.4.1.tgz" integrity sha1-0zV0eaD9/dWQf+Z+F+CoXJBuEwE= "@types/parse-json@^4.0.0": version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/@types/parse-json/download/@types/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" + resolved "https://registry.npm.alibaba-inc.com/@types/parse-json/download/@types/parse-json-4.0.0.tgz" integrity sha1-L4u0QUNNFjs1+4/9zNcTiSf/uMA= "@types/prettier@^2.0.0": version "2.7.1" - resolved "https://registry.npm.alibaba-inc.com/@types/prettier/download/@types/prettier-2.7.1.tgz#dfd20e2dc35f027cdd6c1908e80a5ddc7499670e" + resolved "https://registry.npm.alibaba-inc.com/@types/prettier/download/@types/prettier-2.7.1.tgz" integrity sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow== "@types/prop-types@*": version "15.7.5" - resolved "https://registry.npm.alibaba-inc.com/@types/prop-types/download/@types/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" + resolved "https://registry.npm.alibaba-inc.com/@types/prop-types/download/@types/prop-types-15.7.5.tgz" integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== +"@types/q@^1.5.1": + version "1.5.6" + resolved "https://registry.npmjs.org/@types/q/-/q-1.5.6.tgz" + integrity sha512-IKjZ8RjTSwD4/YG+2gtj7BPFRB/lNbWKTiSj3M7U/TD2B7HfYCxvp2Zz6xA2WIY7pAuL1QOUPw8gQRbUrrq4fQ== + "@types/react-dom@17.0.2": version "17.0.2" - resolved "https://registry.npm.alibaba-inc.com/@types/react-dom/download/@types/react-dom-17.0.2.tgz#35654cf6c49ae162d5bc90843d5437dc38008d43" + resolved "https://registry.npm.alibaba-inc.com/@types/react-dom/download/@types/react-dom-17.0.2.tgz" integrity sha1-NWVM9sSa4WLVvJCEPVQ33DgAjUM= dependencies: "@types/react" "*" "@types/react-dom@^16.9.8": version "16.9.17" - resolved "https://registry.npm.alibaba-inc.com/@types/react-dom/download/@types/react-dom-16.9.17.tgz#29100cbcc422d7b7dba7de24bb906de56680dd34" + resolved "https://registry.npm.alibaba-inc.com/@types/react-dom/download/@types/react-dom-16.9.17.tgz" integrity sha512-qSRyxEsrm5btPXnowDOs5jSkgT8ldAA0j6Qp+otHUh+xHzy3sXmgNfyhucZjAjkgpdAUw9rJe0QRtX/l+yaS4g== dependencies: "@types/react" "^16" "@types/react-helmet@^6.1.0": version "6.1.5" - resolved "https://registry.npm.alibaba-inc.com/@types/react-helmet/download/@types/react-helmet-6.1.5.tgz#35f89a6b1646ee2bc342a33a9a6c8777933f9083" + resolved "https://registry.npm.alibaba-inc.com/@types/react-helmet/download/@types/react-helmet-6.1.5.tgz" integrity sha512-/ICuy7OHZxR0YCAZLNg9r7I9aijWUWvxaPR6uTuyxe8tAj5RL4Sw1+R6NhXUtOsarkGYPmaHdBDvuXh2DIN/uA== dependencies: "@types/react" "*" "@types/react-redux@^7.1.0", "@types/react-redux@^7.1.20": version "7.1.24" - resolved "https://registry.npm.alibaba-inc.com/@types/react-redux/download/@types/react-redux-7.1.24.tgz#6caaff1603aba17b27d20f8ad073e4c077e975c0" + resolved "https://registry.npm.alibaba-inc.com/@types/react-redux/download/@types/react-redux-7.1.24.tgz" integrity sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ== dependencies: "@types/hoist-non-react-statics" "^3.3.0" @@ -2051,7 +2826,7 @@ "@types/react-router-config@5.0.2": version "5.0.2" - resolved "https://registry.npm.alibaba-inc.com/@types/react-router-config/download/@types/react-router-config-5.0.2.tgz#4d3b52e71ed363a1976a12321e67b09a99ad6d10" + resolved "https://registry.npm.alibaba-inc.com/@types/react-router-config/download/@types/react-router-config-5.0.2.tgz" integrity sha1-TTtS5x7TY6GXahIyHmewmpmtbRA= dependencies: "@types/history" "*" @@ -2060,7 +2835,7 @@ "@types/react-router-config@^5.0.2": version "5.0.6" - resolved "https://registry.npm.alibaba-inc.com/@types/react-router-config/download/@types/react-router-config-5.0.6.tgz#87c5c57e72d241db900d9734512c50ccec062451" + resolved "https://registry.npm.alibaba-inc.com/@types/react-router-config/download/@types/react-router-config-5.0.6.tgz" integrity sha512-db1mx37a1EJDf1XeX8jJN7R3PZABmJQXR8r28yUjVMFSjkmnQo6X6pOEEmNl+Tp2gYQOGPdYbFIipBtdElZ3Yg== dependencies: "@types/history" "^4.7.11" @@ -2069,7 +2844,7 @@ "@types/react-router-dom@5.1.7": version "5.1.7" - resolved "https://registry.npm.alibaba-inc.com/@types/react-router-dom/download/@types/react-router-dom-5.1.7.tgz#a126d9ea76079ffbbdb0d9225073eb5797ab7271" + resolved "https://registry.npm.alibaba-inc.com/@types/react-router-dom/download/@types/react-router-dom-5.1.7.tgz" integrity sha1-oSbZ6nYHn/u9sNkiUHPrV5ercnE= dependencies: "@types/history" "*" @@ -2078,7 +2853,7 @@ "@types/react-router-dom@^5.1.2": version "5.3.3" - resolved "https://registry.npm.alibaba-inc.com/@types/react-router-dom/download/@types/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83" + resolved "https://registry.npm.alibaba-inc.com/@types/react-router-dom/download/@types/react-router-dom-5.3.3.tgz" integrity sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw== dependencies: "@types/history" "^4.7.11" @@ -2087,7 +2862,7 @@ "@types/react-router@*": version "5.1.19" - resolved "https://registry.npm.alibaba-inc.com/@types/react-router/download/@types/react-router-5.1.19.tgz#9b404246fba7f91474d7008a3d48c17b6e075ad6" + resolved "https://registry.npm.alibaba-inc.com/@types/react-router/download/@types/react-router-5.1.19.tgz" integrity sha512-Fv/5kb2STAEMT3wHzdKQK2z8xKq38EDIGVrutYLmQVVLe+4orDFquU52hQrULnEHinMKv9FSA6lf9+uNT1ITtA== dependencies: "@types/history" "^4.7.11" @@ -2095,7 +2870,7 @@ "@types/react-router@5.1.12": version "5.1.12" - resolved "https://registry.npm.alibaba-inc.com/@types/react-router/download/@types/react-router-5.1.12.tgz#0f300e09468e7aed86e18241c90238c18c377e51" + resolved "https://registry.npm.alibaba-inc.com/@types/react-router/download/@types/react-router-5.1.12.tgz" integrity sha1-DzAOCUaOeu2G4YJByQI4wYw3flE= dependencies: "@types/history" "*" @@ -2103,7 +2878,7 @@ "@types/react@*": version "18.0.25" - resolved "https://registry.npm.alibaba-inc.com/@types/react/download/@types/react-18.0.25.tgz#8b1dcd7e56fe7315535a4af25435e0bb55c8ae44" + resolved "https://registry.npm.alibaba-inc.com/@types/react/download/@types/react-18.0.25.tgz" integrity sha512-xD6c0KDT4m7n9uD4ZHi02lzskaiqcBxf4zi+tXZY98a04wvc0hi/TcCPC2FOESZi51Nd7tlUeOJY8RofL799/g== dependencies: "@types/prop-types" "*" @@ -2112,7 +2887,7 @@ "@types/react@16 || 17 || 18": version "18.2.0" - resolved "https://registry.npm.alibaba-inc.com/@types/react/download/@types/react-18.2.0.tgz#15cda145354accfc09a18d2f2305f9fc099ada21" + resolved "https://registry.npm.alibaba-inc.com/@types/react/download/@types/react-18.2.0.tgz" integrity sha512-0FLj93y5USLHdnhIhABk83rm8XEGA7kH3cr+YUlvxoUGp1xNt/DINUMvqPxLyOQMzLmZe8i4RTHbvb8MC7NmrA== dependencies: "@types/prop-types" "*" @@ -2121,7 +2896,7 @@ "@types/react@17.0.52": version "17.0.52" - resolved "https://registry.npm.alibaba-inc.com/@types/react/download/@types/react-17.0.52.tgz#10d8b907b5c563ac014a541f289ae8eaa9bf2e9b" + resolved "https://registry.npm.alibaba-inc.com/@types/react/download/@types/react-17.0.52.tgz" integrity sha512-vwk8QqVODi0VaZZpDXQCmEmiOuyjEFPY7Ttaw5vjM112LOq37yz1CDJGrRJwA1fYEq4Iitd5rnjd1yWAc/bT+A== dependencies: "@types/prop-types" "*" @@ -2130,7 +2905,7 @@ "@types/react@^16", "@types/react@^16.9.43": version "16.14.34" - resolved "https://registry.npm.alibaba-inc.com/@types/react/download/@types/react-16.14.34.tgz#d129324ffda312044e1c47aab18696e4ed493282" + resolved "https://registry.npm.alibaba-inc.com/@types/react/download/@types/react-16.14.34.tgz" integrity sha512-b99nWeGGReLh6aKBppghVqp93dFJtgtDOzc8NXM6hewD8PQ2zZG5kBLgbx+VJr7Q7WBMjHxaIl3dwpwwPIUgyA== dependencies: "@types/prop-types" "*" @@ -2139,44 +2914,54 @@ "@types/scheduler@*": version "0.16.2" - resolved "https://registry.npm.alibaba-inc.com/@types/scheduler/download/@types/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" + resolved "https://registry.npm.alibaba-inc.com/@types/scheduler/download/@types/scheduler-0.16.2.tgz" integrity sha1-GmL4lSVyPd4kuhsBsJK/XfitTTk= "@types/semver@^7.3.12": version "7.3.13" - resolved "https://registry.npm.alibaba-inc.com/@types/semver/download/@types/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" + resolved "https://registry.npm.alibaba-inc.com/@types/semver/download/@types/semver-7.3.13.tgz" integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== "@types/stack-utils@^2.0.0": version "2.0.1" - resolved "https://registry.npm.alibaba-inc.com/@types/stack-utils/download/@types/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" + resolved "https://registry.npm.alibaba-inc.com/@types/stack-utils/download/@types/stack-utils-2.0.1.tgz" integrity sha1-IPGClPeX8iCbX2XI47XI6CYdEnw= +"@types/tough-cookie@*": + version "4.0.3" + resolved "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.3.tgz" + integrity sha512-THo502dA5PzG/sfQH+42Lw3fvmYkceefOspdCwpHRul8ik2Jv1K8I5OZz1AT3/rs46kwgMCe9bSBmDLYkkOMGg== + "@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2": version "2.0.6" - resolved "https://registry.npm.alibaba-inc.com/@types/unist/download/@types/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" + resolved "https://registry.npm.alibaba-inc.com/@types/unist/download/@types/unist-2.0.6.tgz" integrity sha1-JQp7FsO5H2cqJFUuxkZ47rHToI0= +"@types/validator@^12.0.1": + version "12.0.1" + resolved "https://registry.yarnpkg.com/@types/validator/-/validator-12.0.1.tgz#73dbc7f5f730ff7131754bca682824eb3c260b79" + integrity sha512-l57fIANZLMe8DArz+SDb+7ATXnDm15P7u2wHBw5mb0aSMd+UuvmvhouBF2hdLgQPDMJ39sh9g2MJO4GkZ0VAdQ== + "@types/video.js@7.3.50": version "7.3.50" - resolved "https://registry.npm.alibaba-inc.com/@types/video.js/download/@types/video.js-7.3.50.tgz#5354323fcf0ab99352d79ddce75843faa82297e0" + resolved "https://registry.npm.alibaba-inc.com/@types/video.js/download/@types/video.js-7.3.50.tgz" integrity sha512-xG0xoeyLGuWhtWMBBLRVhTEOfT2n6AjhNoWhFWVbpa6A8hSMi4eNvttuHYXsn6NslITu7IUdKPDRQ2bAWgXKDA== "@types/yargs-parser@*": version "21.0.0" - resolved "https://registry.npm.alibaba-inc.com/@types/yargs-parser/download/@types/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + resolved "https://registry.npm.alibaba-inc.com/@types/yargs-parser/download/@types/yargs-parser-21.0.0.tgz" integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== "@types/yargs@^15.0.0": version "15.0.14" - resolved "https://registry.npm.alibaba-inc.com/@types/yargs/download/@types/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06" + resolved "https://registry.npm.alibaba-inc.com/@types/yargs/download/@types/yargs-15.0.14.tgz" integrity sha1-Jtgh3biecEkhYLZtEKDrbfj2+wY= dependencies: "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^5.8.1": version "5.44.0" - resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/eslint-plugin/download/@typescript-eslint/eslint-plugin-5.44.0.tgz#105788f299050c917eb85c4d9fd04b089e3740de" + resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/eslint-plugin/download/@typescript-eslint/eslint-plugin-5.44.0.tgz" integrity sha512-j5ULd7FmmekcyWeArx+i8x7sdRHzAtXTkmDPthE4amxZOWKFK7bomoJ4r7PJ8K7PoMzD16U8MmuZFAonr1ERvw== dependencies: "@typescript-eslint/scope-manager" "5.44.0" @@ -2191,7 +2976,7 @@ "@typescript-eslint/experimental-utils@^4.0.1": version "4.33.0" - resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/experimental-utils/download/@typescript-eslint/experimental-utils-4.33.0.tgz#6f2a786a4209fa2222989e9380b5331b2810f7fd" + resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/experimental-utils/download/@typescript-eslint/experimental-utils-4.33.0.tgz" integrity sha1-byp4akIJ+iIimJ6TgLUzGygQ9/0= dependencies: "@types/json-schema" "^7.0.7" @@ -2203,7 +2988,7 @@ "@typescript-eslint/parser@^5.9.0": version "5.44.0" - resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/parser/download/@typescript-eslint/parser-5.44.0.tgz#99e2c710a2252191e7a79113264f438338b846ad" + resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/parser/download/@typescript-eslint/parser-5.44.0.tgz" integrity sha512-H7LCqbZnKqkkgQHaKLGC6KUjt3pjJDx8ETDqmwncyb6PuoigYajyAwBGz08VU/l86dZWZgI4zm5k2VaKqayYyA== dependencies: "@typescript-eslint/scope-manager" "5.44.0" @@ -2213,7 +2998,7 @@ "@typescript-eslint/scope-manager@4.33.0": version "4.33.0" - resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/scope-manager/download/@typescript-eslint/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3" + resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/scope-manager/download/@typescript-eslint/scope-manager-4.33.0.tgz" integrity sha1-045JKA2YPody4pEhz4xukiHygKM= dependencies: "@typescript-eslint/types" "4.33.0" @@ -2221,7 +3006,7 @@ "@typescript-eslint/scope-manager@5.44.0": version "5.44.0" - resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/scope-manager/download/@typescript-eslint/scope-manager-5.44.0.tgz#988c3f34b45b3474eb9ff0674c18309dedfc3e04" + resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/scope-manager/download/@typescript-eslint/scope-manager-5.44.0.tgz" integrity sha512-2pKml57KusI0LAhgLKae9kwWeITZ7IsZs77YxyNyIVOwQ1kToyXRaJLl+uDEXzMN5hnobKUOo2gKntK9H1YL8g== dependencies: "@typescript-eslint/types" "5.44.0" @@ -2229,7 +3014,7 @@ "@typescript-eslint/type-utils@5.44.0": version "5.44.0" - resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/type-utils/download/@typescript-eslint/type-utils-5.44.0.tgz#bc5a6e8a0269850714a870c9268c038150dfb3c7" + resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/type-utils/download/@typescript-eslint/type-utils-5.44.0.tgz" integrity sha512-A1u0Yo5wZxkXPQ7/noGkRhV4J9opcymcr31XQtOzcc5nO/IHN2E2TPMECKWYpM3e6olWEM63fq/BaL1wEYnt/w== dependencies: "@typescript-eslint/typescript-estree" "5.44.0" @@ -2239,17 +3024,17 @@ "@typescript-eslint/types@4.33.0": version "4.33.0" - resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/types/download/@typescript-eslint/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" + resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/types/download/@typescript-eslint/types-4.33.0.tgz" integrity sha1-oeWQNqO1OuhDDO6/KpGdx/mvbXI= "@typescript-eslint/types@5.44.0": version "5.44.0" - resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/types/download/@typescript-eslint/types-5.44.0.tgz#f3f0b89aaff78f097a2927fe5688c07e786a0241" + resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/types/download/@typescript-eslint/types-5.44.0.tgz" integrity sha512-Tp+zDnHmGk4qKR1l+Y1rBvpjpm5tGXX339eAlRBDg+kgZkz9Bw+pqi4dyseOZMsGuSH69fYfPJCBKBrbPCxYFQ== "@typescript-eslint/typescript-estree@4.33.0": version "4.33.0" - resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/typescript-estree/download/@typescript-eslint/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609" + resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/typescript-estree/download/@typescript-eslint/typescript-estree-4.33.0.tgz" integrity sha1-DftRwpCPaMXAjYKu/q8WahfCRgk= dependencies: "@typescript-eslint/types" "4.33.0" @@ -2262,7 +3047,7 @@ "@typescript-eslint/typescript-estree@5.44.0": version "5.44.0" - resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/typescript-estree/download/@typescript-eslint/typescript-estree-5.44.0.tgz#0461b386203e8d383bb1268b1ed1da9bc905b045" + resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/typescript-estree/download/@typescript-eslint/typescript-estree-5.44.0.tgz" integrity sha512-M6Jr+RM7M5zeRj2maSfsZK2660HKAJawv4Ud0xT+yauyvgrsHu276VtXlKDFnEmhG+nVEd0fYZNXGoAgxwDWJw== dependencies: "@typescript-eslint/types" "5.44.0" @@ -2275,7 +3060,7 @@ "@typescript-eslint/utils@5.44.0": version "5.44.0" - resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/utils/download/@typescript-eslint/utils-5.44.0.tgz#d733da4d79d6c30f1a68b531cdda1e0c1f00d52d" + resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/utils/download/@typescript-eslint/utils-5.44.0.tgz" integrity sha512-fMzA8LLQ189gaBjS0MZszw5HBdZgVwxVFShCO3QN+ws3GlPkcy9YuS3U4wkT6su0w+Byjq3mS3uamy9HE4Yfjw== dependencies: "@types/json-schema" "^7.0.9" @@ -2289,7 +3074,7 @@ "@typescript-eslint/visitor-keys@4.33.0": version "4.33.0" - resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/visitor-keys/download/@typescript-eslint/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd" + resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/visitor-keys/download/@typescript-eslint/visitor-keys-4.33.0.tgz" integrity sha1-KiL3ekFgQom3oYZYbp7EjKku8d0= dependencies: "@typescript-eslint/types" "4.33.0" @@ -2297,7 +3082,7 @@ "@typescript-eslint/visitor-keys@5.44.0": version "5.44.0" - resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/visitor-keys/download/@typescript-eslint/visitor-keys-5.44.0.tgz#10740dc28902bb903d12ee3a005cc3a70207d433" + resolved "https://registry.npm.alibaba-inc.com/@typescript-eslint/visitor-keys/download/@typescript-eslint/visitor-keys-5.44.0.tgz" integrity sha512-a48tLG8/4m62gPFbJ27FxwCOqPKxsb8KC3HkmYoq2As/4YyjQl1jDbRr1s63+g4FS/iIehjmN3L5UjmKva1HzQ== dependencies: "@typescript-eslint/types" "5.44.0" @@ -2305,28 +3090,28 @@ "@umijs/ast@3.5.35": version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/@umijs/ast/download/@umijs/ast-3.5.35.tgz#621b3504bce7d47f3e9d0a4311edd5c1e58eda02" + resolved "https://registry.npm.alibaba-inc.com/@umijs/ast/download/@umijs/ast-3.5.35.tgz" integrity sha512-klxzB/eu7rXN8FU5fi33EeQwkZ0oAwJkPGOQpuLODOiat1di8FvYl5iW9xdVCfC1iS3IIW4ajorYdYz+OlYsqg== dependencies: "@umijs/utils" "3.5.35" "@umijs/babel-plugin-auto-css-modules@3.5.35": version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/@umijs/babel-plugin-auto-css-modules/download/@umijs/babel-plugin-auto-css-modules-3.5.35.tgz#bf812370696d378f46006c90fd36011830f1516e" + resolved "https://registry.npm.alibaba-inc.com/@umijs/babel-plugin-auto-css-modules/download/@umijs/babel-plugin-auto-css-modules-3.5.35.tgz" integrity sha512-Ycj1zo3KA8JJXN7LNwH1Sfk0xHWo9tgtU0J8CvpD7PEm8ub7tMx3hXA+0zp21vdwkwwnvrzlSZtBlo9NbXqCkA== dependencies: "@umijs/utils" "3.5.35" "@umijs/babel-plugin-import-to-await-require@3.5.35": version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/@umijs/babel-plugin-import-to-await-require/download/@umijs/babel-plugin-import-to-await-require-3.5.35.tgz#efc9978d79160f90d5f6a4e26b0130d9da01b7e4" + resolved "https://registry.npm.alibaba-inc.com/@umijs/babel-plugin-import-to-await-require/download/@umijs/babel-plugin-import-to-await-require-3.5.35.tgz" integrity sha512-sZsvpk3I8ptvtHoVYtUdQZT5nYcTvmwPj+gSCjPxxgBBxAdGywheda0RXK8/iP+vbLinK08H3d0rpa/91XzHyA== dependencies: "@umijs/utils" "3.5.35" "@umijs/babel-plugin-lock-core-js-3@3.5.35": version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/@umijs/babel-plugin-lock-core-js-3/download/@umijs/babel-plugin-lock-core-js-3-3.5.35.tgz#1c4a351e20753fdadac0dd1beb0ad64c4fc46bbf" + resolved "https://registry.npm.alibaba-inc.com/@umijs/babel-plugin-lock-core-js-3/download/@umijs/babel-plugin-lock-core-js-3-3.5.35.tgz" integrity sha512-g/vJHvHknF2/B0XLl44rP63eBqdBIPrXAgCv9/0jSxEhzTzcimXaXmRkmq2PL4TgNe5S7LS6O9BtWvtMiOrfNA== dependencies: "@umijs/utils" "3.5.35" @@ -2334,14 +3119,14 @@ "@umijs/babel-plugin-no-anonymous-default-export@3.5.35": version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/@umijs/babel-plugin-no-anonymous-default-export/download/@umijs/babel-plugin-no-anonymous-default-export-3.5.35.tgz#0803a345634d9c7edebff5ce61e8814cc28f6b02" + resolved "https://registry.npm.alibaba-inc.com/@umijs/babel-plugin-no-anonymous-default-export/download/@umijs/babel-plugin-no-anonymous-default-export-3.5.35.tgz" integrity sha512-znaPMLP5lOGxXI+e9Ai8yWZvLzToVlH6hCz8j3GjKYWQElga4NJYzUqBP89l5RuP+nTJGmnG4HqgvWkLjvFUqw== dependencies: "@umijs/utils" "3.5.35" "@umijs/babel-preset-umi@3.5.35": version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/@umijs/babel-preset-umi/download/@umijs/babel-preset-umi-3.5.35.tgz#1e0f9600a081738a27631cd9729f076d64ea03e0" + resolved "https://registry.npm.alibaba-inc.com/@umijs/babel-preset-umi/download/@umijs/babel-preset-umi-3.5.35.tgz" integrity sha512-gWpREqwGtCT6FQpHHl0dC8WW0Q84YXt8UboTxYVuYLDccFas++EikOtORN3wr6Omelt9EqEfczSLD2YPoukORg== dependencies: "@babel/runtime" "7.18.6" @@ -2354,7 +3139,7 @@ "@umijs/bundler-utils@3.5.35": version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/@umijs/bundler-utils/download/@umijs/bundler-utils-3.5.35.tgz#c97426748011c25c568585d7d6da0c7dee4234a2" + resolved "https://registry.npm.alibaba-inc.com/@umijs/bundler-utils/download/@umijs/bundler-utils-3.5.35.tgz" integrity sha512-qPA+aUbM2g1r2kHSK37V2JHzttew4QHiAASCO706+YmPfaWURE+0s8GNayUDvt3GOpHYJ9mrLX9etr4A1xJYNQ== dependencies: "@umijs/babel-preset-umi" "3.5.35" @@ -2363,7 +3148,7 @@ "@umijs/bundler-webpack@3.5.35": version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/@umijs/bundler-webpack/download/@umijs/bundler-webpack-3.5.35.tgz#dcdcda6f92ba527a619dbae20ad5d5dd85c4ea41" + resolved "https://registry.npm.alibaba-inc.com/@umijs/bundler-webpack/download/@umijs/bundler-webpack-3.5.35.tgz" integrity sha512-h8yZcTqB1BkOLwiMVLwgYIjmL1SKet1B0cq4BGSVY4GcAW3nAwqjfQ+K02pZd2MxFbxGDqJsmuul8fQqH0MR6A== dependencies: "@umijs/bundler-utils" "3.5.35" @@ -2384,12 +3169,12 @@ "@umijs/case-sensitive-paths-webpack-plugin@^1.0.1": version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/@umijs/case-sensitive-paths-webpack-plugin/download/@umijs/case-sensitive-paths-webpack-plugin-1.0.1.tgz#02655299f52912289f2df28fbeaea636e748c1df" + resolved "https://registry.npm.alibaba-inc.com/@umijs/case-sensitive-paths-webpack-plugin/download/@umijs/case-sensitive-paths-webpack-plugin-1.0.1.tgz" integrity sha512-kDKJ8yTarxwxGJDInG33hOpaQRZ//XpNuuznQ/1Mscypw6kappzFmrBr2dOYave++K7JHouoANF354UpbEQw0Q== "@umijs/core@3.5.35": version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/@umijs/core/download/@umijs/core-3.5.35.tgz#f436d600ad68761d1db07c5731059906c1567593" + resolved "https://registry.npm.alibaba-inc.com/@umijs/core/download/@umijs/core-3.5.35.tgz" integrity sha512-Weyhz/fFLh8jX8/iS0mK4awbG+OEjrS2DzEPt7eJgooDhadOnEXznz9lY87LXPfZfI2sL0/5b3kuHjaOsHDGwg== dependencies: "@umijs/ast" "3.5.35" @@ -2399,7 +3184,7 @@ "@umijs/deps@3.5.35": version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/@umijs/deps/download/@umijs/deps-3.5.35.tgz#f3dfcad6d651b376704ccad99035c95ecffb7451" + resolved "https://registry.npm.alibaba-inc.com/@umijs/deps/download/@umijs/deps-3.5.35.tgz" integrity sha512-iDNMcmo8+hqe4SyZl+mr/xMYgxkYFg9HYb6QAvCt4p44Az3iD05D/jfXu+zSwxOsZ6S0LwZ5SYary6S32tp2LQ== dependencies: "@bloomberg/record-tuple-polyfill" "0.0.3" @@ -2412,7 +3197,7 @@ "@umijs/fabric@^2.5.6": version "2.14.0" - resolved "https://registry.npm.alibaba-inc.com/@umijs/fabric/download/@umijs/fabric-2.14.0.tgz#dd3b3188ae7cb6ffc52e1aaf3e33ba5b350177de" + resolved "https://registry.npm.alibaba-inc.com/@umijs/fabric/download/@umijs/fabric-2.14.0.tgz" integrity sha512-tiqKWYFwK9dgrdC8U1IjdIqeIv6W3NhROJHb07u1D72KWpGoN2U7/gVRtyMq7psBSK4EwHyXL6sFtIGUibs2ng== dependencies: "@babel/core" "^7.12.10" @@ -2448,7 +3233,7 @@ "@umijs/openapi@^1.2.0": version "1.8.0" - resolved "https://registry.npm.alibaba-inc.com/@umijs/openapi/download/@umijs/openapi-1.8.0.tgz#6fd71e18aa4fc94ffb516ed891833f00edf8c7c8" + resolved "https://registry.npm.alibaba-inc.com/@umijs/openapi/download/@umijs/openapi-1.8.0.tgz" integrity sha512-okVmh9kIBrct4y1LOlzbY4ZnqHJIKXVdbSW6TWLM+da5JVMDgkFr4LBuuw4ESLaYc65yAgpXc7YX9OsuFkTTdg== dependencies: "@umijs/fabric" "^2.5.6" @@ -2469,17 +3254,17 @@ "@umijs/plugin-access@2.4.3": version "2.4.3" - resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-access/download/@umijs/plugin-access-2.4.3.tgz#6bccbfe4969f43e58bc552a5ffbe247a2c33779a" + resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-access/download/@umijs/plugin-access-2.4.3.tgz" integrity sha512-6FON4aHzVFs/vtFK5Sdnw+FBolfoYi8wV8V9Q8x2T19NwjZtjXSPjt0gtrG4jdx4LRsSV2DKLaMGoJYbNr94aA== "@umijs/plugin-analytics@0.2.2": version "0.2.2" - resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-analytics/download/@umijs/plugin-analytics-0.2.2.tgz#575fd231d4327ea13413217aa1b5fc6bdd89465e" + resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-analytics/download/@umijs/plugin-analytics-0.2.2.tgz" integrity sha1-V1/SMdQyfqE0EyF6obX8a92JRl4= "@umijs/plugin-antd@0.13.0": version "0.13.0" - resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-antd/download/@umijs/plugin-antd-0.13.0.tgz#9a7e2f21d37fa4200f25024047035b420557693a" + resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-antd/download/@umijs/plugin-antd-0.13.0.tgz" integrity sha512-7tooYtOylVatrzMWCJtk8JFQL90i94OD0FgZYpKBbM7keThH8prYkSkDJFIDkuGfZ6pl6BJT8ESnYLxf2OiQUw== dependencies: antd "^4.1.3" @@ -2488,12 +3273,12 @@ "@umijs/plugin-crossorigin@1.2.1": version "1.2.1" - resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-crossorigin/download/@umijs/plugin-crossorigin-1.2.1.tgz#c210375392dc020ad201b9b0ab5a49234e24e6d3" + resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-crossorigin/download/@umijs/plugin-crossorigin-1.2.1.tgz" integrity sha1-whA3U5LcAgrSAbmwq1pJI04k5tM= "@umijs/plugin-dva@0.13.0": version "0.13.0" - resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-dva/download/@umijs/plugin-dva-0.13.0.tgz#aa8cf9982cfb5b8d5fcb59c3915cca866dc37dab" + resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-dva/download/@umijs/plugin-dva-0.13.0.tgz" integrity sha1-qoz5mCz7W41fy1nDkVzKhm3Dfas= dependencies: babel-plugin-dva-hmr "^0.4.2" @@ -2503,7 +3288,7 @@ "@umijs/plugin-helmet@1.1.3": version "1.1.3" - resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-helmet/download/@umijs/plugin-helmet-1.1.3.tgz#d66e257fa90d6c20f56b6d744a746d3f3e40a880" + resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-helmet/download/@umijs/plugin-helmet-1.1.3.tgz" integrity sha1-1m4lf6kNbCD1a210SnRtPz5AqIA= dependencies: "@types/react-helmet" "^6.1.0" @@ -2511,12 +3296,12 @@ "@umijs/plugin-initial-state@2.4.0": version "2.4.0" - resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-initial-state/download/@umijs/plugin-initial-state-2.4.0.tgz#a6759082f2bdd0aeb278ae95b2e4b562a061aed6" + resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-initial-state/download/@umijs/plugin-initial-state-2.4.0.tgz" integrity sha1-pnWQgvK90K6yeK6VsuS1YqBhrtY= "@umijs/plugin-layout@0.18.1": version "0.18.1" - resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-layout/download/@umijs/plugin-layout-0.18.1.tgz#8490fb525a6225fbf3081b9c32d145def42da88c" + resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-layout/download/@umijs/plugin-layout-0.18.1.tgz" integrity sha1-hJD7UlpiJfvzCBucMtFF3vQtqIw= dependencies: "@umijs/route-utils" "^2.0.0" @@ -2526,7 +3311,7 @@ "@umijs/plugin-locale@0.15.1": version "0.15.1" - resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-locale/download/@umijs/plugin-locale-0.15.1.tgz#2b2c7f419d40d2a44a6b3041b7ad7d40abff69cf" + resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-locale/download/@umijs/plugin-locale-0.15.1.tgz" integrity sha1-Kyx/QZ1A0qRKazBBt619QKv/ac8= dependencies: "@ant-design/icons" "^4.1.0" @@ -2539,14 +3324,14 @@ "@umijs/plugin-model@2.6.2": version "2.6.2" - resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-model/download/@umijs/plugin-model-2.6.2.tgz#779a726ae0b0746723df166a28e17f026adc517a" + resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-model/download/@umijs/plugin-model-2.6.2.tgz" integrity sha1-d5pyauCwdGcj3xZqKOF/AmrcUXo= dependencies: fast-deep-equal "3.1.1" "@umijs/plugin-openapi@1.3.3": version "1.3.3" - resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-openapi/download/@umijs/plugin-openapi-1.3.3.tgz#c527e9f4b4bad2140fbe860ce9a222d35959e746" + resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-openapi/download/@umijs/plugin-openapi-1.3.3.tgz" integrity sha512-z1gJpX1MDAO5YlJH+zsQ4bq0jgmIoy89k5lyTylVvP22M31h7sC9cAwNHmQeJMzGatYooGJu//rnThsSlRdIUg== dependencies: "@umijs/openapi" "^1.2.0" @@ -2555,7 +3340,7 @@ "@umijs/plugin-request@2.8.0": version "2.8.0" - resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-request/download/@umijs/plugin-request-2.8.0.tgz#f2ac21a1e39e6a2f94b42f1b348a4b480b355139" + resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-request/download/@umijs/plugin-request-2.8.0.tgz" integrity sha1-8qwhoeOeai+UtC8bNIpLSAs1UTk= dependencies: "@ahooksjs/use-request" "^2.0.0" @@ -2563,14 +3348,14 @@ "@umijs/plugin-test@1.0.2": version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-test/download/@umijs/plugin-test-1.0.2.tgz#df67c7b6e31bf4df4e2857d04a103046e557143d" + resolved "https://registry.npm.alibaba-inc.com/@umijs/plugin-test/download/@umijs/plugin-test-1.0.2.tgz" integrity sha1-32fHtuMb9N9OKFfQShAwRuVXFD0= dependencies: "@umijs/test" "~3.5.14" "@umijs/preset-built-in@3.5.35": version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/@umijs/preset-built-in/download/@umijs/preset-built-in-3.5.35.tgz#999ff6a40af1d7c419e749ab42348b872ede149e" + resolved "https://registry.npm.alibaba-inc.com/@umijs/preset-built-in/download/@umijs/preset-built-in-3.5.35.tgz" integrity sha512-t7LxPMnkpqvLEWb2mGeycbgGWKt1zbxugRKGX0d8AZMEHaZji/wENVrIiTnzvr8FnJHPjoMoXeCHxt8rlyKw3A== dependencies: "@types/react-router-config" "5.0.2" @@ -2602,7 +3387,7 @@ "@umijs/preset-react@1.8.31": version "1.8.31" - resolved "https://registry.npm.alibaba-inc.com/@umijs/preset-react/download/@umijs/preset-react-1.8.31.tgz#3f5a5604c8f9353685e990475bc15814059df6ce" + resolved "https://registry.npm.alibaba-inc.com/@umijs/preset-react/download/@umijs/preset-react-1.8.31.tgz" integrity sha512-zQRYJw68mgG6pPcy6GwAXFRC/XxATIGmiaFAZHt7aYDy3VCccmjNKjs1pXqrcHYmGhoa7TyjCHUYEuJSv0n8uw== dependencies: "@umijs/plugin-access" "2.4.3" @@ -2620,7 +3405,7 @@ "@umijs/renderer-mpa@3.5.35": version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/@umijs/renderer-mpa/download/@umijs/renderer-mpa-3.5.35.tgz#617937784fbdc89755aa3c811c8f12512786b6e0" + resolved "https://registry.npm.alibaba-inc.com/@umijs/renderer-mpa/download/@umijs/renderer-mpa-3.5.35.tgz" integrity sha512-FmqnaRRph6hg1zCWQw1vJfUwU9M73AL5Q7FFbcori3Ush51UkhnKfwkX3gRgXNMiiOMXrEDD5btCJWqaRLfhyg== dependencies: "@types/react" "^16.9.43" @@ -2629,7 +3414,7 @@ "@umijs/renderer-react@3.5.35": version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/@umijs/renderer-react/download/@umijs/renderer-react-3.5.35.tgz#b96733b8f6c61db8e861899386979767ae367db8" + resolved "https://registry.npm.alibaba-inc.com/@umijs/renderer-react/download/@umijs/renderer-react-3.5.35.tgz" integrity sha512-2s7dx5RtTNX42JzPYMDErRwAswatXiG6mK6ittdisPtr0TP3uXG3B0TwThqtEsHlE8yMTDrWgRmTOvwmsYHaMA== dependencies: "@types/react" "^16.9.43" @@ -2640,7 +3425,7 @@ "@umijs/route-utils@^1.0.5": version "1.0.37" - resolved "https://registry.npm.alibaba-inc.com/@umijs/route-utils/download/@umijs/route-utils-1.0.37.tgz#1ceb516980d4754ce2d5959878fe72259091a990" + resolved "https://registry.npm.alibaba-inc.com/@umijs/route-utils/download/@umijs/route-utils-1.0.37.tgz" integrity sha1-HOtRaYDUdUzi1ZWYeP5yJZCRqZA= dependencies: "@qixian.cs/path-to-regexp" "^6.1.0" @@ -2650,7 +3435,7 @@ "@umijs/route-utils@^2.0.0", "@umijs/route-utils@^2.1.0": version "2.2.1" - resolved "https://registry.npm.alibaba-inc.com/@umijs/route-utils/download/@umijs/route-utils-2.2.1.tgz#b517ec203c709b1d53254af30dc86b0fb02c0c13" + resolved "https://registry.npm.alibaba-inc.com/@umijs/route-utils/download/@umijs/route-utils-2.2.1.tgz" integrity sha512-MSkqBGRU+pThh8HE7UOfLal2WUBxJKpkuf+E/DxNrbfct4YJBv9Gv5fvueYTnZXoBAJVlTq01rHNtzVddTRggA== dependencies: "@qixian.cs/path-to-regexp" "^6.1.0" @@ -2658,9 +3443,14 @@ lodash.isequal "^4.5.0" memoize-one "^5.1.1" +"@umijs/route-utils@^4.0.0": + version "4.0.1" + resolved "https://registry.npmjs.org/@umijs/route-utils/-/route-utils-4.0.1.tgz" + integrity sha512-+1ixf1BTOLuH+ORb4x8vYMPeIt38n9q0fJDwhv9nSxrV46mxbLF0nmELIo9CKQB2gHfuC4+hww6xejJ6VYnBHQ== + "@umijs/runtime@3.5.35": version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/@umijs/runtime/download/@umijs/runtime-3.5.35.tgz#3aa855053461993e0825cbf9ba1d4d0d4f2e5932" + resolved "https://registry.npm.alibaba-inc.com/@umijs/runtime/download/@umijs/runtime-3.5.35.tgz" integrity sha512-RZojTaESpu7H1xxjEAqOW53aGA/8gRxUN0/2FW+EOD6getRC4pptuEzFInfu93NfLa06hsXJO31zgYKukTF+Kw== dependencies: "@types/react-router" "5.1.12" @@ -2672,7 +3462,7 @@ "@umijs/server@3.5.35": version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/@umijs/server/download/@umijs/server-3.5.35.tgz#738c9cab15184192ebabc13833627878a75b49c6" + resolved "https://registry.npm.alibaba-inc.com/@umijs/server/download/@umijs/server-3.5.35.tgz" integrity sha512-U8WXA2GXcR0lRjx1xaW2ub12B+FiKTey+8XdAyxfEhupHwq3nnyY1megshe4aC1n+0O+ByG8tvaKfuH9YZ9XyA== dependencies: "@umijs/core" "3.5.35" @@ -2681,12 +3471,12 @@ "@umijs/ssr-darkreader@^4.9.44": version "4.9.45" - resolved "https://registry.npm.alibaba-inc.com/@umijs/ssr-darkreader/download/@umijs/ssr-darkreader-4.9.45.tgz#7f13cfc89616f3203290775eb61b53047ece1733" + resolved "https://registry.npm.alibaba-inc.com/@umijs/ssr-darkreader/download/@umijs/ssr-darkreader-4.9.45.tgz" integrity sha512-XlcwzSYQ/SRZpHdwIyMDS4FOGX5kP4U/2g2mykyn/iPQTK4xTiQAyBu6UnnDnn7d5P8s7Atzh1C7H0ETNOypJg== "@umijs/test@3.5.35", "@umijs/test@~3.5.14": version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/@umijs/test/download/@umijs/test-3.5.35.tgz#1eeddbafaf4bd4220b4078e0d67a4abc3491fdf5" + resolved "https://registry.npm.alibaba-inc.com/@umijs/test/download/@umijs/test-3.5.35.tgz" integrity sha512-6GHT9zbbPaDrHkQiMfKG/lzoBl3SD2zdHJ7ldHSpOvLv6bszFlG+jcc1HB8CreYbUhFgovTKDi1uAwzot5P+0w== dependencies: "@babel/core" "7.18.6" @@ -2702,7 +3492,7 @@ "@umijs/types@3.5.35": version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/@umijs/types/download/@umijs/types-3.5.35.tgz#873d2c692e7a57652baca34de71db44379c57b53" + resolved "https://registry.npm.alibaba-inc.com/@umijs/types/download/@umijs/types-3.5.35.tgz" integrity sha512-hjFHnAghxZOQsj8rdTHHfkHGsyhpFnvDAK8TX4u6UPL6ugleyzg8wxXZmU/SNkSyzqM4U/18Azt6oG39bAV8UQ== dependencies: "@umijs/babel-preset-umi" "3.5.35" @@ -2715,12 +3505,12 @@ "@umijs/use-params@^1.0.9": version "1.0.9" - resolved "https://registry.npm.alibaba-inc.com/@umijs/use-params/download/@umijs/use-params-1.0.9.tgz#0ae4a87f4922d8e8e3fb4495b0f8f4de9ca38c52" + resolved "https://registry.npm.alibaba-inc.com/@umijs/use-params/download/@umijs/use-params-1.0.9.tgz" integrity sha512-QlN0RJSBVQBwLRNxbxjQ5qzqYIGn+K7USppMoIOVlf7fxXHsnQZ2bEsa6Pm74bt6DVQxpUE8HqvdStn6Y9FV1w== "@umijs/utils@3.5.35": version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/@umijs/utils/download/@umijs/utils-3.5.35.tgz#21d57c236c2acf305c317261db19bc6206d3118e" + resolved "https://registry.npm.alibaba-inc.com/@umijs/utils/download/@umijs/utils-3.5.35.tgz" integrity sha512-xYto01cUMXiNpM7FZrWmx5db85UlpLJMCSiPzbo4YUfUfeGySKBeeRVNkBFOKpaImetEx2TDxby7KILPPjSo4w== dependencies: "@umijs/babel-preset-umi" "3.5.35" @@ -2728,7 +3518,7 @@ "@videojs/http-streaming@2.14.3": version "2.14.3" - resolved "https://registry.npm.alibaba-inc.com/@videojs/http-streaming/download/@videojs/http-streaming-2.14.3.tgz#3277e03b576766decb4fc663e954e18bfa10d2a1" + resolved "https://registry.npm.alibaba-inc.com/@videojs/http-streaming/download/@videojs/http-streaming-2.14.3.tgz" integrity sha512-2tFwxCaNbcEZzQugWf8EERwNMyNtspfHnvxRGRABQs09W/5SqmkWFuGWfUAm4wQKlXGfdPyAJ1338ASl459xAA== dependencies: "@babel/runtime" "^7.12.5" @@ -2742,7 +3532,7 @@ "@videojs/http-streaming@2.16.2": version "2.16.2" - resolved "https://registry.npm.alibaba-inc.com/@videojs/http-streaming/download/@videojs/http-streaming-2.16.2.tgz#a9be925b4e368a41dbd67d49c4f566715169b84b" + resolved "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-2.16.2.tgz" integrity sha512-etPTUdCFu7gUWc+1XcbiPr+lrhOcBu3rV5OL1M+3PDW89zskScAkkcdqYzP4pFodBPye/ydamQoTDScOnElw5A== dependencies: "@babel/runtime" "^7.12.5" @@ -2756,7 +3546,7 @@ "@videojs/vhs-utils@3.0.5", "@videojs/vhs-utils@^3.0.4", "@videojs/vhs-utils@^3.0.5": version "3.0.5" - resolved "https://registry.npm.alibaba-inc.com/@videojs/vhs-utils/download/@videojs/vhs-utils-3.0.5.tgz#665ba70d78258ba1ab977364e2fe9f4d4799c46c" + resolved "https://registry.npm.alibaba-inc.com/@videojs/vhs-utils/download/@videojs/vhs-utils-3.0.5.tgz" integrity sha512-PKVgdo8/GReqdx512F+ombhS+Bzogiofy1LgAj4tN8PfdBx3HSS7V5WfJotKTqtOWGwVfSWsrYN/t09/DSryrw== dependencies: "@babel/runtime" "^7.12.5" @@ -2765,7 +3555,7 @@ "@videojs/xhr@2.6.0": version "2.6.0" - resolved "https://registry.npm.alibaba-inc.com/@videojs/xhr/download/@videojs/xhr-2.6.0.tgz#cd897e0ad54faf497961bcce3fa16dc15a26bb80" + resolved "https://registry.npm.alibaba-inc.com/@videojs/xhr/download/@videojs/xhr-2.6.0.tgz" integrity sha1-zYl+CtVPr0l5YbzOP6FtwVomu4A= dependencies: "@babel/runtime" "^7.5.5" @@ -2774,27 +3564,27 @@ "@xmldom/xmldom@^0.7.2": version "0.7.10" - resolved "https://registry.npm.alibaba-inc.com/@xmldom/xmldom/download/@xmldom/xmldom-0.7.10.tgz#b1f4a7dc63ac35b2750847644d5dacf5b4ead12f" + resolved "https://registry.npm.alibaba-inc.com/@xmldom/xmldom/download/@xmldom/xmldom-0.7.10.tgz" integrity sha512-hb9QhOg5MGmpVkFcoZ9XJMe1em5gd0e2eqqjK87O1dwULedXsnY/Zg/Ju6lcohA+t6jVkmKpe7I1etqhvdRdrQ== "@xmldom/xmldom@^0.8.3": - version "0.8.6" - resolved "https://registry.npm.alibaba-inc.com/@xmldom/xmldom/download/@xmldom/xmldom-0.8.6.tgz#8a1524eb5bd5e965c1e3735476f0262469f71440" - integrity sha512-uRjjusqpoqfmRkTaNuLJ2VohVr67Q5YwDATW3VU7PfzTj6IRaihGrYI7zckGZjxQPBIp63nfvJbM+Yu5ICh0Bg== + version "0.8.10" + resolved "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz" + integrity sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw== a-sync-waterfall@^1.0.0: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/a-sync-waterfall/download/a-sync-waterfall-1.0.1.tgz#75b6b6aa72598b497a125e7a2770f14f4c8a1fa7" + resolved "https://registry.npm.alibaba-inc.com/a-sync-waterfall/download/a-sync-waterfall-1.0.1.tgz" integrity sha1-dba2qnJZi0l6El56J3DxT0yKH6c= abab@^2.0.3, abab@^2.0.5: version "2.0.6" - resolved "https://registry.npm.alibaba-inc.com/abab/download/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" + resolved "https://registry.npm.alibaba-inc.com/abab/download/abab-2.0.6.tgz" integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== acorn-globals@^6.0.0: version "6.0.0" - resolved "https://registry.npm.alibaba-inc.com/acorn-globals/download/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" + resolved "https://registry.npm.alibaba-inc.com/acorn-globals/download/acorn-globals-6.0.0.tgz" integrity sha1-Rs3Tnw+P8IqHZhm1X1rIptx3C0U= dependencies: acorn "^7.1.1" @@ -2802,34 +3592,34 @@ acorn-globals@^6.0.0: acorn-jsx@^5.3.1: version "5.3.2" - resolved "https://registry.npm.alibaba-inc.com/acorn-jsx/download/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + resolved "https://registry.npm.alibaba-inc.com/acorn-jsx/download/acorn-jsx-5.3.2.tgz" integrity sha1-ftW7VZCLOy8bxVxq8WU7rafweTc= acorn-walk@^7.1.1: version "7.2.0" - resolved "https://registry.npm.alibaba-inc.com/acorn-walk/download/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + resolved "https://registry.npm.alibaba-inc.com/acorn-walk/download/acorn-walk-7.2.0.tgz" integrity sha1-DeiJpgEgOQmw++B7iTjcIdLpZ7w= acorn@^7.1.1, acorn@^7.4.0: version "7.4.1" - resolved "https://registry.npm.alibaba-inc.com/acorn/download/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + resolved "https://registry.npm.alibaba-inc.com/acorn/download/acorn-7.4.1.tgz" integrity sha1-/q7SVZc9LndVW4PbwIhRpsY1IPo= acorn@^8.2.4, acorn@^8.5.0: version "8.8.1" - resolved "https://registry.npm.alibaba-inc.com/acorn/download/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" + resolved "https://registry.npm.alibaba-inc.com/acorn/download/acorn-8.8.1.tgz" integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== add-dom-event-listener@^1.1.0: version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/add-dom-event-listener/download/add-dom-event-listener-1.1.0.tgz#6a92db3a0dd0abc254e095c0f1dc14acbbaae310" + resolved "https://registry.npm.alibaba-inc.com/add-dom-event-listener/download/add-dom-event-listener-1.1.0.tgz" integrity sha1-apLbOg3Qq8JU4JXA8dwUrLuq4xA= dependencies: object-assign "4.x" aes-decrypter@3.1.3: version "3.1.3" - resolved "https://registry.npm.alibaba-inc.com/aes-decrypter/download/aes-decrypter-3.1.3.tgz#65ff5f2175324d80c41083b0e135d1464b12ac35" + resolved "https://registry.npm.alibaba-inc.com/aes-decrypter/download/aes-decrypter-3.1.3.tgz" integrity sha512-VkG9g4BbhMBy+N5/XodDeV6F02chEk9IpgRTq/0bS80y4dzy79VH2Gtms02VXomf3HmyRe3yyJYkJ990ns+d6A== dependencies: "@babel/runtime" "^7.12.5" @@ -2839,32 +3629,48 @@ aes-decrypter@3.1.3: agent-base@6: version "6.0.2" - resolved "https://registry.npm.alibaba-inc.com/agent-base/download/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + resolved "https://registry.npm.alibaba-inc.com/agent-base/download/agent-base-6.0.2.tgz" integrity sha1-Sf/1hXfP7j83F2/qtMIuAPhtf3c= dependencies: debug "4" aggregate-error@^3.0.0: version "3.1.0" - resolved "https://registry.npm.alibaba-inc.com/aggregate-error/download/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + resolved "https://registry.npm.alibaba-inc.com/aggregate-error/download/aggregate-error-3.1.0.tgz" integrity sha1-kmcP9Q9TWb23o+DUDQ7DDFc3aHo= dependencies: clean-stack "^2.0.0" indent-string "^4.0.0" +ahooks@^2.10.14: + version "2.10.14" + resolved "https://registry.npmjs.org/ahooks/-/ahooks-2.10.14.tgz" + integrity sha512-axWa7VoAgu7bxA56dDl0CXW4rvaQmDBiov/d3tAy0x1YNYywYMKokL8TdLgJ5zO/oXGiWmG7BxlGOQGkqE/zkQ== + dependencies: + "@ahooksjs/use-request" "^2.8.14" + "@types/js-cookie" "^2.2.6" + dayjs "^1.9.1" + 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.0.0" + ajv-errors@^1.0.0: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/ajv-errors/download/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" + resolved "https://registry.npm.alibaba-inc.com/ajv-errors/download/ajv-errors-1.0.1.tgz" integrity sha1-81mGrOuRr63sQQL72FAUlQzvpk0= ajv-keywords@^3.1.0, ajv-keywords@^3.5.2: version "3.5.2" - resolved "https://registry.npm.alibaba-inc.com/ajv-keywords/download/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + resolved "https://registry.npm.alibaba-inc.com/ajv-keywords/download/ajv-keywords-3.5.2.tgz" integrity sha1-MfKdpatuANHC0yms97WSlhTVAU0= ajv@^6.1.0, ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" - resolved "https://registry.npm.alibaba-inc.com/ajv/download/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + resolved "https://registry.npm.alibaba-inc.com/ajv/download/ajv-6.12.6.tgz" integrity sha1-uvWmLoArB9l3A0WG+MO69a3ybfQ= dependencies: fast-deep-equal "^3.1.1" @@ -2874,7 +3680,7 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5: ajv@^8.0.1: version "8.11.2" - resolved "https://registry.npm.alibaba-inc.com/ajv/download/ajv-8.11.2.tgz#aecb20b50607acf2569b6382167b65a96008bb78" + resolved "https://registry.npm.alibaba-inc.com/ajv/download/ajv-8.11.2.tgz" integrity sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg== dependencies: fast-deep-equal "^3.1.1" @@ -2884,43 +3690,43 @@ ajv@^8.0.1: ansi-colors@^4.1.1: version "4.1.3" - resolved "https://registry.npm.alibaba-inc.com/ansi-colors/download/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + resolved "https://registry.npm.alibaba-inc.com/ansi-colors/download/ansi-colors-4.1.3.tgz" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: version "4.3.2" - resolved "https://registry.npm.alibaba-inc.com/ansi-escapes/download/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + resolved "https://registry.npm.alibaba-inc.com/ansi-escapes/download/ansi-escapes-4.3.2.tgz" integrity sha1-ayKR0dt9mLZSHV8e+kLQ86n+tl4= dependencies: type-fest "^0.21.3" ansi-html@^0.0.9: version "0.0.9" - resolved "https://registry.npm.alibaba-inc.com/ansi-html/download/ansi-html-0.0.9.tgz#6512d02342ae2cc68131952644a129cb734cd3f0" + resolved "https://registry.npm.alibaba-inc.com/ansi-html/download/ansi-html-0.0.9.tgz" integrity sha512-ozbS3LuenHVxNRh/wdnN16QapUHzauqSomAl1jwwJRRsGwFwtj644lIhxfWu0Fy0acCij2+AEgHvjscq3dlVXg== ansi-regex@^5.0.0, ansi-regex@^5.0.1: version "5.0.1" - resolved "https://registry.npm.alibaba-inc.com/ansi-regex/download/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + resolved "https://registry.npm.alibaba-inc.com/ansi-regex/download/ansi-regex-5.0.1.tgz" integrity sha1-CCyyyJyf6GWaMRpTvWpNxTAdswQ= ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.npm.alibaba-inc.com/ansi-styles/download/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + resolved "https://registry.npm.alibaba-inc.com/ansi-styles/download/ansi-styles-3.2.1.tgz" integrity sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0= dependencies: color-convert "^1.9.0" ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" - resolved "https://registry.npm.alibaba-inc.com/ansi-styles/download/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + resolved "https://registry.npm.alibaba-inc.com/ansi-styles/download/ansi-styles-4.3.0.tgz" integrity sha1-7dgDYornHATIWuegkG7a00tkiTc= dependencies: color-convert "^2.0.1" antd-mobile@^2.3.1: version "2.3.4" - resolved "https://registry.npm.alibaba-inc.com/antd-mobile/download/antd-mobile-2.3.4.tgz#8f584707b30343d102f3ca10fdaf677e2a5d1cc8" + resolved "https://registry.npm.alibaba-inc.com/antd-mobile/download/antd-mobile-2.3.4.tgz" integrity sha1-j1hHB7MDQ9EC88oQ/a9nfipdHMg= dependencies: array-tree-filter "~2.1.0" @@ -2949,7 +3755,7 @@ antd-mobile@^2.3.1: antd@5.0.7: version "5.0.7" - resolved "https://registry.npm.alibaba-inc.com/antd/download/antd-5.0.7.tgz#0c182ad33c9de81b204f4fa430d75480fad7e0d6" + resolved "https://registry.npm.alibaba-inc.com/antd/download/antd-5.0.7.tgz" integrity sha512-A/HO/VCS6nHMkpnjfPSxXoet1MBu6N003osaGbSI3mnOvRj0V/9jEOXJ2slj+2YNhACFYJfVyXeEamwQx2Njcw== dependencies: "@ant-design/colors" "^6.0.0" @@ -3001,7 +3807,7 @@ antd@5.0.7: antd@^4.1.2, antd@^4.1.3: version "4.24.2" - resolved "https://registry.npm.alibaba-inc.com/antd/download/antd-4.24.2.tgz#3c3d8f42846857e34eba86a1374ad63423a1d282" + resolved "https://registry.npm.alibaba-inc.com/antd/download/antd-4.24.2.tgz" integrity sha512-ItSltW72hkQCPE/xjl27n58STTGEhL85+Gj2I6TPnu5JYsAKHWfHu7hyGWXPXV015Oh48tqL1QUovxd/kCaUtg== dependencies: "@ant-design/colors" "^6.0.0" @@ -3048,17 +3854,72 @@ antd@^4.1.2, antd@^4.1.3: rc-util "^5.22.5" scroll-into-view-if-needed "^2.2.25" -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/anymatch/download/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha1-vLJLTzeTTZqnrBe0ra+J58du8us= +antd@^5.9.0: + version "5.9.0" + resolved "https://registry.npmjs.org/antd/-/antd-5.9.0.tgz" + integrity sha512-YgLGtz+GbzrQws+R7siXolUN89ERH2Kbcu8Bz98VY4fwwMSDKKhbCGkIjw9mnIhcrXpHT+FXwrqjAV3j9eakSA== dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" + "@ant-design/colors" "^7.0.0" + "@ant-design/cssinjs" "^1.16.0" + "@ant-design/icons" "^5.2.2" + "@ant-design/react-slick" "~1.0.0" + "@babel/runtime" "^7.18.3" + "@ctrl/tinycolor" "^3.6.0" + "@rc-component/color-picker" "~1.4.1" + "@rc-component/mutate-observer" "^1.1.0" + "@rc-component/tour" "~1.10.0" + "@rc-component/trigger" "^1.15.6" + "@types/jsdom" "^21.1.2" + classnames "^2.2.6" + copy-to-clipboard "^3.2.0" + dayjs "^1.11.1" + qrcode.react "^3.1.0" + rc-cascader "~3.16.0" + rc-checkbox "~3.1.0" + rc-collapse "~3.7.1" + rc-dialog "~9.2.0" + rc-drawer "~6.4.1" + rc-dropdown "~4.1.0" + rc-field-form "~1.38.0" + rc-image "~7.2.0" + rc-input "~1.1.1" + rc-input-number "~8.0.4" + rc-mentions "~2.7.0" + rc-menu "~9.12.0" + rc-motion "^2.9.0" + rc-notification "~5.1.1" + rc-pagination "~3.6.1" + rc-picker "~3.13.2" + rc-progress "~3.5.1" + rc-rate "~2.12.0" + rc-resize-observer "^1.3.1" + rc-segmented "~2.2.2" + rc-select "~14.8.1" + rc-slider "~10.2.1" + rc-steps "~6.0.1" + rc-switch "~4.1.0" + rc-table "~7.33.1" + rc-tabs "~12.12.1" + rc-textarea "~1.3.4" + rc-tooltip "~6.0.1" + rc-tree "~5.7.10" + rc-tree-select "~5.12.1" + rc-upload "~4.3.4" + rc-util "^5.37.0" + scroll-into-view-if-needed "^3.0.3" + throttle-debounce "^5.0.0" + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.alibaba-inc.com/anymatch/download/anymatch-2.0.0.tgz" + integrity sha1-vLJLTzeTTZqnrBe0ra+J58du8us= + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" anymatch@^3.0.3, anymatch@~3.1.1: version "3.1.2" - resolved "https://registry.npm.alibaba-inc.com/anymatch/download/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + resolved "https://registry.npm.alibaba-inc.com/anymatch/download/anymatch-3.1.2.tgz" integrity sha1-wFV8CWrzLxBhmPT04qODU343hxY= dependencies: normalize-path "^3.0.0" @@ -3066,34 +3927,42 @@ anymatch@^3.0.3, anymatch@~3.1.1: arch@^2.1.1: version "2.2.0" - resolved "https://registry.npm.alibaba-inc.com/arch/download/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" + resolved "https://registry.npm.alibaba-inc.com/arch/download/arch-2.2.0.tgz" integrity sha1-G8R4GPMFdk8jqzMGsL/AhsWinRE= argparse@^1.0.7: version "1.0.10" - resolved "https://registry.npm.alibaba-inc.com/argparse/download/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + resolved "https://registry.npm.alibaba-inc.com/argparse/download/argparse-1.0.10.tgz" integrity sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE= dependencies: sprintf-js "~1.0.2" arr-diff@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/arr-diff/download/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + resolved "https://registry.npm.alibaba-inc.com/arr-diff/download/arr-diff-4.0.0.tgz" integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= arr-flatten@^1.1.0: version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/arr-flatten/download/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + resolved "https://registry.npm.alibaba-inc.com/arr-flatten/download/arr-flatten-1.1.0.tgz" integrity sha1-NgSLv/TntH4TZkQxbJlmnqWukfE= arr-union@^3.1.0: version "3.1.0" - resolved "https://registry.npm.alibaba-inc.com/arr-union/download/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + resolved "https://registry.npm.alibaba-inc.com/arr-union/download/arr-union-3.1.0.tgz" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + array-includes@^3.1.5, array-includes@^3.1.6: version "3.1.6" - resolved "https://registry.npm.alibaba-inc.com/array-includes/download/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" + resolved "https://registry.npm.alibaba-inc.com/array-includes/download/array-includes-3.1.6.tgz" integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== dependencies: call-bind "^1.0.2" @@ -3104,22 +3973,34 @@ array-includes@^3.1.5, array-includes@^3.1.6: array-tree-filter@2.1.x, array-tree-filter@^2.1.0, array-tree-filter@~2.1.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/array-tree-filter/download/array-tree-filter-2.1.0.tgz#873ac00fec83749f255ac8dd083814b4f6329190" + resolved "https://registry.npm.alibaba-inc.com/array-tree-filter/download/array-tree-filter-2.1.0.tgz" integrity sha1-hzrAD+yDdJ8lWsjdCDgUtPYykZA= +array-union@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz" + integrity sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng== + dependencies: + array-uniq "^1.0.1" + array-union@^2.1.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/array-union/download/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + resolved "https://registry.npm.alibaba-inc.com/array-union/download/array-union-2.1.0.tgz" integrity sha1-t5hCCtvrHego2ErNii4j0+/oXo0= +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz" + integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q== + array-unique@^0.3.2: version "0.3.2" - resolved "https://registry.npm.alibaba-inc.com/array-unique/download/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + resolved "https://registry.npm.alibaba-inc.com/array-unique/download/array-unique-0.3.2.tgz" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= array.prototype.flatmap@^1.3.1: version "1.3.1" - resolved "https://registry.npm.alibaba-inc.com/array.prototype.flatmap/download/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" + resolved "https://registry.npm.alibaba-inc.com/array.prototype.flatmap/download/array.prototype.flatmap-1.3.1.tgz" integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== dependencies: call-bind "^1.0.2" @@ -3127,9 +4008,20 @@ array.prototype.flatmap@^1.3.1: es-abstract "^1.20.4" es-shim-unscopables "^1.0.0" +array.prototype.reduce@^1.0.6: + version "1.0.6" + resolved "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.6.tgz" + integrity sha512-UW+Mz8LG/sPSU8jRDCjVr6J/ZKAGpHfwrZ6kWTG5qCxIEiXdVshqGnu5vEZA8S1y6X4aCSbQZ0/EEsfvEvBiSg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-array-method-boxes-properly "^1.0.0" + is-string "^1.0.7" + array.prototype.tosorted@^1.1.1: version "1.1.1" - resolved "https://registry.npm.alibaba-inc.com/array.prototype.tosorted/download/array.prototype.tosorted-1.1.1.tgz#ccf44738aa2b5ac56578ffda97c03fd3e23dd532" + resolved "https://registry.npm.alibaba-inc.com/array.prototype.tosorted/download/array.prototype.tosorted-1.1.1.tgz" integrity sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ== dependencies: call-bind "^1.0.2" @@ -3138,19 +4030,37 @@ array.prototype.tosorted@^1.1.1: es-shim-unscopables "^1.0.0" get-intrinsic "^1.1.3" +arraybuffer.prototype.slice@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz" + integrity sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + is-array-buffer "^3.0.2" + is-shared-array-buffer "^1.0.2" + arrify@^1.0.1: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/arrify/download/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + resolved "https://registry.npm.alibaba-inc.com/arrify/download/arrify-1.0.1.tgz" integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= +arrify@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz" + integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== + asap@^2.0.3, asap@~2.0.3: version "2.0.6" - resolved "https://registry.npm.alibaba-inc.com/asap/download/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + resolved "https://registry.npm.alibaba-inc.com/asap/download/asap-2.0.6.tgz" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= asn1.js@^5.2.0: version "5.4.1" - resolved "https://registry.npm.alibaba-inc.com/asn1.js/download/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + resolved "https://registry.npm.alibaba-inc.com/asn1.js/download/asn1.js-5.4.1.tgz" integrity sha1-EamAuE67kXgc41sP3C7ilON4Pwc= dependencies: bn.js "^4.0.0" @@ -3160,7 +4070,7 @@ asn1.js@^5.2.0: assert@^1.1.1: version "1.5.0" - resolved "https://registry.npm.alibaba-inc.com/assert/download/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" + resolved "https://registry.npm.alibaba-inc.com/assert/download/assert-1.5.0.tgz" integrity sha1-VcEJqvbgrv2z3EtxJAxwv1dLGOs= dependencies: object-assign "^4.1.1" @@ -3168,32 +4078,37 @@ assert@^1.1.1: assign-symbols@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/assign-symbols/download/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + resolved "https://registry.npm.alibaba-inc.com/assign-symbols/download/assign-symbols-1.0.0.tgz" integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= astral-regex@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/astral-regex/download/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + resolved "https://registry.npm.alibaba-inc.com/astral-regex/download/astral-regex-2.0.0.tgz" integrity sha1-SDFDxWeu7UeFdZwIZXhtx319LjE= async-validator@^4.1.0: version "4.2.5" - resolved "https://registry.npm.alibaba-inc.com/async-validator/download/async-validator-4.2.5.tgz#c96ea3332a521699d0afaaceed510a54656c6339" + resolved "https://registry.npm.alibaba-inc.com/async-validator/download/async-validator-4.2.5.tgz" integrity sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg== +async-validator@~1.11.3: + version "1.11.5" + resolved "https://registry.npmjs.org/async-validator/-/async-validator-1.11.5.tgz" + integrity sha512-XNtCsMAeAH1pdLMEg1z8/Bb3a8cdCbui9QbJATRFHHHW5kT6+NPI3zSVQUXgikTFITzsg+kYY5NTWhM2Orwt9w== + asynckit@^0.4.0: version "0.4.0" - resolved "https://registry.npm.alibaba-inc.com/asynckit/download/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + resolved "https://registry.npm.alibaba-inc.com/asynckit/download/asynckit-0.4.0.tgz" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= atob@^2.1.2: version "2.1.2" - resolved "https://registry.npm.alibaba-inc.com/atob/download/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + resolved "https://registry.npm.alibaba-inc.com/atob/download/atob-2.1.2.tgz" integrity sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k= autoprefixer@^9.6.1, autoprefixer@^9.8.6: version "9.8.8" - resolved "https://registry.npm.alibaba-inc.com/autoprefixer/download/autoprefixer-9.8.8.tgz#fd4bd4595385fa6f06599de749a4d5f7a474957a" + resolved "https://registry.npm.alibaba-inc.com/autoprefixer/download/autoprefixer-9.8.8.tgz" integrity sha1-/UvUWVOF+m8GWZ3nSaTV96R0lXo= dependencies: browserslist "^4.12.0" @@ -3204,9 +4119,14 @@ autoprefixer@^9.6.1, autoprefixer@^9.8.6: postcss "^7.0.32" postcss-value-parser "^4.1.0" +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + babel-jest@^26.6.3: version "26.6.3" - resolved "https://registry.npm.alibaba-inc.com/babel-jest/download/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" + resolved "https://registry.npm.alibaba-inc.com/babel-jest/download/babel-jest-26.6.3.tgz" integrity sha1-2H0lywA3V3oMifguV1XF0pPAEFY= dependencies: "@jest/transform" "^26.6.2" @@ -3220,12 +4140,12 @@ babel-jest@^26.6.3: babel-plugin-dva-hmr@^0.4.2: version "0.4.2" - resolved "https://registry.npm.alibaba-inc.com/babel-plugin-dva-hmr/download/babel-plugin-dva-hmr-0.4.2.tgz#56cf3d49cc366fb191cd883e27ca42bddfd12735" + resolved "https://registry.npm.alibaba-inc.com/babel-plugin-dva-hmr/download/babel-plugin-dva-hmr-0.4.2.tgz" integrity sha1-Vs89Scw2b7GRzYg+J8pCvd/RJzU= babel-plugin-istanbul@^6.0.0: version "6.1.1" - resolved "https://registry.npm.alibaba-inc.com/babel-plugin-istanbul/download/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + resolved "https://registry.npm.alibaba-inc.com/babel-plugin-istanbul/download/babel-plugin-istanbul-6.1.1.tgz" integrity sha1-+ojsWSMv2bTjbbvFQKjsmptH2nM= dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -3236,7 +4156,7 @@ babel-plugin-istanbul@^6.0.0: babel-plugin-jest-hoist@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/babel-plugin-jest-hoist/download/babel-plugin-jest-hoist-26.6.2.tgz#8185bd030348d254c6d7dd974355e6a28b21e62d" + resolved "https://registry.npm.alibaba-inc.com/babel-plugin-jest-hoist/download/babel-plugin-jest-hoist-26.6.2.tgz" integrity sha1-gYW9AwNI0lTG192XQ1Xmoosh5i0= dependencies: "@babel/template" "^7.3.3" @@ -3246,7 +4166,7 @@ babel-plugin-jest-hoist@^26.6.2: babel-plugin-polyfill-corejs2@^0.3.3: version "0.3.3" - resolved "https://registry.npm.alibaba-inc.com/babel-plugin-polyfill-corejs2/download/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122" + resolved "https://registry.npm.alibaba-inc.com/babel-plugin-polyfill-corejs2/download/babel-plugin-polyfill-corejs2-0.3.3.tgz" integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q== dependencies: "@babel/compat-data" "^7.17.7" @@ -3255,7 +4175,7 @@ babel-plugin-polyfill-corejs2@^0.3.3: babel-plugin-polyfill-corejs3@^0.6.0: version "0.6.0" - resolved "https://registry.npm.alibaba-inc.com/babel-plugin-polyfill-corejs3/download/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a" + resolved "https://registry.npm.alibaba-inc.com/babel-plugin-polyfill-corejs3/download/babel-plugin-polyfill-corejs3-0.6.0.tgz" integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA== dependencies: "@babel/helper-define-polyfill-provider" "^0.3.3" @@ -3263,14 +4183,14 @@ babel-plugin-polyfill-corejs3@^0.6.0: babel-plugin-polyfill-regenerator@^0.4.1: version "0.4.1" - resolved "https://registry.npm.alibaba-inc.com/babel-plugin-polyfill-regenerator/download/babel-plugin-polyfill-regenerator-0.4.1.tgz#390f91c38d90473592ed43351e801a9d3e0fd747" + resolved "https://registry.npm.alibaba-inc.com/babel-plugin-polyfill-regenerator/download/babel-plugin-polyfill-regenerator-0.4.1.tgz" integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw== dependencies: "@babel/helper-define-polyfill-provider" "^0.3.3" babel-preset-current-node-syntax@^1.0.0: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/babel-preset-current-node-syntax/download/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + resolved "https://registry.npm.alibaba-inc.com/babel-preset-current-node-syntax/download/babel-preset-current-node-syntax-1.0.1.tgz" integrity sha1-tDmSObibKgEfndvj5PQB/EDP9zs= dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" @@ -3288,7 +4208,7 @@ babel-preset-current-node-syntax@^1.0.0: babel-preset-jest@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/babel-preset-jest/download/babel-preset-jest-26.6.2.tgz#747872b1171df032252426586881d62d31798fee" + resolved "https://registry.npm.alibaba-inc.com/babel-preset-jest/download/babel-preset-jest-26.6.2.tgz" integrity sha1-dHhysRcd8DIlJCZYaIHWLTF5j+4= dependencies: babel-plugin-jest-hoist "^26.6.2" @@ -3296,7 +4216,7 @@ babel-preset-jest@^26.6.2: babel-runtime@6.x, babel-runtime@^6.23.0, babel-runtime@^6.26.0: version "6.26.0" - resolved "https://registry.npm.alibaba-inc.com/babel-runtime/download/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + resolved "https://registry.npm.alibaba-inc.com/babel-runtime/download/babel-runtime-6.26.0.tgz" integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= dependencies: core-js "^2.4.0" @@ -3304,27 +4224,32 @@ babel-runtime@6.x, babel-runtime@^6.23.0, babel-runtime@^6.26.0: bail@^1.0.0: version "1.0.5" - resolved "https://registry.npm.alibaba-inc.com/bail/download/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" + resolved "https://registry.npm.alibaba-inc.com/bail/download/bail-1.0.5.tgz" integrity sha1-tvoTNASjksvB+MS/Y/WVM1Hnp3Y= balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/balanced-match/download/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + resolved "https://registry.npm.alibaba-inc.com/balanced-match/download/balanced-match-1.0.2.tgz" integrity sha1-6D46fj8wCzTLnYf2FfoMvzV2kO4= balanced-match@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/balanced-match/download/balanced-match-2.0.0.tgz#dc70f920d78db8b858535795867bf48f820633d9" + resolved "https://registry.npm.alibaba-inc.com/balanced-match/download/balanced-match-2.0.0.tgz" integrity sha1-3HD5INeNuLhYU1eVhnv0j4IGM9k= +base16@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz" + integrity sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ== + base64-js@^1.0.2: version "1.5.1" - resolved "https://registry.npm.alibaba-inc.com/base64-js/download/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + resolved "https://registry.npm.alibaba-inc.com/base64-js/download/base64-js-1.5.1.tgz" integrity sha1-GxtEAWClv3rUC2UPCVljSBkDkwo= base@^0.11.1: version "0.11.2" - resolved "https://registry.npm.alibaba-inc.com/base/download/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + resolved "https://registry.npm.alibaba-inc.com/base/download/base-0.11.2.tgz" integrity sha1-e95c7RRbbVUakNuH+DxVi060io8= dependencies: cache-base "^1.0.1" @@ -3337,27 +4262,32 @@ base@^0.11.1: big.js@^5.2.2: version "5.2.2" - resolved "https://registry.npm.alibaba-inc.com/big.js/download/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + resolved "https://registry.npm.alibaba-inc.com/big.js/download/big.js-5.2.2.tgz" integrity sha1-ZfCvOC9Xi83HQr2cKB6cstd2gyg= binary-extensions@^2.0.0: version "2.2.0" - resolved "https://registry.npm.alibaba-inc.com/binary-extensions/download/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + resolved "https://registry.npm.alibaba-inc.com/binary-extensions/download/binary-extensions-2.2.0.tgz" integrity sha1-dfUC7q+f/eQvyYgpZFvk6na9ni0= bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: version "4.12.0" - resolved "https://registry.npm.alibaba-inc.com/bn.js/download/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + resolved "https://registry.npm.alibaba-inc.com/bn.js/download/bn.js-4.12.0.tgz" integrity sha1-d1s/J477uXGO7HNh9IP7Nvu/6og= bn.js@^5.0.0, bn.js@^5.1.1: version "5.2.1" - resolved "https://registry.npm.alibaba-inc.com/bn.js/download/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + resolved "https://registry.npm.alibaba-inc.com/bn.js/download/bn.js-5.2.1.tgz" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== +boolbase@^1.0.0, boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.npm.alibaba-inc.com/brace-expansion/download/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + resolved "https://registry.npm.alibaba-inc.com/brace-expansion/download/brace-expansion-1.1.11.tgz" integrity sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0= dependencies: balanced-match "^1.0.0" @@ -3365,7 +4295,7 @@ brace-expansion@^1.1.7: braces@^2.3.1: version "2.3.2" - resolved "https://registry.npm.alibaba-inc.com/braces/download/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + resolved "https://registry.npm.alibaba-inc.com/braces/download/braces-2.3.2.tgz" integrity sha1-WXn9PxTNUxVl5fot8av/8d+u5yk= dependencies: arr-flatten "^1.1.0" @@ -3381,24 +4311,24 @@ braces@^2.3.1: braces@^3.0.2, braces@~3.0.2: version "3.0.2" - resolved "https://registry.npm.alibaba-inc.com/braces/download/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + resolved "https://registry.npm.alibaba-inc.com/braces/download/braces-3.0.2.tgz" integrity sha1-NFThpGLujVmeI23zNs2epPiv4Qc= dependencies: fill-range "^7.0.1" brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/brorand/download/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + resolved "https://registry.npm.alibaba-inc.com/brorand/download/brorand-1.1.0.tgz" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= browser-process-hrtime@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/browser-process-hrtime/download/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + resolved "https://registry.npm.alibaba-inc.com/browser-process-hrtime/download/browser-process-hrtime-1.0.0.tgz" integrity sha1-PJtLfXgsgSHlbxAQbYTA0P/JRiY= browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.2.0" - resolved "https://registry.npm.alibaba-inc.com/browserify-aes/download/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + resolved "https://registry.npm.alibaba-inc.com/browserify-aes/download/browserify-aes-1.2.0.tgz" integrity sha1-Mmc0ZC9APavDADIJhTu3CtQo70g= dependencies: buffer-xor "^1.0.3" @@ -3410,7 +4340,7 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4: browserify-cipher@^1.0.0: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/browserify-cipher/download/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + resolved "https://registry.npm.alibaba-inc.com/browserify-cipher/download/browserify-cipher-1.0.1.tgz" integrity sha1-jWR0wbhwv9q807z8wZNKEOlPFfA= dependencies: browserify-aes "^1.0.4" @@ -3419,7 +4349,7 @@ browserify-cipher@^1.0.0: browserify-des@^1.0.0: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/browserify-des/download/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + resolved "https://registry.npm.alibaba-inc.com/browserify-des/download/browserify-des-1.0.2.tgz" integrity sha1-OvTx9Zg5QDVy8cZiBDdfen9wPpw= dependencies: cipher-base "^1.0.1" @@ -3429,7 +4359,7 @@ browserify-des@^1.0.0: browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: version "4.1.0" - resolved "https://registry.npm.alibaba-inc.com/browserify-rsa/download/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + resolved "https://registry.npm.alibaba-inc.com/browserify-rsa/download/browserify-rsa-4.1.0.tgz" integrity sha1-sv0Gtbda4pf3zi3GUfkY9b4VjI0= dependencies: bn.js "^5.0.0" @@ -3437,7 +4367,7 @@ browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: browserify-sign@^4.0.0: version "4.2.1" - resolved "https://registry.npm.alibaba-inc.com/browserify-sign/download/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" + resolved "https://registry.npm.alibaba-inc.com/browserify-sign/download/browserify-sign-4.2.1.tgz" integrity sha1-6vSt1G3VS+O7OzbAzxWrvrp5VsM= dependencies: bn.js "^5.1.1" @@ -3452,14 +4382,14 @@ browserify-sign@^4.0.0: browserify-zlib@^0.2.0: version "0.2.0" - resolved "https://registry.npm.alibaba-inc.com/browserify-zlib/download/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + resolved "https://registry.npm.alibaba-inc.com/browserify-zlib/download/browserify-zlib-0.2.0.tgz" integrity sha1-KGlFnZqjviRf6P4sofRuLn9U1z8= dependencies: pako "~1.0.5" browserslist@^4.12.0, browserslist@^4.21.3, browserslist@^4.21.4, browserslist@^4.6.4: version "4.21.4" - resolved "https://registry.npm.alibaba-inc.com/browserslist/download/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" + resolved "https://registry.npm.alibaba-inc.com/browserslist/download/browserslist-4.21.4.tgz" integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== dependencies: caniuse-lite "^1.0.30001400" @@ -3469,24 +4399,24 @@ browserslist@^4.12.0, browserslist@^4.21.3, browserslist@^4.21.4, browserslist@^ bser@2.1.1: version "2.1.1" - resolved "https://registry.npm.alibaba-inc.com/bser/download/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + resolved "https://registry.npm.alibaba-inc.com/bser/download/bser-2.1.1.tgz" integrity sha1-5nh9og7OnQeZhTPP2d5vXDj0vAU= dependencies: node-int64 "^0.4.0" buffer-from@^1.0.0: version "1.1.2" - resolved "https://registry.npm.alibaba-inc.com/buffer-from/download/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + resolved "https://registry.npm.alibaba-inc.com/buffer-from/download/buffer-from-1.1.2.tgz" integrity sha1-KxRqb9cugLT1XSVfNe1Zo6mkG9U= buffer-xor@^1.0.3: version "1.0.3" - resolved "https://registry.npm.alibaba-inc.com/buffer-xor/download/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + resolved "https://registry.npm.alibaba-inc.com/buffer-xor/download/buffer-xor-1.0.3.tgz" integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= buffer@^4.3.0: version "4.9.2" - resolved "https://registry.npm.alibaba-inc.com/buffer/download/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + resolved "https://registry.npm.alibaba-inc.com/buffer/download/buffer-4.9.2.tgz" integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== dependencies: base64-js "^1.0.2" @@ -3495,12 +4425,12 @@ buffer@^4.3.0: builtin-status-codes@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/builtin-status-codes/download/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + resolved "https://registry.npm.alibaba-inc.com/builtin-status-codes/download/builtin-status-codes-3.0.0.tgz" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= cache-base@^1.0.1: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/cache-base/download/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + resolved "https://registry.npm.alibaba-inc.com/cache-base/download/cache-base-1.0.1.tgz" integrity sha1-Cn9GQWgxyLZi7jb+TnxZ129marI= dependencies: collection-visit "^1.0.0" @@ -3515,7 +4445,7 @@ cache-base@^1.0.1: call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/call-bind/download/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + resolved "https://registry.npm.alibaba-inc.com/call-bind/download/call-bind-1.0.2.tgz" integrity sha1-sdTonmiBGcPJqQOtMKuy9qkZvjw= dependencies: function-bind "^1.1.1" @@ -3523,36 +4453,36 @@ call-bind@^1.0.0, call-bind@^1.0.2: call-me-maybe@^1.0.1: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/call-me-maybe/download/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa" + resolved "https://registry.npm.alibaba-inc.com/call-me-maybe/download/call-me-maybe-1.0.2.tgz" integrity sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ== caller-callsite@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/caller-callsite/download/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + resolved "https://registry.npm.alibaba-inc.com/caller-callsite/download/caller-callsite-2.0.0.tgz" integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= dependencies: callsites "^2.0.0" caller-path@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/caller-path/download/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + resolved "https://registry.npm.alibaba-inc.com/caller-path/download/caller-path-2.0.0.tgz" integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= dependencies: caller-callsite "^2.0.0" callsites@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/callsites/download/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + resolved "https://registry.npm.alibaba-inc.com/callsites/download/callsites-2.0.0.tgz" integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= callsites@^3.0.0: version "3.1.0" - resolved "https://registry.npm.alibaba-inc.com/callsites/download/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + resolved "https://registry.npm.alibaba-inc.com/callsites/download/callsites-3.1.0.tgz" integrity sha1-s2MKvYlDQy9Us/BRkjjjPNffL3M= camelcase-keys@^6.2.2: version "6.2.2" - resolved "https://registry.npm.alibaba-inc.com/camelcase-keys/download/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" + resolved "https://registry.npm.alibaba-inc.com/camelcase-keys/download/camelcase-keys-6.2.2.tgz" integrity sha1-XnVda6UaoiPsfT1S8ld4IQ+dw8A= dependencies: camelcase "^5.3.1" @@ -3561,29 +4491,29 @@ camelcase-keys@^6.2.2: camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" - resolved "https://registry.npm.alibaba-inc.com/camelcase/download/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + resolved "https://registry.npm.alibaba-inc.com/camelcase/download/camelcase-5.3.1.tgz" integrity sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA= camelcase@^6.0.0: version "6.3.0" - resolved "https://registry.npm.alibaba-inc.com/camelcase/download/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + resolved "https://registry.npm.alibaba-inc.com/camelcase/download/camelcase-6.3.0.tgz" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001400: - version "1.0.30001431" - resolved "https://registry.npm.alibaba-inc.com/caniuse-lite/download/caniuse-lite-1.0.30001431.tgz#e7c59bd1bc518fae03a4656be442ce6c4887a795" - integrity sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ== + version "1.0.30001534" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001534.tgz" + integrity sha512-vlPVrhsCS7XaSh2VvWluIQEzVhefrUQcEsQWSS5A5V+dM07uv1qHeQzAOTGIMy9i3e9bH15+muvI/UHojVgS/Q== capture-exit@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/capture-exit/download/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" + resolved "https://registry.npm.alibaba-inc.com/capture-exit/download/capture-exit-2.0.0.tgz" integrity sha1-+5U7+uvreB9iiYI52rtCbQilCaQ= dependencies: rsvp "^4.8.4" -chalk@^2.0.0, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" - resolved "https://registry.npm.alibaba-inc.com/chalk/download/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + resolved "https://registry.npm.alibaba-inc.com/chalk/download/chalk-2.4.2.tgz" integrity sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ= dependencies: ansi-styles "^3.2.1" @@ -3592,7 +4522,7 @@ chalk@^2.0.0, chalk@^2.4.2: chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: version "4.1.2" - resolved "https://registry.npm.alibaba-inc.com/chalk/download/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + resolved "https://registry.npm.alibaba-inc.com/chalk/download/chalk-4.1.2.tgz" integrity sha1-qsTit3NKdAhnrrFr8CqtVWoeegE= dependencies: ansi-styles "^4.1.0" @@ -3600,27 +4530,27 @@ chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: char-regex@^1.0.2: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/char-regex/download/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + resolved "https://registry.npm.alibaba-inc.com/char-regex/download/char-regex-1.0.2.tgz" integrity sha1-10Q1giYhf5ge1Y9Hmx1rzClUXc8= character-entities-legacy@^1.0.0: version "1.1.4" - resolved "https://registry.npm.alibaba-inc.com/character-entities-legacy/download/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" + resolved "https://registry.npm.alibaba-inc.com/character-entities-legacy/download/character-entities-legacy-1.1.4.tgz" integrity sha1-lLwYRdznClu50uzHSHJWYSk9j8E= character-entities@^1.0.0: version "1.2.4" - resolved "https://registry.npm.alibaba-inc.com/character-entities/download/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" + resolved "https://registry.npm.alibaba-inc.com/character-entities/download/character-entities-1.2.4.tgz" integrity sha1-4Sw5Obfq9OWxXnrUxeKOHUjFsWs= character-reference-invalid@^1.0.0: version "1.1.4" - resolved "https://registry.npm.alibaba-inc.com/character-reference-invalid/download/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" + resolved "https://registry.npm.alibaba-inc.com/character-reference-invalid/download/character-reference-invalid-1.1.4.tgz" integrity sha1-CDMpzaDq4nKrPbvzfpo4LBOvFWA= chokidar@3.5.1: version "3.5.1" - resolved "https://registry.npm.alibaba-inc.com/chokidar/download/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" + resolved "https://registry.npm.alibaba-inc.com/chokidar/download/chokidar-3.5.1.tgz" integrity sha1-7pznu+vSt59J8wR5nVRo4x4U5oo= dependencies: anymatch "~3.1.1" @@ -3635,17 +4565,17 @@ chokidar@3.5.1: ci-info@^1.5.0: version "1.6.0" - resolved "https://registry.npm.alibaba-inc.com/ci-info/download/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" + resolved "https://registry.npm.alibaba-inc.com/ci-info/download/ci-info-1.6.0.tgz" integrity sha1-LKINu5zrMtRSSmgzAzE/AwSx5Jc= ci-info@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/ci-info/download/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + resolved "https://registry.npm.alibaba-inc.com/ci-info/download/ci-info-2.0.0.tgz" integrity sha1-Z6npZL4xpR4V5QENWObxKDQAL0Y= cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" - resolved "https://registry.npm.alibaba-inc.com/cipher-base/download/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + resolved "https://registry.npm.alibaba-inc.com/cipher-base/download/cipher-base-1.0.4.tgz" integrity sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94= dependencies: inherits "^2.0.1" @@ -3653,12 +4583,12 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: cjs-module-lexer@^0.6.0: version "0.6.0" - resolved "https://registry.npm.alibaba-inc.com/cjs-module-lexer/download/cjs-module-lexer-0.6.0.tgz#4186fcca0eae175970aee870b9fe2d6cf8d5655f" + resolved "https://registry.npm.alibaba-inc.com/cjs-module-lexer/download/cjs-module-lexer-0.6.0.tgz" integrity sha1-QYb8yg6uF1lwruhwuf4tbPjVZV8= class-utils@^0.3.5: version "0.3.6" - resolved "https://registry.npm.alibaba-inc.com/class-utils/download/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + resolved "https://registry.npm.alibaba-inc.com/class-utils/download/class-utils-0.3.6.tgz" integrity sha1-+TNprouafOAv1B+q0MqDAzGQxGM= dependencies: arr-union "^3.1.0" @@ -3668,39 +4598,44 @@ class-utils@^0.3.5: classnames@2.x, classnames@^2.2.0, classnames@^2.2.1, classnames@^2.2.3, classnames@^2.2.4, classnames@^2.2.5, classnames@^2.2.6, classnames@^2.3.1, classnames@^2.3.2: version "2.3.2" - resolved "https://registry.npm.alibaba-inc.com/classnames/download/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" + resolved "https://registry.npm.alibaba-inc.com/classnames/download/classnames-2.3.2.tgz" integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== clean-regexp@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/clean-regexp/download/clean-regexp-1.0.0.tgz#8df7c7aae51fd36874e8f8d05b9180bc11a3fed7" + resolved "https://registry.npm.alibaba-inc.com/clean-regexp/download/clean-regexp-1.0.0.tgz" integrity sha1-jffHquUf02h06PjQW5GAvBGj/tc= dependencies: escape-string-regexp "^1.0.5" clean-stack@^2.0.0: version "2.2.0" - resolved "https://registry.npm.alibaba-inc.com/clean-stack/download/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + resolved "https://registry.npm.alibaba-inc.com/clean-stack/download/clean-stack-2.2.0.tgz" integrity sha1-7oRy27Ep5yezHooQpCfe6d/kAIs= cli-cursor@^3.1.0: version "3.1.0" - resolved "https://registry.npm.alibaba-inc.com/cli-cursor/download/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + resolved "https://registry.npm.alibaba-inc.com/cli-cursor/download/cli-cursor-3.1.0.tgz" integrity sha1-JkMFp65JDR0Dvwybp8kl0XU68wc= dependencies: restore-cursor "^3.1.0" cli-truncate@^2.1.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/cli-truncate/download/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" + resolved "https://registry.npm.alibaba-inc.com/cli-truncate/download/cli-truncate-2.1.0.tgz" integrity sha1-w54ovwXtzeW+O5iZKiLe7Vork8c= dependencies: slice-ansi "^3.0.0" string-width "^4.2.0" +client-only@^0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz" + integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== + clipboardy@2.3.0: version "2.3.0" - resolved "https://registry.npm.alibaba-inc.com/clipboardy/download/clipboardy-2.3.0.tgz#3c2903650c68e46a91b388985bc2774287dba290" + resolved "https://registry.npm.alibaba-inc.com/clipboardy/download/clipboardy-2.3.0.tgz" integrity sha1-PCkDZQxo5GqRs4iYW8J3QofbopA= dependencies: arch "^2.1.1" @@ -3709,7 +4644,7 @@ clipboardy@2.3.0: cliui@^6.0.0: version "6.0.0" - resolved "https://registry.npm.alibaba-inc.com/cliui/download/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + resolved "https://registry.npm.alibaba-inc.com/cliui/download/cliui-6.0.0.tgz" integrity sha1-UR1wLAxOQcoVbX0OlgIfI+EyJbE= dependencies: string-width "^4.2.0" @@ -3718,7 +4653,7 @@ cliui@^6.0.0: cliui@^8.0.1: version "8.0.1" - resolved "https://registry.npm.alibaba-inc.com/cliui/download/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + resolved "https://registry.npm.alibaba-inc.com/cliui/download/cliui-8.0.1.tgz" integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== dependencies: string-width "^4.2.0" @@ -3727,120 +4662,145 @@ cliui@^8.0.1: clone-regexp@^2.1.0: version "2.2.0" - resolved "https://registry.npm.alibaba-inc.com/clone-regexp/download/clone-regexp-2.2.0.tgz#7d65e00885cd8796405c35a737e7a86b7429e36f" + resolved "https://registry.npm.alibaba-inc.com/clone-regexp/download/clone-regexp-2.2.0.tgz" integrity sha1-fWXgCIXNh5ZAXDWnN+eoa3Qp428= dependencies: is-regexp "^2.0.0" co@^4.6.0: version "4.6.0" - resolved "https://registry.npm.alibaba-inc.com/co/download/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + resolved "https://registry.npm.alibaba-inc.com/co/download/co-4.6.0.tgz" integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= +coa@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz" + integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== + dependencies: + "@types/q" "^1.5.1" + chalk "^2.4.1" + q "^1.1.2" + collect-v8-coverage@^1.0.0: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/collect-v8-coverage/download/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" + resolved "https://registry.npm.alibaba-inc.com/collect-v8-coverage/download/collect-v8-coverage-1.0.1.tgz" integrity sha1-zCyOlPwYu9/+ZNZTRXDIpnOyf1k= collection-visit@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/collection-visit/download/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + resolved "https://registry.npm.alibaba-inc.com/collection-visit/download/collection-visit-1.0.0.tgz" integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= dependencies: map-visit "^1.0.0" object-visit "^1.0.0" -color-convert@^1.9.0: +color-convert@^1.9.0, color-convert@^1.9.3: version "1.9.3" - resolved "https://registry.npm.alibaba-inc.com/color-convert/download/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg= + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-convert@^2.0.1: version "2.0.1" - resolved "https://registry.npm.alibaba-inc.com/color-convert/download/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + resolved "https://registry.npm.alibaba-inc.com/color-convert/download/color-convert-2.0.1.tgz" integrity sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM= dependencies: color-name "~1.1.4" color-name@1.1.3: version "1.1.3" - resolved "https://registry.npm.alibaba-inc.com/color-name/download/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + resolved "https://registry.npm.alibaba-inc.com/color-name/download/color-name-1.1.3.tgz" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -color-name@~1.1.4: +color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" - resolved "https://registry.npm.alibaba-inc.com/color-name/download/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + resolved "https://registry.npm.alibaba-inc.com/color-name/download/color-name-1.1.4.tgz" integrity sha1-wqCah6y95pVD3m9j+jmVyCbFNqI= +color-string@^1.6.0: + version "1.9.1" + resolved "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^3.1.3: + version "3.2.1" + resolved "https://registry.npmjs.org/color/-/color-3.2.1.tgz" + integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA== + dependencies: + color-convert "^1.9.3" + color-string "^1.6.0" + colorette@^2.0.16: version "2.0.19" - resolved "https://registry.npm.alibaba-inc.com/colorette/download/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" + resolved "https://registry.npm.alibaba-inc.com/colorette/download/colorette-2.0.19.tgz" integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== combined-stream@^1.0.8: version "1.0.8" - resolved "https://registry.npm.alibaba-inc.com/combined-stream/download/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + resolved "https://registry.npm.alibaba-inc.com/combined-stream/download/combined-stream-1.0.8.tgz" integrity sha1-w9RaizT9cwYxoRCoolIGgrMdWn8= dependencies: delayed-stream "~1.0.0" commander@*: version "9.4.1" - resolved "https://registry.npm.alibaba-inc.com/commander/download/commander-9.4.1.tgz#d1dd8f2ce6faf93147295c0df13c7c21141cfbdd" + resolved "https://registry.npm.alibaba-inc.com/commander/download/commander-9.4.1.tgz" integrity sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw== commander@^2.20.0: version "2.20.3" - resolved "https://registry.npm.alibaba-inc.com/commander/download/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + resolved "https://registry.npm.alibaba-inc.com/commander/download/commander-2.20.3.tgz" integrity sha1-/UhehMA+tIgcIHIrpIA16FMa6zM= commander@^5.1.0: version "5.1.0" - resolved "https://registry.npm.alibaba-inc.com/commander/download/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" + resolved "https://registry.npm.alibaba-inc.com/commander/download/commander-5.1.0.tgz" integrity sha1-Rqu9FlL44Fm92u+Zu9yyrZzxea4= commander@^6.2.0: version "6.2.1" - resolved "https://registry.npm.alibaba-inc.com/commander/download/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" + resolved "https://registry.npm.alibaba-inc.com/commander/download/commander-6.2.1.tgz" integrity sha1-B5LraC37wyWZm7K4T93duhEKxzw= component-classes@^1.2.5: version "1.2.6" - resolved "https://registry.npm.alibaba-inc.com/component-classes/download/component-classes-1.2.6.tgz#c642394c3618a4d8b0b8919efccbbd930e5cd691" + resolved "https://registry.npm.alibaba-inc.com/component-classes/download/component-classes-1.2.6.tgz" integrity sha1-xkI5TDYYpNiwuJGe/Mu9kw5c1pE= dependencies: component-indexof "0.0.3" component-emitter@^1.2.1: version "1.3.0" - resolved "https://registry.npm.alibaba-inc.com/component-emitter/download/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + resolved "https://registry.npm.alibaba-inc.com/component-emitter/download/component-emitter-1.3.0.tgz" integrity sha1-FuQHD7qK4ptnnyIVhT7hgasuq8A= component-indexof@0.0.3: version "0.0.3" - resolved "https://registry.npm.alibaba-inc.com/component-indexof/download/component-indexof-0.0.3.tgz#11d091312239eb8f32c8f25ae9cb002ffe8d3c24" + resolved "https://registry.npm.alibaba-inc.com/component-indexof/download/component-indexof-0.0.3.tgz" integrity sha1-EdCRMSI5648yyPJa6csAL/6NPCQ= compute-scroll-into-view@^1.0.17: version "1.0.17" - resolved "https://registry.npm.alibaba-inc.com/compute-scroll-into-view/download/compute-scroll-into-view-1.0.17.tgz#6a88f18acd9d42e9cf4baa6bec7e0522607ab7ab" + resolved "https://registry.npm.alibaba-inc.com/compute-scroll-into-view/download/compute-scroll-into-view-1.0.17.tgz" integrity sha1-aojxis2dQunPS6pr7H4FImB6t6s= compute-scroll-into-view@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/compute-scroll-into-view/download/compute-scroll-into-view-3.0.0.tgz#95d2f2f4653e7edda74dd1e38edaaa897918e0f0" + resolved "https://registry.npm.alibaba-inc.com/compute-scroll-into-view/download/compute-scroll-into-view-3.0.0.tgz" integrity sha512-Yk1An4qzo5++Cu6peT9PsmRKIU8tALpmdoE09n//AfGQFcPfx21/tMGMsmKYmLJWaBJrGOJ5Jz5hoU+7cZZUWQ== concat-map@0.0.1: version "0.0.1" - resolved "https://registry.npm.alibaba-inc.com/concat-map/download/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved "https://registry.npm.alibaba-inc.com/concat-map/download/concat-map-0.0.1.tgz" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= connected-react-router@6.5.2: version "6.5.2" - resolved "https://registry.npm.alibaba-inc.com/connected-react-router/download/connected-react-router-6.5.2.tgz#422af70f86cb276681e20ab4295cf27dd9b6c7e3" + resolved "https://registry.npm.alibaba-inc.com/connected-react-router/download/connected-react-router-6.5.2.tgz" integrity sha1-Qir3D4bLJ2aB4gq0KVzyfdm2x+M= dependencies: immutable "^3.8.1" @@ -3849,71 +4809,71 @@ connected-react-router@6.5.2: console-browserify@^1.1.0: version "1.2.0" - resolved "https://registry.npm.alibaba-inc.com/console-browserify/download/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + resolved "https://registry.npm.alibaba-inc.com/console-browserify/download/console-browserify-1.2.0.tgz" integrity sha1-ZwY871fOts9Jk6KrOlWECujEkzY= constants-browserify@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/constants-browserify/download/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + resolved "https://registry.npm.alibaba-inc.com/constants-browserify/download/constants-browserify-1.0.0.tgz" integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.9.0" - resolved "https://registry.npm.alibaba-inc.com/convert-source-map/download/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + resolved "https://registry.npm.alibaba-inc.com/convert-source-map/download/convert-source-map-1.9.0.tgz" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== copy-descriptor@^0.1.0: version "0.1.1" - resolved "https://registry.npm.alibaba-inc.com/copy-descriptor/download/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + resolved "https://registry.npm.alibaba-inc.com/copy-descriptor/download/copy-descriptor-0.1.1.tgz" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= copy-to-clipboard@3.3.3, copy-to-clipboard@^3.2.0, copy-to-clipboard@^3.3.1: version "3.3.3" - resolved "https://registry.npm.alibaba-inc.com/copy-to-clipboard/download/copy-to-clipboard-3.3.3.tgz#55ac43a1db8ae639a4bd99511c148cdd1b83a1b0" + resolved "https://registry.npm.alibaba-inc.com/copy-to-clipboard/download/copy-to-clipboard-3.3.3.tgz" integrity sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA== dependencies: toggle-selection "^1.0.6" core-js-compat@^3.25.1: version "3.26.1" - resolved "https://registry.npm.alibaba-inc.com/core-js-compat/download/core-js-compat-3.26.1.tgz#0e710b09ebf689d719545ac36e49041850f943df" + resolved "https://registry.npm.alibaba-inc.com/core-js-compat/download/core-js-compat-3.26.1.tgz" integrity sha512-622/KzTudvXCDLRw70iHW4KKs1aGpcRcowGWyYJr2DEBfRrd6hNJybxSWJFuZYD4ma86xhrwDDHxmDaIq4EA8A== dependencies: browserslist "^4.21.4" core-js-pure@^3.8.1: version "3.26.1" - resolved "https://registry.npm.alibaba-inc.com/core-js-pure/download/core-js-pure-3.26.1.tgz#653f4d7130c427820dcecd3168b594e8bb095a33" + resolved "https://registry.npm.alibaba-inc.com/core-js-pure/download/core-js-pure-3.26.1.tgz" integrity sha512-VVXcDpp/xJ21KdULRq/lXdLzQAtX7+37LzpyfFM973il0tWSsDEoyzG38G14AjTpK9VTfiNM9jnFauq/CpaWGQ== core-js@3.6.5: version "3.6.5" - resolved "https://registry.npm.alibaba-inc.com/core-js/download/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" + resolved "https://registry.npm.alibaba-inc.com/core-js/download/core-js-3.6.5.tgz" integrity sha1-c5XcJzrzf7LlDpvT2f6EEoUjHRo= core-js@3.8.2: version "3.8.2" - resolved "https://registry.npm.alibaba-inc.com/core-js/download/core-js-3.8.2.tgz#0a1fd6709246da9ca8eff5bb0cbd15fba9ac7044" + resolved "https://registry.npm.alibaba-inc.com/core-js/download/core-js-3.8.2.tgz" integrity sha1-Ch/WcJJG2pyo7/W7DL0V+6mscEQ= core-js@^1.0.0: version "1.2.7" - resolved "https://registry.npm.alibaba-inc.com/core-js/download/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" + resolved "https://registry.npm.alibaba-inc.com/core-js/download/core-js-1.2.7.tgz" integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY= core-js@^2.4.0: version "2.6.12" - resolved "https://registry.npm.alibaba-inc.com/core-js/download/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" + resolved "https://registry.npm.alibaba-inc.com/core-js/download/core-js-2.6.12.tgz" integrity sha1-2TM9+nsGXjR8xWgiGdb2kIWcwuw= core-util-is@~1.0.0: version "1.0.3" - resolved "https://registry.npm.alibaba-inc.com/core-util-is/download/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + resolved "https://registry.npm.alibaba-inc.com/core-util-is/download/core-util-is-1.0.3.tgz" integrity sha1-pgQtNjTCsn6TKPg3uWX6yDgI24U= cosmiconfig@^5.0.0: version "5.2.1" - resolved "https://registry.npm.alibaba-inc.com/cosmiconfig/download/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + resolved "https://registry.npm.alibaba-inc.com/cosmiconfig/download/cosmiconfig-5.2.1.tgz" integrity sha1-BA9yaAnFked6F8CjYmykW08Wixo= dependencies: import-fresh "^2.0.0" @@ -3923,7 +4883,7 @@ cosmiconfig@^5.0.0: cosmiconfig@^7.0.0: version "7.1.0" - resolved "https://registry.npm.alibaba-inc.com/cosmiconfig/download/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" + resolved "https://registry.npm.alibaba-inc.com/cosmiconfig/download/cosmiconfig-7.1.0.tgz" integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== dependencies: "@types/parse-json" "^4.0.0" @@ -3932,9 +4892,34 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" +cp-file@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/cp-file/-/cp-file-7.0.0.tgz" + integrity sha512-0Cbj7gyvFVApzpK/uhCtQ/9kE9UnYpxMzaq5nQQC/Dh4iaj5fxp7iEFIullrYwzj8nf0qnsI1Qsx34hAeAebvw== + dependencies: + graceful-fs "^4.1.2" + make-dir "^3.0.0" + nested-error-stacks "^2.0.0" + p-event "^4.1.0" + +cpy@^8.1.2: + version "8.1.2" + resolved "https://registry.npmjs.org/cpy/-/cpy-8.1.2.tgz" + integrity sha512-dmC4mUesv0OYH2kNFEidtf/skUwv4zePmGeepjyyJ0qTo5+8KhA1o99oIAwVVLzQMAeDJml74d6wPPKb6EZUTg== + 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.0" + p-all "^2.1.0" + p-filter "^2.1.0" + p-map "^3.0.0" + create-ecdh@^4.0.0: version "4.0.4" - resolved "https://registry.npm.alibaba-inc.com/create-ecdh/download/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + resolved "https://registry.npm.alibaba-inc.com/create-ecdh/download/create-ecdh-4.0.4.tgz" integrity sha1-1uf0v/pmc2CFoHYv06YyaE2rzE4= dependencies: bn.js "^4.1.0" @@ -3942,7 +4927,7 @@ create-ecdh@^4.0.0: create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" - resolved "https://registry.npm.alibaba-inc.com/create-hash/download/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + resolved "https://registry.npm.alibaba-inc.com/create-hash/download/create-hash-1.2.0.tgz" integrity sha1-iJB4rxGmN1a8+1m9IhmWvjqe8ZY= dependencies: cipher-base "^1.0.1" @@ -3953,7 +4938,7 @@ create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: version "1.1.7" - resolved "https://registry.npm.alibaba-inc.com/create-hmac/download/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + resolved "https://registry.npm.alibaba-inc.com/create-hmac/download/create-hmac-1.1.7.tgz" integrity sha1-aRcMeLOrlXFHsriwRXLkfq0iQ/8= dependencies: cipher-base "^1.0.3" @@ -3963,24 +4948,31 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: safe-buffer "^5.0.1" sha.js "^2.4.8" -create-react-class@^15.6.0: +create-react-class@^15.5.3, create-react-class@^15.6.0: version "15.7.0" - resolved "https://registry.npm.alibaba-inc.com/create-react-class/download/create-react-class-15.7.0.tgz#7499d7ca2e69bb51d13faf59bd04f0c65a1d6c1e" - integrity sha1-dJnXyi5pu1HRP69ZvQTwxlodbB4= + resolved "https://registry.npmjs.org/create-react-class/-/create-react-class-15.7.0.tgz" + integrity sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng== dependencies: loose-envify "^1.3.1" object-assign "^4.1.1" cross-env@7.0.3: version "7.0.3" - resolved "https://registry.npm.alibaba-inc.com/cross-env/download/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + resolved "https://registry.npm.alibaba-inc.com/cross-env/download/cross-env-7.0.3.tgz" integrity sha1-hlJkspZ33AFbqEGJGJZd0jL8VM8= dependencies: cross-spawn "^7.0.1" +cross-fetch@^3.1.5: + version "3.1.8" + resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz" + integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== + dependencies: + node-fetch "^2.6.12" + cross-spawn@^5.0.1: version "5.1.0" - resolved "https://registry.npm.alibaba-inc.com/cross-spawn/download/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + resolved "https://registry.npm.alibaba-inc.com/cross-spawn/download/cross-spawn-5.1.0.tgz" integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= dependencies: lru-cache "^4.0.1" @@ -3989,7 +4981,7 @@ cross-spawn@^5.0.1: cross-spawn@^6.0.0: version "6.0.5" - resolved "https://registry.npm.alibaba-inc.com/cross-spawn/download/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + resolved "https://registry.npm.alibaba-inc.com/cross-spawn/download/cross-spawn-6.0.5.tgz" integrity sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q= dependencies: nice-try "^1.0.4" @@ -4000,7 +4992,7 @@ cross-spawn@^6.0.0: cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2: version "7.0.3" - resolved "https://registry.npm.alibaba-inc.com/cross-spawn/download/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + resolved "https://registry.npm.alibaba-inc.com/cross-spawn/download/cross-spawn-7.0.3.tgz" integrity sha1-9zqFudXUHQRVUcF34ogtSshXKKY= dependencies: path-key "^3.1.0" @@ -4009,7 +5001,7 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2: crypto-browserify@^3.11.0: version "3.12.0" - resolved "https://registry.npm.alibaba-inc.com/crypto-browserify/download/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + resolved "https://registry.npm.alibaba-inc.com/crypto-browserify/download/crypto-browserify-3.12.0.tgz" integrity sha1-OWz58xN/A+S45TLFj2mCVOAPgOw= dependencies: browserify-cipher "^1.0.0" @@ -4026,7 +5018,7 @@ crypto-browserify@^3.11.0: css-animation@1.x, css-animation@^1.3.2: version "1.6.1" - resolved "https://registry.npm.alibaba-inc.com/css-animation/download/css-animation-1.6.1.tgz#162064a3b0d51f958b7ff37b3d6d4de18e17039e" + resolved "https://registry.npm.alibaba-inc.com/css-animation/download/css-animation-1.6.1.tgz" integrity sha1-FiBko7DVH5WLf/N7PW1N4Y4XA54= dependencies: babel-runtime "6.x" @@ -4034,14 +5026,14 @@ css-animation@1.x, css-animation@^1.3.2: css-blank-pseudo@^0.1.4: version "0.1.4" - resolved "https://registry.npm.alibaba-inc.com/css-blank-pseudo/download/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5" + resolved "https://registry.npm.alibaba-inc.com/css-blank-pseudo/download/css-blank-pseudo-0.1.4.tgz" integrity sha1-3979MlS/ioICeZNnTM81SDv8s8U= dependencies: postcss "^7.0.5" css-has-pseudo@^0.10.0: version "0.10.0" - resolved "https://registry.npm.alibaba-inc.com/css-has-pseudo/download/css-has-pseudo-0.10.0.tgz#3c642ab34ca242c59c41a125df9105841f6966ee" + resolved "https://registry.npm.alibaba-inc.com/css-has-pseudo/download/css-has-pseudo-0.10.0.tgz" integrity sha1-PGQqs0yiQsWcQaEl35EFhB9pZu4= dependencies: postcss "^7.0.6" @@ -4049,64 +5041,161 @@ css-has-pseudo@^0.10.0: css-mediaquery@^0.1.2: version "0.1.2" - resolved "https://registry.npm.alibaba-inc.com/css-mediaquery/download/css-mediaquery-0.1.2.tgz#6a2c37344928618631c54bd33cedd301da18bea0" + resolved "https://registry.npm.alibaba-inc.com/css-mediaquery/download/css-mediaquery-0.1.2.tgz" integrity sha1-aiw3NEkoYYYxxUvTPO3TAdoYvqA= css-prefers-color-scheme@^3.1.1: version "3.1.1" - resolved "https://registry.npm.alibaba-inc.com/css-prefers-color-scheme/download/css-prefers-color-scheme-3.1.1.tgz#6f830a2714199d4f0d0d0bb8a27916ed65cff1f4" + resolved "https://registry.npm.alibaba-inc.com/css-prefers-color-scheme/download/css-prefers-color-scheme-3.1.1.tgz" integrity sha1-b4MKJxQZnU8NDQu4onkW7WXP8fQ= dependencies: postcss "^7.0.5" +css-select-base-adapter@^0.1.1: + version "0.1.1" + resolved "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz" + integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== + +css-select@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz" + integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== + dependencies: + boolbase "^1.0.0" + css-what "^3.2.1" + domutils "^1.7.0" + nth-check "^1.0.2" + +css-tree@1.0.0-alpha.37: + version "1.0.0-alpha.37" + resolved "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz" + integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== + dependencies: + mdn-data "2.0.4" + source-map "^0.6.1" + +css-tree@^1.1.2: + version "1.1.3" + resolved "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz" + integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== + dependencies: + mdn-data "2.0.14" + source-map "^0.6.1" + +css-what@^3.2.1: + version "3.4.2" + resolved "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz" + integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ== + cssdb@^4.4.0: version "4.4.0" - resolved "https://registry.npm.alibaba-inc.com/cssdb/download/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0" + resolved "https://registry.npm.alibaba-inc.com/cssdb/download/cssdb-4.4.0.tgz" integrity sha1-O/LypowQ9cagir2SN4Mx7oA83bA= cssesc@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/cssesc/download/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" + resolved "https://registry.npm.alibaba-inc.com/cssesc/download/cssesc-2.0.0.tgz" integrity sha1-OxO9G7HLNuG8taTc0n9UxdyzVwM= cssesc@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/cssesc/download/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + resolved "https://registry.npm.alibaba-inc.com/cssesc/download/cssesc-3.0.0.tgz" integrity sha1-N3QZGZA7hoVl4cCep0dEXNGJg+4= +csso@^4.0.2: + version "4.2.0" + resolved "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz" + integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== + dependencies: + css-tree "^1.1.2" + cssom@^0.4.4: version "0.4.4" - resolved "https://registry.npm.alibaba-inc.com/cssom/download/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" + resolved "https://registry.npm.alibaba-inc.com/cssom/download/cssom-0.4.4.tgz" integrity sha1-WmbPk9LQtmHYC/akT7ZfXC5OChA= cssom@~0.3.6: version "0.3.8" - resolved "https://registry.npm.alibaba-inc.com/cssom/download/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + resolved "https://registry.npm.alibaba-inc.com/cssom/download/cssom-0.3.8.tgz" integrity sha1-nxJ29bK0Y/IRTT8sdSUK+MGjb0o= cssstyle@^2.3.0: version "2.3.0" - resolved "https://registry.npm.alibaba-inc.com/cssstyle/download/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + resolved "https://registry.npm.alibaba-inc.com/cssstyle/download/cssstyle-2.3.0.tgz" integrity sha1-/2ZaDdvcMYZLCWR/NBY0Q9kLCFI= dependencies: cssom "~0.3.6" -csstype@^3.0.10, csstype@^3.0.2: +csstype@^3.0.10, csstype@^3.0.2, csstype@^3.0.8: version "3.1.1" - resolved "https://registry.npm.alibaba-inc.com/csstype/download/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" + resolved "https://registry.npm.alibaba-inc.com/csstype/download/csstype-3.1.1.tgz" integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== +"d3-color@1 - 3": + version "3.1.0" + resolved "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz" + integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== + +"d3-dispatch@1 - 2": + version "2.0.0" + resolved "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz" + integrity sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA== + +d3-ease@^1.0.5: + version "1.0.7" + resolved "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz" + integrity sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ== + +d3-force@^2.0.1, d3-force@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/d3-force/-/d3-force-2.1.1.tgz" + integrity sha512-nAuHEzBqMvpFVMf9OX75d00OxvOXdxY+xECIXjW6Gv8BRrXu6gAWbv/9XKrvfJ5i5DCokDW7RYE50LRoK092ew== + dependencies: + d3-dispatch "1 - 2" + d3-quadtree "1 - 2" + d3-timer "1 - 2" + +d3-interpolate@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz" + integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== + dependencies: + d3-color "1 - 3" + +"d3-quadtree@1 - 2", d3-quadtree@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-2.0.0.tgz" + integrity sha512-b0Ed2t1UUalJpc3qXzKi+cPGxeXRr4KU9YSlocN74aTzp6R/Ud43t79yLLqxHRWZfsvWXmbDWPpoENK1K539xw== + +"d3-timer@1 - 2", d3-timer@^1.0.9: + version "1.0.10" + resolved "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz" + integrity sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw== + d@1, d@^1.0.1: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/d/download/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + resolved "https://registry.npm.alibaba-inc.com/d/download/d-1.0.1.tgz" integrity sha1-hpgJU3LVjb7jRv/Qxwk/mfj561o= dependencies: es5-ext "^0.10.50" type "^1.0.1" +dagre-compound@^0.0.11: + version "0.0.11" + resolved "https://registry.npmjs.org/dagre-compound/-/dagre-compound-0.0.11.tgz" + integrity sha512-UrSgRP9LtOZCYb9e5doolZXpc7xayyszgyOs7uakTK4n4KsLegLVTRRtq01GpQd/iZjYw5fWMapx9ed+c80MAQ== + +dagre@^0.8.5: + version "0.8.5" + resolved "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz" + integrity sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw== + dependencies: + graphlib "^2.1.8" + lodash "^4.17.15" + data-urls@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/data-urls/download/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" + resolved "https://registry.npm.alibaba-inc.com/data-urls/download/data-urls-2.0.0.tgz" integrity sha1-FWSFpyljqXD11YIar2Qr7yvy25s= dependencies: abab "^2.0.3" @@ -4115,31 +5204,36 @@ data-urls@^2.0.0: date-fns@2.x: version "2.29.3" - resolved "https://registry.npm.alibaba-inc.com/date-fns/download/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8" + resolved "https://registry.npm.alibaba-inc.com/date-fns/download/date-fns-2.29.3.tgz" integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA== dayjs@1.x, dayjs@^1.10.3, dayjs@^1.11.1, dayjs@^1.11.4: version "1.11.6" - resolved "https://registry.npm.alibaba-inc.com/dayjs/download/dayjs-1.11.6.tgz#2e79a226314ec3ec904e3ee1dd5a4f5e5b1c7afb" + resolved "https://registry.npm.alibaba-inc.com/dayjs/download/dayjs-1.11.6.tgz" integrity sha512-zZbY5giJAinCG+7AGaw0wIhNZ6J8AhWuSXKvuc1KAyMiRsvGQWqh4L+MomvhdAYjN+lqvVCMq1I41e3YHvXkyQ== +dayjs@^1.11.9, dayjs@^1.9.1: + version "1.11.9" + resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz" + integrity sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA== + debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" - resolved "https://registry.npm.alibaba-inc.com/debug/download/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + resolved "https://registry.npm.alibaba-inc.com/debug/download/debug-2.6.9.tgz" integrity sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8= dependencies: ms "2.0.0" debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.4: version "4.3.4" - resolved "https://registry.npm.alibaba-inc.com/debug/download/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + resolved "https://registry.npm.alibaba-inc.com/debug/download/debug-4.3.4.tgz" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" decamelize-keys@^1.1.0: version "1.1.1" - resolved "https://registry.npm.alibaba-inc.com/decamelize-keys/download/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" + resolved "https://registry.npm.alibaba-inc.com/decamelize-keys/download/decamelize-keys-1.1.1.tgz" integrity sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg== dependencies: decamelize "^1.1.0" @@ -4147,64 +5241,87 @@ decamelize-keys@^1.1.0: decamelize@^1.1.0, decamelize@^1.2.0: version "1.2.0" - resolved "https://registry.npm.alibaba-inc.com/decamelize/download/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + resolved "https://registry.npm.alibaba-inc.com/decamelize/download/decamelize-1.2.0.tgz" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= decimal.js@^10.2.1: version "10.4.2" - resolved "https://registry.npm.alibaba-inc.com/decimal.js/download/decimal.js-10.4.2.tgz#0341651d1d997d86065a2ce3a441fbd0d8e8b98e" + resolved "https://registry.npm.alibaba-inc.com/decimal.js/download/decimal.js-10.4.2.tgz" integrity sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA== -decode-uri-component@^0.2.0, decode-uri-component@^0.2.2: +decode-uri-component@^0.2.0: version "0.2.2" - resolved "https://registry.npm.alibaba-inc.com/decode-uri-component/download/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + resolved "https://registry.npm.alibaba-inc.com/decode-uri-component/download/decode-uri-component-0.2.2.tgz" integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== +decode-uri-component@^0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.4.1.tgz" + integrity sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ== + dedent@^0.7.0: version "0.7.0" - resolved "https://registry.npm.alibaba-inc.com/dedent/download/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + resolved "https://registry.npm.alibaba-inc.com/dedent/download/dedent-0.7.0.tgz" integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.4" - resolved "https://registry.npm.alibaba-inc.com/deep-is/download/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + resolved "https://registry.npm.alibaba-inc.com/deep-is/download/deep-is-0.1.4.tgz" integrity sha1-pvLc5hL63S7x9Rm3NVHxfoUZmDE= deepmerge@^1.5.2: version "1.5.2" - resolved "https://registry.npm.alibaba-inc.com/deepmerge/download/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753" + resolved "https://registry.npm.alibaba-inc.com/deepmerge/download/deepmerge-1.5.2.tgz" integrity sha1-EEmdhohEza1P7ghC34x/bwyVp1M= deepmerge@^4.2.2: version "4.2.2" - resolved "https://registry.npm.alibaba-inc.com/deepmerge/download/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + resolved "https://registry.npm.alibaba-inc.com/deepmerge/download/deepmerge-4.2.2.tgz" integrity sha1-RNLqNnm49NT/ujPwPYZfwee/SVU= +define-data-property@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/define-data-property/-/define-data-property-1.0.1.tgz" + integrity sha512-22M+6zEspQHx10bfFQl2ET39IvfuQ7+rZIH7+ard8fCC4hPmkOSy+8JhKxBRLaWUziJ0O63NTYT97LR8zUfPTw== + dependencies: + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + define-properties@^1.1.3, define-properties@^1.1.4: version "1.1.4" - resolved "https://registry.npm.alibaba-inc.com/define-properties/download/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + resolved "https://registry.npm.alibaba-inc.com/define-properties/download/define-properties-1.1.4.tgz" integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== dependencies: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +define-properties@^1.2.0: + version "1.2.1" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + define-property@^0.2.5: version "0.2.5" - resolved "https://registry.npm.alibaba-inc.com/define-property/download/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + resolved "https://registry.npm.alibaba-inc.com/define-property/download/define-property-0.2.5.tgz" integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/define-property/download/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + resolved "https://registry.npm.alibaba-inc.com/define-property/download/define-property-1.0.0.tgz" integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" - resolved "https://registry.npm.alibaba-inc.com/define-property/download/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + resolved "https://registry.npm.alibaba-inc.com/define-property/download/define-property-2.0.2.tgz" integrity sha1-1Flono1lS6d+AqgX+HENcCyxbp0= dependencies: is-descriptor "^1.0.2" @@ -4212,17 +5329,17 @@ define-property@^2.0.2: delayed-stream@~1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/delayed-stream/download/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + resolved "https://registry.npm.alibaba-inc.com/delayed-stream/download/delayed-stream-1.0.0.tgz" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= depd@2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/depd/download/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + resolved "https://registry.npm.alibaba-inc.com/depd/download/depd-2.0.0.tgz" integrity sha1-tpYWPMdXVg0JzyLMj60Vcbeedt8= des.js@^1.0.0: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/des.js/download/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + resolved "https://registry.npm.alibaba-inc.com/des.js/download/des.js-1.0.1.tgz" integrity sha1-U4IULhvcU/hdhtU+X0qn3rkeCEM= dependencies: inherits "^2.0.1" @@ -4230,62 +5347,84 @@ des.js@^1.0.0: destroy@1.2.0: version "1.2.0" - resolved "https://registry.npm.alibaba-inc.com/destroy/download/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + resolved "https://registry.npm.alibaba-inc.com/destroy/download/destroy-1.2.0.tgz" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== +detect-browser@^5.0.0, detect-browser@^5.1.0: + version "5.3.0" + resolved "https://registry.npmjs.org/detect-browser/-/detect-browser-5.3.0.tgz" + integrity sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w== + detect-indent@^6.0.0: version "6.1.0" - resolved "https://registry.npm.alibaba-inc.com/detect-indent/download/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" + resolved "https://registry.npm.alibaba-inc.com/detect-indent/download/detect-indent-6.1.0.tgz" integrity sha1-WSSF67v2s7GrK+F1yDk9BMoNV+Y= detect-newline@3.1.0, detect-newline@^3.0.0: version "3.1.0" - resolved "https://registry.npm.alibaba-inc.com/detect-newline/download/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + resolved "https://registry.npm.alibaba-inc.com/detect-newline/download/detect-newline-3.1.0.tgz" integrity sha1-V29d/GOuGhkv8ZLYrTr2MImRtlE= diff-sequences@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/diff-sequences/download/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" + resolved "https://registry.npm.alibaba-inc.com/diff-sequences/download/diff-sequences-26.6.2.tgz" integrity sha1-SLqZFX3hkjQS7tQdtrbUqpynwLE= +diff@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz" + integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== + diffie-hellman@^5.0.0: version "5.0.3" - resolved "https://registry.npm.alibaba-inc.com/diffie-hellman/download/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + resolved "https://registry.npm.alibaba-inc.com/diffie-hellman/download/diffie-hellman-5.0.3.tgz" integrity sha1-QOjumPVaIUlgcUaSHGPhrl89KHU= dependencies: bn.js "^4.1.0" miller-rabin "^4.0.0" randombytes "^2.0.0" +dir-glob@^2.2.2: + version "2.2.2" + resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz" + integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw== + dependencies: + path-type "^3.0.0" + dir-glob@^3.0.1: version "3.0.1" - resolved "https://registry.npm.alibaba-inc.com/dir-glob/download/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + resolved "https://registry.npm.alibaba-inc.com/dir-glob/download/dir-glob-3.0.1.tgz" integrity sha1-Vtv3PZkqSpO6FYT0U0Bj/S5BcX8= dependencies: path-type "^4.0.0" doctrine@^2.1.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/doctrine/download/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + resolved "https://registry.npm.alibaba-inc.com/doctrine/download/doctrine-2.1.0.tgz" integrity sha1-XNAfwQFiG0LEzX9dGmYkNxbT850= dependencies: esutils "^2.0.2" doctrine@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/doctrine/download/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + resolved "https://registry.npm.alibaba-inc.com/doctrine/download/doctrine-3.0.0.tgz" integrity sha1-rd6+rXKmV023g2OdyHoSF3OXOWE= dependencies: esutils "^2.0.2" dom-align@1.x, dom-align@^1.7.0: version "1.12.4" - resolved "https://registry.npm.alibaba-inc.com/dom-align/download/dom-align-1.12.4.tgz#3503992eb2a7cfcb2ed3b2a6d21e0b9c00d54511" + resolved "https://registry.npm.alibaba-inc.com/dom-align/download/dom-align-1.12.4.tgz" integrity sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw== +dom-scroll-into-view@1.x, dom-scroll-into-view@^1.2.0: + version "1.2.1" + resolved "https://registry.npmjs.org/dom-scroll-into-view/-/dom-scroll-into-view-1.2.1.tgz" + integrity sha512-LwNVg3GJOprWDO+QhLL1Z9MMgWe/KAFLxVWKzjRTxNSPn8/LLDIfmuG71YHznXCqaqTjvHJDYO1MEAgX6XCNbQ== + dom-serializer@0: version "0.2.2" - resolved "https://registry.npm.alibaba-inc.com/dom-serializer/download/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" + resolved "https://registry.npm.alibaba-inc.com/dom-serializer/download/dom-serializer-0.2.2.tgz" integrity sha1-GvuB9TNxcXXUeGVd68XjMtn5u1E= dependencies: domelementtype "^2.0.1" @@ -4293,54 +5432,63 @@ dom-serializer@0: dom-walk@^0.1.0: version "0.1.2" - resolved "https://registry.npm.alibaba-inc.com/dom-walk/download/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" + resolved "https://registry.npm.alibaba-inc.com/dom-walk/download/dom-walk-0.1.2.tgz" integrity sha1-DFSL7wSPTR8qlySQAiNgYNqj/YQ= domain-browser@^1.1.1: version "1.2.0" - resolved "https://registry.npm.alibaba-inc.com/domain-browser/download/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + resolved "https://registry.npm.alibaba-inc.com/domain-browser/download/domain-browser-1.2.0.tgz" integrity sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto= domelementtype@1, domelementtype@^1.3.1: version "1.3.1" - resolved "https://registry.npm.alibaba-inc.com/domelementtype/download/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + resolved "https://registry.npm.alibaba-inc.com/domelementtype/download/domelementtype-1.3.1.tgz" integrity sha1-0EjESzew0Qp/Kj1f7j9DM9eQSB8= domelementtype@^2.0.1: version "2.3.0" - resolved "https://registry.npm.alibaba-inc.com/domelementtype/download/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + resolved "https://registry.npm.alibaba-inc.com/domelementtype/download/domelementtype-2.3.0.tgz" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== domexception@^2.0.1: version "2.0.1" - resolved "https://registry.npm.alibaba-inc.com/domexception/download/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" + resolved "https://registry.npm.alibaba-inc.com/domexception/download/domexception-2.0.1.tgz" integrity sha1-+0Su+6eT4VdLCvau0oAdBXUp8wQ= dependencies: webidl-conversions "^5.0.0" domhandler@^2.3.0: version "2.4.2" - resolved "https://registry.npm.alibaba-inc.com/domhandler/download/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" + resolved "https://registry.npm.alibaba-inc.com/domhandler/download/domhandler-2.4.2.tgz" integrity sha1-iAUJfpM9ZehVRvcm1g9euItE+AM= dependencies: domelementtype "1" -domutils@^1.5.1: +domutils@^1.5.1, domutils@^1.7.0: version "1.7.0" - resolved "https://registry.npm.alibaba-inc.com/domutils/download/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + resolved "https://registry.npm.alibaba-inc.com/domutils/download/domutils-1.7.0.tgz" integrity sha1-Vuo0HoNOBuZ0ivehyyXaZ+qfjCo= dependencies: dom-serializer "0" domelementtype "1" +draft-js@^0.10.0, draft-js@~0.10.0: + version "0.10.5" + resolved "https://registry.npmjs.org/draft-js/-/draft-js-0.10.5.tgz" + integrity sha512-LE6jSCV9nkPhfVX2ggcRLA4FKs6zWq9ceuO/88BpXdNCS7mjRTgs0NsV6piUCJX9YxMsB9An33wnkMmU2sD2Zg== + dependencies: + fbjs "^0.8.15" + immutable "~3.7.4" + object-assign "^4.1.0" + drange@^1.0.2: version "1.1.1" - resolved "https://registry.npm.alibaba-inc.com/drange/download/drange-1.1.1.tgz#b2aecec2aab82fcef11dbbd7b9e32b83f8f6c0b8" + resolved "https://registry.npm.alibaba-inc.com/drange/download/drange-1.1.1.tgz" integrity sha1-sq7Owqq4L87xHbvXueMrg/j2wLg= dva-core@2.0.4: version "2.0.4" - resolved "https://registry.npm.alibaba-inc.com/dva-core/download/dva-core-2.0.4.tgz#086665d1d5f684e089c5bfac9ba388d91cc9050a" + resolved "https://registry.npm.alibaba-inc.com/dva-core/download/dva-core-2.0.4.tgz" integrity sha1-CGZl0dX2hOCJxb+sm6OI2RzJBQo= dependencies: "@babel/runtime" "^7.0.0" @@ -4353,7 +5501,7 @@ dva-core@2.0.4: dva-immer@^0.5.2: version "0.5.2" - resolved "https://registry.npm.alibaba-inc.com/dva-immer/download/dva-immer-0.5.2.tgz#128bd6d96b25f11e6f137807b614b9c58cf03f32" + resolved "https://registry.npm.alibaba-inc.com/dva-immer/download/dva-immer-0.5.2.tgz" integrity sha1-EovW2Wsl8R5vE3gHthS5xYzwPzI= dependencies: "@babel/runtime" "^7.0.0" @@ -4361,14 +5509,14 @@ dva-immer@^0.5.2: dva-loading@^3.0.20: version "3.0.22" - resolved "https://registry.npm.alibaba-inc.com/dva-loading/download/dva-loading-3.0.22.tgz#c0dd2fb081492752b992d9ce2701b88825186e02" + resolved "https://registry.npm.alibaba-inc.com/dva-loading/download/dva-loading-3.0.22.tgz" integrity sha1-wN0vsIFJJ1K5ktnOJwG4iCUYbgI= dependencies: "@babel/runtime" "^7.0.0" dva@^2.6.0-beta.20: version "2.6.0-beta.22" - resolved "https://registry.npm.alibaba-inc.com/dva/download/dva-2.6.0-beta.22.tgz#3288993ecea70ee9c507d4aa9e0ed8247d4af69c" + resolved "https://registry.npm.alibaba-inc.com/dva/download/dva-2.6.0-beta.22.tgz" integrity sha1-MoiZPs6nDunFB9Sqng7YJH1K9pw= dependencies: "@babel/runtime" "^7.0.0" @@ -4387,17 +5535,17 @@ dva@^2.6.0-beta.20: ee-first@1.1.1: version "1.1.1" - resolved "https://registry.npm.alibaba-inc.com/ee-first/download/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + resolved "https://registry.npm.alibaba-inc.com/ee-first/download/ee-first-1.1.1.tgz" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.4.251: version "1.4.284" - resolved "https://registry.npm.alibaba-inc.com/electron-to-chromium/download/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" + resolved "https://registry.npm.alibaba-inc.com/electron-to-chromium/download/electron-to-chromium-1.4.284.tgz" integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== elliptic@^6.5.3: version "6.5.4" - resolved "https://registry.npm.alibaba-inc.com/elliptic/download/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + resolved "https://registry.npm.alibaba-inc.com/elliptic/download/elliptic-6.5.4.tgz" integrity sha1-2jfOvTHnmhNn6UG1ku0fvr1Yq7s= dependencies: bn.js "^4.11.9" @@ -4410,72 +5558,122 @@ elliptic@^6.5.3: emittery@^0.7.1: version "0.7.2" - resolved "https://registry.npm.alibaba-inc.com/emittery/download/emittery-0.7.2.tgz#25595908e13af0f5674ab419396e2fb394cdfa82" + resolved "https://registry.npm.alibaba-inc.com/emittery/download/emittery-0.7.2.tgz" integrity sha1-JVlZCOE68PVnSrQZOW4vs5TN+oI= emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.npm.alibaba-inc.com/emoji-regex/download/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + resolved "https://registry.npm.alibaba-inc.com/emoji-regex/download/emoji-regex-8.0.0.tgz" integrity sha1-6Bj9ac5cz8tARZT4QpY79TFkzDc= emojis-list@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/emojis-list/download/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + resolved "https://registry.npm.alibaba-inc.com/emojis-list/download/emojis-list-3.0.0.tgz" integrity sha1-VXBmIEatKeLpFucariYKvf9Pang= encodeurl@~1.0.2: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/encodeurl/download/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + resolved "https://registry.npm.alibaba-inc.com/encodeurl/download/encodeurl-1.0.2.tgz" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= encoding@^0.1.11: version "0.1.13" - resolved "https://registry.npm.alibaba-inc.com/encoding/download/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + resolved "https://registry.npm.alibaba-inc.com/encoding/download/encoding-0.1.13.tgz" integrity sha1-VldK/deR9UqOmyeFwFgqLSYhD6k= dependencies: iconv-lite "^0.6.2" end-of-stream@^1.1.0: version "1.4.4" - resolved "https://registry.npm.alibaba-inc.com/end-of-stream/download/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + resolved "https://registry.npm.alibaba-inc.com/end-of-stream/download/end-of-stream-1.4.4.tgz" integrity sha1-WuZKX0UFe682JuwU2gyl5LJDHrA= dependencies: once "^1.4.0" enquirer@^2.3.5, enquirer@^2.3.6: version "2.3.6" - resolved "https://registry.npm.alibaba-inc.com/enquirer/download/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + resolved "https://registry.npm.alibaba-inc.com/enquirer/download/enquirer-2.3.6.tgz" integrity sha1-Kn/l3WNKHkElqXXsmU/1RW3Dc00= dependencies: ansi-colors "^4.1.1" entities@^1.1.1: version "1.1.2" - resolved "https://registry.npm.alibaba-inc.com/entities/download/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + resolved "https://registry.npm.alibaba-inc.com/entities/download/entities-1.1.2.tgz" integrity sha1-vfpzUplmTfr9NFKe1PhSKidf6lY= entities@^2.0.0: version "2.2.0" - resolved "https://registry.npm.alibaba-inc.com/entities/download/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + resolved "https://registry.npm.alibaba-inc.com/entities/download/entities-2.2.0.tgz" integrity sha1-CY3JDruD2N/6CJ1VJWs1HTTE2lU= +entities@^4.4.0: + version "4.5.0" + resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + error-ex@^1.3.1: version "1.3.2" - resolved "https://registry.npm.alibaba-inc.com/error-ex/download/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + resolved "https://registry.npm.alibaba-inc.com/error-ex/download/error-ex-1.3.2.tgz" integrity sha1-tKxAZIEH/c3PriQvQovqihTU8b8= dependencies: is-arrayish "^0.2.1" error-stack-parser@^2.0.6: version "2.1.4" - resolved "https://registry.npm.alibaba-inc.com/error-stack-parser/download/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286" + resolved "https://registry.npm.alibaba-inc.com/error-stack-parser/download/error-stack-parser-2.1.4.tgz" integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ== dependencies: stackframe "^1.3.4" +es-abstract@^1.17.2, es-abstract@^1.22.1: + version "1.22.1" + resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz" + integrity sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw== + dependencies: + array-buffer-byte-length "^1.0.0" + arraybuffer.prototype.slice "^1.0.1" + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.2.1" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.10" + is-weakref "^1.0.2" + object-inspect "^1.12.3" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.5.0" + safe-array-concat "^1.0.0" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.7" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-buffer "^1.0.0" + typed-array-byte-length "^1.0.0" + typed-array-byte-offset "^1.0.0" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.10" + es-abstract@^1.19.0, es-abstract@^1.20.4: version "1.20.4" - resolved "https://registry.npm.alibaba-inc.com/es-abstract/download/es-abstract-1.20.4.tgz#1d103f9f8d78d4cf0713edcd6d0ed1a46eed5861" + resolved "https://registry.npm.alibaba-inc.com/es-abstract/download/es-abstract-1.20.4.tgz" integrity sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA== dependencies: call-bind "^1.0.2" @@ -4503,21 +5701,35 @@ es-abstract@^1.19.0, es-abstract@^1.20.4: string.prototype.trimstart "^1.0.5" unbox-primitive "^1.0.2" +es-array-method-boxes-properly@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz" + integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== + es-module-lexer@0.7.1: version "0.7.1" - resolved "https://registry.npm.alibaba-inc.com/es-module-lexer/download/es-module-lexer-0.7.1.tgz#c2c8e0f46f2df06274cdaf0dd3f3b33e0a0b267d" + resolved "https://registry.npm.alibaba-inc.com/es-module-lexer/download/es-module-lexer-0.7.1.tgz" integrity sha1-wsjg9G8t8GJ0za8N0/OzPgoLJn0= +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + es-shim-unscopables@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/es-shim-unscopables/download/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" + resolved "https://registry.npm.alibaba-inc.com/es-shim-unscopables/download/es-shim-unscopables-1.0.0.tgz" integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== dependencies: has "^1.0.3" es-to-primitive@^1.2.1: version "1.2.1" - resolved "https://registry.npm.alibaba-inc.com/es-to-primitive/download/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + resolved "https://registry.npm.alibaba-inc.com/es-to-primitive/download/es-to-primitive-1.2.1.tgz" integrity sha1-5VzUyc3BiLzvsDs2bHNjI/xciYo= dependencies: is-callable "^1.1.4" @@ -4526,7 +5738,7 @@ es-to-primitive@^1.2.1: es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: version "0.10.62" - resolved "https://registry.npm.alibaba-inc.com/es5-ext/download/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5" + resolved "https://registry.npm.alibaba-inc.com/es5-ext/download/es5-ext-0.10.62.tgz" integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA== dependencies: es6-iterator "^2.0.3" @@ -4535,12 +5747,12 @@ es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@ es5-imcompatible-versions@^0.1.62: version "0.1.77" - resolved "https://registry.npm.alibaba-inc.com/es5-imcompatible-versions/download/es5-imcompatible-versions-0.1.77.tgz#7c7cc6e35ff4daf3a2bbeb629426e929f0d59f17" + resolved "https://registry.npm.alibaba-inc.com/es5-imcompatible-versions/download/es5-imcompatible-versions-0.1.77.tgz" integrity sha512-PYCZ6CvLzvVOPK4Lgja32PhWUoEJkQ1mWep0xuGtvVzmRAHq2xWHUuQ+jUXsIIAHo6c3Kh+n0z4rKCgBd4CrXA== es6-iterator@^2.0.3: version "2.0.3" - resolved "https://registry.npm.alibaba-inc.com/es6-iterator/download/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + resolved "https://registry.npm.alibaba-inc.com/es6-iterator/download/es6-iterator-2.0.3.tgz" integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= dependencies: d "1" @@ -4549,12 +5761,12 @@ es6-iterator@^2.0.3: es6-promise@^3.2.1: version "3.3.1" - resolved "https://registry.npm.alibaba-inc.com/es6-promise/download/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613" + resolved "https://registry.npm.alibaba-inc.com/es6-promise/download/es6-promise-3.3.1.tgz" integrity sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM= es6-symbol@^3.1.1, es6-symbol@^3.1.3: version "3.1.3" - resolved "https://registry.npm.alibaba-inc.com/es6-symbol/download/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + resolved "https://registry.npm.alibaba-inc.com/es6-symbol/download/es6-symbol-3.1.3.tgz" integrity sha1-utXTwbzawoJp9MszHkMceKxwXRg= dependencies: d "^1.0.1" @@ -4562,7 +5774,7 @@ es6-symbol@^3.1.1, es6-symbol@^3.1.3: es6-weak-map@^2.0.3: version "2.0.3" - resolved "https://registry.npm.alibaba-inc.com/es6-weak-map/download/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" + resolved "https://registry.npm.alibaba-inc.com/es6-weak-map/download/es6-weak-map-2.0.3.tgz" integrity sha1-ttofFswswNm+Q+a9v8Xn383zHVM= dependencies: d "1" @@ -4572,37 +5784,37 @@ es6-weak-map@^2.0.3: esbuild@0.12.15: version "0.12.15" - resolved "https://registry.npm.alibaba-inc.com/esbuild/download/esbuild-0.12.15.tgz#9d99cf39aeb2188265c5983e983e236829f08af0" + resolved "https://registry.npm.alibaba-inc.com/esbuild/download/esbuild-0.12.15.tgz" integrity sha1-nZnPOa6yGIJlxZg+mD4jaCnwivA= escalade@^3.1.1: version "3.1.1" - resolved "https://registry.npm.alibaba-inc.com/escalade/download/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + resolved "https://registry.npm.alibaba-inc.com/escalade/download/escalade-3.1.1.tgz" integrity sha1-2M/ccACWXFoBdLSoLqpcBVJ0LkA= escape-html@~1.0.3: version "1.0.3" - resolved "https://registry.npm.alibaba-inc.com/escape-html/download/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + resolved "https://registry.npm.alibaba-inc.com/escape-html/download/escape-html-1.0.3.tgz" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.npm.alibaba-inc.com/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + resolved "https://registry.npm.alibaba-inc.com/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= escape-string-regexp@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/escape-string-regexp/download/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + resolved "https://registry.npm.alibaba-inc.com/escape-string-regexp/download/escape-string-regexp-2.0.0.tgz" integrity sha1-owME6Z2qMuI7L9IPUbq9B8/8o0Q= escape-string-regexp@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/escape-string-regexp/download/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + resolved "https://registry.npm.alibaba-inc.com/escape-string-regexp/download/escape-string-regexp-4.0.0.tgz" integrity sha1-FLqDpdNz49MR5a/KKc9b+tllvzQ= escodegen@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/escodegen/download/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" + resolved "https://registry.npm.alibaba-inc.com/escodegen/download/escodegen-2.0.0.tgz" integrity sha1-XjKxKDPoqo+jXhvwvvqJOASEx90= dependencies: esprima "^4.0.1" @@ -4614,7 +5826,7 @@ escodegen@^2.0.0: eslint-ast-utils@^1.1.0: version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/eslint-ast-utils/download/eslint-ast-utils-1.1.0.tgz#3d58ba557801cfb1c941d68131ee9f8c34bd1586" + resolved "https://registry.npm.alibaba-inc.com/eslint-ast-utils/download/eslint-ast-utils-1.1.0.tgz" integrity sha1-PVi6VXgBz7HJQdaBMe6fjDS9FYY= dependencies: lodash.get "^4.4.2" @@ -4622,12 +5834,12 @@ eslint-ast-utils@^1.1.0: eslint-config-prettier@^8.3.0: version "8.5.0" - resolved "https://registry.npm.alibaba-inc.com/eslint-config-prettier/download/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1" + resolved "https://registry.npm.alibaba-inc.com/eslint-config-prettier/download/eslint-config-prettier-8.5.0.tgz" integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== eslint-formatter-pretty@^4.0.0: version "4.1.0" - resolved "https://registry.npm.alibaba-inc.com/eslint-formatter-pretty/download/eslint-formatter-pretty-4.1.0.tgz#7a6877c14ffe2672066c853587d89603e97c7708" + resolved "https://registry.npm.alibaba-inc.com/eslint-formatter-pretty/download/eslint-formatter-pretty-4.1.0.tgz" integrity sha1-emh3wU/+JnIGbIU1h9iWA+l8dwg= dependencies: "@types/eslint" "^7.2.13" @@ -4641,31 +5853,31 @@ eslint-formatter-pretty@^4.0.0: eslint-plugin-babel@^5.3.0: version "5.3.1" - resolved "https://registry.npm.alibaba-inc.com/eslint-plugin-babel/download/eslint-plugin-babel-5.3.1.tgz#75a2413ffbf17e7be57458301c60291f2cfbf560" + resolved "https://registry.npm.alibaba-inc.com/eslint-plugin-babel/download/eslint-plugin-babel-5.3.1.tgz" integrity sha1-daJBP/vxfnvldFgwHGApHyz79WA= dependencies: eslint-rule-composer "^0.3.0" eslint-plugin-jest@^24.0.1: version "24.7.0" - resolved "https://registry.npm.alibaba-inc.com/eslint-plugin-jest/download/eslint-plugin-jest-24.7.0.tgz#206ac0833841e59e375170b15f8d0955219c4889" + resolved "https://registry.npm.alibaba-inc.com/eslint-plugin-jest/download/eslint-plugin-jest-24.7.0.tgz" integrity sha1-IGrAgzhB5Z43UXCxX40JVSGcSIk= dependencies: "@typescript-eslint/experimental-utils" "^4.0.1" eslint-plugin-promise@^6.0.0: version "6.1.1" - resolved "https://registry.npm.alibaba-inc.com/eslint-plugin-promise/download/eslint-plugin-promise-6.1.1.tgz#269a3e2772f62875661220631bd4dafcb4083816" + resolved "https://registry.npm.alibaba-inc.com/eslint-plugin-promise/download/eslint-plugin-promise-6.1.1.tgz" integrity sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig== eslint-plugin-react-hooks@^4.1.2: version "4.6.0" - resolved "https://registry.npm.alibaba-inc.com/eslint-plugin-react-hooks/download/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" + resolved "https://registry.npm.alibaba-inc.com/eslint-plugin-react-hooks/download/eslint-plugin-react-hooks-4.6.0.tgz" integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== eslint-plugin-react@^7.21.5: version "7.31.11" - resolved "https://registry.npm.alibaba-inc.com/eslint-plugin-react/download/eslint-plugin-react-7.31.11.tgz#011521d2b16dcf95795df688a4770b4eaab364c8" + resolved "https://registry.npm.alibaba-inc.com/eslint-plugin-react/download/eslint-plugin-react-7.31.11.tgz" integrity sha512-TTvq5JsT5v56wPa9OYHzsrOlHzKZKjV+aLgS+55NJP/cuzdiQPC7PfYoUjMoxlffKtvijpk7vA/jmuqRb9nohw== dependencies: array-includes "^3.1.6" @@ -4686,7 +5898,7 @@ eslint-plugin-react@^7.21.5: eslint-plugin-unicorn@^20.0.0: version "20.1.0" - resolved "https://registry.npm.alibaba-inc.com/eslint-plugin-unicorn/download/eslint-plugin-unicorn-20.1.0.tgz#a43f60ffc98406d72ec2a5fcc6dad24ba0192bc9" + resolved "https://registry.npm.alibaba-inc.com/eslint-plugin-unicorn/download/eslint-plugin-unicorn-20.1.0.tgz" integrity sha1-pD9g/8mEBtcuwqX8xtrSS6AZK8k= dependencies: ci-info "^2.0.0" @@ -4705,17 +5917,17 @@ eslint-plugin-unicorn@^20.0.0: eslint-rule-composer@^0.3.0: version "0.3.0" - resolved "https://registry.npm.alibaba-inc.com/eslint-rule-composer/download/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" + resolved "https://registry.npm.alibaba-inc.com/eslint-rule-composer/download/eslint-rule-composer-0.3.0.tgz" integrity sha1-eTIMknsMXA09PSt2yLSkiPJbuvk= eslint-rule-docs@^1.1.5: version "1.1.235" - resolved "https://registry.npm.alibaba-inc.com/eslint-rule-docs/download/eslint-rule-docs-1.1.235.tgz#be6ef1fc3525f17b3c859ae2997fedadc89bfb9b" + resolved "https://registry.npm.alibaba-inc.com/eslint-rule-docs/download/eslint-rule-docs-1.1.235.tgz" integrity sha512-+TQ+x4JdTnDoFEXXb3fDvfGOwnyNV7duH8fXWTPD1ieaBmB8omj7Gw/pMBBu4uI2uJCCU8APDaQJzWuXnTsH4A== eslint-scope@5.1.1, eslint-scope@^5.1.1: version "5.1.1" - resolved "https://registry.npm.alibaba-inc.com/eslint-scope/download/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + resolved "https://registry.npm.alibaba-inc.com/eslint-scope/download/eslint-scope-5.1.1.tgz" integrity sha1-54blmmbLkrP2wfsNUIqrF0hI9Iw= dependencies: esrecurse "^4.3.0" @@ -4723,7 +5935,7 @@ eslint-scope@5.1.1, eslint-scope@^5.1.1: eslint-template-visitor@^2.0.0: version "2.3.2" - resolved "https://registry.npm.alibaba-inc.com/eslint-template-visitor/download/eslint-template-visitor-2.3.2.tgz#b52f96ff311e773a345d79053ccc78275bbc463d" + resolved "https://registry.npm.alibaba-inc.com/eslint-template-visitor/download/eslint-template-visitor-2.3.2.tgz" integrity sha1-tS+W/zEedzo0XXkFPMx4J1u8Rj0= dependencies: "@babel/core" "^7.12.16" @@ -4734,36 +5946,36 @@ eslint-template-visitor@^2.0.0: eslint-utils@^2.0.0, eslint-utils@^2.1.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/eslint-utils/download/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + resolved "https://registry.npm.alibaba-inc.com/eslint-utils/download/eslint-utils-2.1.0.tgz" integrity sha1-0t5eA0JOcH3BDHQGjd7a5wh0Gyc= dependencies: eslint-visitor-keys "^1.1.0" eslint-utils@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/eslint-utils/download/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + resolved "https://registry.npm.alibaba-inc.com/eslint-utils/download/eslint-utils-3.0.0.tgz" integrity sha1-iuuvrOc0W7M1WdsKHxOh0tSMNnI= dependencies: eslint-visitor-keys "^2.0.0" eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: version "1.3.0" - resolved "https://registry.npm.alibaba-inc.com/eslint-visitor-keys/download/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + resolved "https://registry.npm.alibaba-inc.com/eslint-visitor-keys/download/eslint-visitor-keys-1.3.0.tgz" integrity sha1-MOvR73wv3/AcOk8VEESvJfqwUj4= eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/eslint-visitor-keys/download/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + resolved "https://registry.npm.alibaba-inc.com/eslint-visitor-keys/download/eslint-visitor-keys-2.1.0.tgz" integrity sha1-9lMoJZMFknOSyTjtROsKXJsr0wM= eslint-visitor-keys@^3.3.0: version "3.3.0" - resolved "https://registry.npm.alibaba-inc.com/eslint-visitor-keys/download/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" + resolved "https://registry.npm.alibaba-inc.com/eslint-visitor-keys/download/eslint-visitor-keys-3.3.0.tgz" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== eslint@^7.11.0: version "7.32.0" - resolved "https://registry.npm.alibaba-inc.com/eslint/download/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" + resolved "https://registry.npm.alibaba-inc.com/eslint/download/eslint-7.32.0.tgz" integrity sha1-xtMooUvj+wjI0dIeEsAv23oqgS0= dependencies: "@babel/code-frame" "7.12.11" @@ -4809,7 +6021,7 @@ eslint@^7.11.0: espree@^7.3.0, espree@^7.3.1: version "7.3.1" - resolved "https://registry.npm.alibaba-inc.com/espree/download/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + resolved "https://registry.npm.alibaba-inc.com/espree/download/espree-7.3.1.tgz" integrity sha1-8t8zC3Usb1UBn4vYm3ZgA5wbu7Y= dependencies: acorn "^7.4.0" @@ -4818,59 +6030,64 @@ espree@^7.3.0, espree@^7.3.1: esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" - resolved "https://registry.npm.alibaba-inc.com/esprima/download/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + resolved "https://registry.npm.alibaba-inc.com/esprima/download/esprima-4.0.1.tgz" integrity sha1-E7BM2z5sXRnfkatph6hpVhmwqnE= esquery@^1.3.1, esquery@^1.4.0: version "1.4.0" - resolved "https://registry.npm.alibaba-inc.com/esquery/download/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + resolved "https://registry.npm.alibaba-inc.com/esquery/download/esquery-1.4.0.tgz" integrity sha1-IUj/w4uC6McFff7UhCWz5h8PJKU= dependencies: estraverse "^5.1.0" esrecurse@^4.3.0: version "4.3.0" - resolved "https://registry.npm.alibaba-inc.com/esrecurse/download/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + resolved "https://registry.npm.alibaba-inc.com/esrecurse/download/esrecurse-4.3.0.tgz" integrity sha1-eteWTWeauyi+5yzsY3WLHF0smSE= dependencies: estraverse "^5.2.0" estraverse@^4.1.1: version "4.3.0" - resolved "https://registry.npm.alibaba-inc.com/estraverse/download/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + resolved "https://registry.npm.alibaba-inc.com/estraverse/download/estraverse-4.3.0.tgz" integrity sha1-OYrT88WiSUi+dyXoPRGn3ijNvR0= estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: version "5.3.0" - resolved "https://registry.npm.alibaba-inc.com/estraverse/download/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + resolved "https://registry.npm.alibaba-inc.com/estraverse/download/estraverse-5.3.0.tgz" integrity sha1-LupSkHAvJquP5TcDcP+GyWXSESM= esutils@^2.0.2: version "2.0.3" - resolved "https://registry.npm.alibaba-inc.com/esutils/download/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + resolved "https://registry.npm.alibaba-inc.com/esutils/download/esutils-2.0.3.tgz" integrity sha1-dNLrTeC42hKTcRkQ1Qd1ubcQ72Q= etag@~1.8.1: version "1.8.1" - resolved "https://registry.npm.alibaba-inc.com/etag/download/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + resolved "https://registry.npm.alibaba-inc.com/etag/download/etag-1.8.1.tgz" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= event-emitter@^0.3.5: version "0.3.5" - resolved "https://registry.npm.alibaba-inc.com/event-emitter/download/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + resolved "https://registry.npm.alibaba-inc.com/event-emitter/download/event-emitter-0.3.5.tgz" integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= dependencies: d "1" es5-ext "~0.10.14" +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + events@^3.0.0: version "3.3.0" - resolved "https://registry.npm.alibaba-inc.com/events/download/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + resolved "https://registry.npm.alibaba-inc.com/events/download/events-3.3.0.tgz" integrity sha1-Mala0Kkk4tLEGagTrrLE6HjqdAA= evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" - resolved "https://registry.npm.alibaba-inc.com/evp_bytestokey/download/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + resolved "https://registry.npm.alibaba-inc.com/evp_bytestokey/download/evp_bytestokey-1.0.3.tgz" integrity sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI= dependencies: md5.js "^1.3.4" @@ -4878,12 +6095,12 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: exec-sh@^0.3.2: version "0.3.6" - resolved "https://registry.npm.alibaba-inc.com/exec-sh/download/exec-sh-0.3.6.tgz#ff264f9e325519a60cb5e273692943483cca63bc" + resolved "https://registry.npm.alibaba-inc.com/exec-sh/download/exec-sh-0.3.6.tgz" integrity sha1-/yZPnjJVGaYMteJzaSlDSDzKY7w= execa@^0.8.0: version "0.8.0" - resolved "https://registry.npm.alibaba-inc.com/execa/download/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" + resolved "https://registry.npm.alibaba-inc.com/execa/download/execa-0.8.0.tgz" integrity sha1-2NdrvBtVIX7RkP1t1J08d07PyNo= dependencies: cross-spawn "^5.0.1" @@ -4896,7 +6113,7 @@ execa@^0.8.0: execa@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/execa/download/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + resolved "https://registry.npm.alibaba-inc.com/execa/download/execa-1.0.0.tgz" integrity sha1-xiNqW7TfbW8V6I5/AXeYIWdJ3dg= dependencies: cross-spawn "^6.0.0" @@ -4909,7 +6126,7 @@ execa@^1.0.0: execa@^4.0.0, execa@^4.1.0: version "4.1.0" - resolved "https://registry.npm.alibaba-inc.com/execa/download/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + resolved "https://registry.npm.alibaba-inc.com/execa/download/execa-4.1.0.tgz" integrity sha1-TlSRrRVy8vF6d9OIxshXE1sihHo= dependencies: cross-spawn "^7.0.0" @@ -4924,24 +6141,24 @@ execa@^4.0.0, execa@^4.1.0: execall@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/execall/download/execall-2.0.0.tgz#16a06b5fe5099df7d00be5d9c06eecded1663b45" + resolved "https://registry.npm.alibaba-inc.com/execall/download/execall-2.0.0.tgz" integrity sha1-FqBrX+UJnffQC+XZwG7s3tFmO0U= dependencies: clone-regexp "^2.1.0" exenv@^1.2.0: version "1.2.2" - resolved "https://registry.npm.alibaba-inc.com/exenv/download/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d" + resolved "https://registry.npm.alibaba-inc.com/exenv/download/exenv-1.2.2.tgz" integrity sha1-KueOhdmJQVhnCwPUe+wfA72Ru50= exit@^0.1.2: version "0.1.2" - resolved "https://registry.npm.alibaba-inc.com/exit/download/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + resolved "https://registry.npm.alibaba-inc.com/exit/download/exit-0.1.2.tgz" integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= expand-brackets@^2.1.4: version "2.1.4" - resolved "https://registry.npm.alibaba-inc.com/expand-brackets/download/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + resolved "https://registry.npm.alibaba-inc.com/expand-brackets/download/expand-brackets-2.1.4.tgz" integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= dependencies: debug "^2.3.3" @@ -4954,7 +6171,7 @@ expand-brackets@^2.1.4: expect@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/expect/download/expect-26.6.2.tgz#c6b996bf26bf3fe18b67b2d0f51fc981ba934417" + resolved "https://registry.npm.alibaba-inc.com/expect/download/expect-26.6.2.tgz" integrity sha1-xrmWvya/P+GLZ7LQ9R/JgbqTRBc= dependencies: "@jest/types" "^26.6.2" @@ -4966,21 +6183,21 @@ expect@^26.6.2: ext@^1.1.2: version "1.7.0" - resolved "https://registry.npm.alibaba-inc.com/ext/download/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + resolved "https://registry.npm.alibaba-inc.com/ext/download/ext-1.7.0.tgz" integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== dependencies: type "^2.7.2" extend-shallow@^2.0.1: version "2.0.1" - resolved "https://registry.npm.alibaba-inc.com/extend-shallow/download/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + resolved "https://registry.npm.alibaba-inc.com/extend-shallow/download/extend-shallow-2.0.1.tgz" integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" - resolved "https://registry.npm.alibaba-inc.com/extend-shallow/download/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + resolved "https://registry.npm.alibaba-inc.com/extend-shallow/download/extend-shallow-3.0.2.tgz" integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= dependencies: assign-symbols "^1.0.0" @@ -4988,12 +6205,12 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: extend@^3.0.0: version "3.0.2" - resolved "https://registry.npm.alibaba-inc.com/extend/download/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + resolved "https://registry.npm.alibaba-inc.com/extend/download/extend-3.0.2.tgz" integrity sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo= extglob@^2.0.4: version "2.0.4" - resolved "https://registry.npm.alibaba-inc.com/extglob/download/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + resolved "https://registry.npm.alibaba-inc.com/extglob/download/extglob-2.0.4.tgz" integrity sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM= dependencies: array-unique "^0.3.2" @@ -5007,17 +6224,29 @@ extglob@^2.0.4: fast-deep-equal@3.1.1: version "3.1.1" - resolved "https://registry.npm.alibaba-inc.com/fast-deep-equal/download/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" + resolved "https://registry.npm.alibaba-inc.com/fast-deep-equal/download/fast-deep-equal-3.1.1.tgz" integrity sha1-VFFFB3xQFJHjOxXsQIwpQ3bpSuQ= fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" - resolved "https://registry.npm.alibaba-inc.com/fast-deep-equal/download/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + resolved "https://registry.npm.alibaba-inc.com/fast-deep-equal/download/fast-deep-equal-3.1.3.tgz" integrity sha1-On1WtVnWy8PrUSMlJE5hmmXGxSU= +fast-glob@^2.2.6: + version "2.2.7" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz" + integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== + dependencies: + "@mrmlnc/readdir-enhanced" "^2.2.1" + "@nodelib/fs.stat" "^1.1.2" + glob-parent "^3.1.0" + is-glob "^4.0.0" + merge2 "^1.2.3" + micromatch "^3.1.10" + fast-glob@^3.0.3, fast-glob@^3.2.4, fast-glob@^3.2.5, fast-glob@^3.2.9: version "3.2.12" - resolved "https://registry.npm.alibaba-inc.com/fast-glob/download/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + resolved "https://registry.npm.alibaba-inc.com/fast-glob/download/fast-glob-3.2.12.tgz" integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== dependencies: "@nodelib/fs.stat" "^2.0.2" @@ -5028,42 +6257,54 @@ fast-glob@^3.0.3, fast-glob@^3.2.4, fast-glob@^3.2.5, fast-glob@^3.2.9: fast-json-stable-stringify@^2.0.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/fast-json-stable-stringify/download/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + resolved "https://registry.npm.alibaba-inc.com/fast-json-stable-stringify/download/fast-json-stable-stringify-2.1.0.tgz" integrity sha1-h0v2nG9ATCtdmcSBNBOZ/VWJJjM= fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" - resolved "https://registry.npm.alibaba-inc.com/fast-levenshtein/download/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + resolved "https://registry.npm.alibaba-inc.com/fast-levenshtein/download/fast-levenshtein-2.0.6.tgz" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= fast-safe-stringify@^2.0.7: version "2.1.1" - resolved "https://registry.npm.alibaba-inc.com/fast-safe-stringify/download/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + resolved "https://registry.npm.alibaba-inc.com/fast-safe-stringify/download/fast-safe-stringify-2.1.1.tgz" integrity sha1-xAaoO25w2eNc47MKgRQd8wrrqIQ= fastest-levenshtein@^1.0.12: version "1.0.16" - resolved "https://registry.npm.alibaba-inc.com/fastest-levenshtein/download/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + resolved "https://registry.npm.alibaba-inc.com/fastest-levenshtein/download/fastest-levenshtein-1.0.16.tgz" integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== fastq@^1.6.0: version "1.13.0" - resolved "https://registry.npm.alibaba-inc.com/fastq/download/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" + resolved "https://registry.npm.alibaba-inc.com/fastq/download/fastq-1.13.0.tgz" integrity sha1-YWdg+Ip1Jr38WWt8q4wYk4w2uYw= dependencies: reusify "^1.0.4" fb-watchman@^2.0.0: version "2.0.2" - resolved "https://registry.npm.alibaba-inc.com/fb-watchman/download/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + resolved "https://registry.npm.alibaba-inc.com/fb-watchman/download/fb-watchman-2.0.2.tgz" integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== dependencies: bser "2.1.1" -fbjs@^0.8.3: +fbemitter@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/fbemitter/-/fbemitter-3.0.0.tgz" + integrity sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw== + dependencies: + fbjs "^3.0.0" + +fbjs-css-vars@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz" + integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== + +fbjs@^0.8.15, fbjs@^0.8.3: version "0.8.18" - resolved "https://registry.npm.alibaba-inc.com/fbjs/download/fbjs-0.8.18.tgz#9835e0addb9aca2eff53295cd79ca1cfc7c9662a" - integrity sha1-mDXgrduayi7/Uylc15yhz8fJZio= + resolved "https://registry.npmjs.org/fbjs/-/fbjs-0.8.18.tgz" + integrity sha512-EQaWFK+fEPSoibjNy8IxUtaFOMXcWsY0JaVrQoZR9zC8N2Ygf9iDITPWjUTVIax95b6I742JFLqASHfsag/vKA== dependencies: core-js "^1.0.0" isomorphic-fetch "^2.1.1" @@ -5073,16 +6314,39 @@ fbjs@^0.8.3: setimmediate "^1.0.5" ua-parser-js "^0.7.30" +fbjs@^3.0.0, fbjs@^3.0.1: + version "3.0.5" + resolved "https://registry.npmjs.org/fbjs/-/fbjs-3.0.5.tgz" + integrity sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg== + dependencies: + cross-fetch "^3.1.5" + fbjs-css-vars "^1.0.0" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^1.0.35" + +fecha@~4.2.0: + version "4.2.3" + resolved "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz" + integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== + file-entry-cache@^6.0.1: version "6.0.1" - resolved "https://registry.npm.alibaba-inc.com/file-entry-cache/download/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + resolved "https://registry.npm.alibaba-inc.com/file-entry-cache/download/file-entry-cache-6.0.1.tgz" integrity sha1-IRst2WWcsDlLBz5zI6w8kz1SICc= dependencies: flat-cache "^3.0.4" +filesize@^10.0.12: + version "10.0.12" + resolved "https://registry.npmjs.org/filesize/-/filesize-10.0.12.tgz" + integrity sha512-6RS9gDchbn+qWmtV2uSjo5vmKizgfCQeb5jKmqx8HyzA3MoLqqyQxN+QcjkGBJt7FjJ9qFce67Auyya5rRRbpw== + fill-range@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/fill-range/download/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + resolved "https://registry.npm.alibaba-inc.com/fill-range/download/fill-range-4.0.0.tgz" integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= dependencies: extend-shallow "^2.0.1" @@ -5092,19 +6356,24 @@ fill-range@^4.0.0: fill-range@^7.0.1: version "7.0.1" - resolved "https://registry.npm.alibaba-inc.com/fill-range/download/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + resolved "https://registry.npm.alibaba-inc.com/fill-range/download/fill-range-7.0.1.tgz" integrity sha1-GRmmp8df44ssfHflGYU12prN2kA= dependencies: to-regex-range "^5.0.1" filter-obj@^1.1.0: version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/filter-obj/download/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" + resolved "https://registry.npm.alibaba-inc.com/filter-obj/download/filter-obj-1.1.0.tgz" integrity sha1-mzERErxsYSehbgFsbF1/GeCAXFs= +filter-obj@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/filter-obj/-/filter-obj-5.1.0.tgz" + integrity sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng== + find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" - resolved "https://registry.npm.alibaba-inc.com/find-up/download/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + resolved "https://registry.npm.alibaba-inc.com/find-up/download/find-up-4.1.0.tgz" integrity sha1-l6/n1s3AvFkoWEt8jXsW6KmqXRk= dependencies: locate-path "^5.0.0" @@ -5112,7 +6381,7 @@ find-up@^4.0.0, find-up@^4.1.0: flat-cache@^3.0.4: version "3.0.4" - resolved "https://registry.npm.alibaba-inc.com/flat-cache/download/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + resolved "https://registry.npm.alibaba-inc.com/flat-cache/download/flat-cache-3.0.4.tgz" integrity sha1-YbAzgwKy/p+Vfcwy/CqH8cMEixE= dependencies: flatted "^3.1.0" @@ -5120,22 +6389,37 @@ flat-cache@^3.0.4: flatted@^3.1.0: version "3.2.7" - resolved "https://registry.npm.alibaba-inc.com/flatted/download/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" + resolved "https://registry.npm.alibaba-inc.com/flatted/download/flatted-3.2.7.tgz" integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== flatten@^1.0.2: version "1.0.3" - resolved "https://registry.npm.alibaba-inc.com/flatten/download/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" + resolved "https://registry.npm.alibaba-inc.com/flatten/download/flatten-1.0.3.tgz" integrity sha1-wSg6yfJ7Noq8HjbR/3sEUBowNWs= +flux@^4.0.1: + version "4.0.4" + resolved "https://registry.npmjs.org/flux/-/flux-4.0.4.tgz" + integrity sha512-NCj3XlayA2UsapRpM7va6wU1+9rE5FIL7qoMcmxWHRzbp0yujihMBm9BBHZ1MDIk5h5o2Bl6eGiCe8rYELAmYw== + dependencies: + fbemitter "^3.0.0" + fbjs "^3.0.1" + +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + for-in@^1.0.2: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/for-in/download/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + resolved "https://registry.npm.alibaba-inc.com/for-in/download/for-in-1.0.2.tgz" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= form-data@^3.0.0: version "3.0.1" - resolved "https://registry.npm.alibaba-inc.com/form-data/download/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + resolved "https://registry.npm.alibaba-inc.com/form-data/download/form-data-3.0.1.tgz" integrity sha1-69U3kbeDVqma+aMA1CgsTV65dV8= dependencies: asynckit "^0.4.0" @@ -5144,34 +6428,34 @@ form-data@^3.0.0: fragment-cache@^0.2.1: version "0.2.1" - resolved "https://registry.npm.alibaba-inc.com/fragment-cache/download/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + resolved "https://registry.npm.alibaba-inc.com/fragment-cache/download/fragment-cache-0.2.1.tgz" integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= dependencies: map-cache "^0.2.2" fresh@0.5.2: version "0.5.2" - resolved "https://registry.npm.alibaba-inc.com/fresh/download/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + resolved "https://registry.npm.alibaba-inc.com/fresh/download/fresh-0.5.2.tgz" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/fs.realpath/download/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.npm.alibaba-inc.com/fs.realpath/download/fs.realpath-1.0.0.tgz" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@^2.1.2, fsevents@~2.3.1: version "2.3.2" - resolved "https://registry.npm.alibaba-inc.com/fsevents/download/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + resolved "https://registry.npm.alibaba-inc.com/fsevents/download/fsevents-2.3.2.tgz" integrity sha1-ilJveLj99GI7cJ4Ll1xSwkwC/Ro= function-bind@^1.1.1: version "1.1.1" - resolved "https://registry.npm.alibaba-inc.com/function-bind/download/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + resolved "https://registry.npm.alibaba-inc.com/function-bind/download/function-bind-1.1.1.tgz" integrity sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0= function.prototype.name@^1.1.5: version "1.1.5" - resolved "https://registry.npm.alibaba-inc.com/function.prototype.name/download/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + resolved "https://registry.npm.alibaba-inc.com/function.prototype.name/download/function.prototype.name-1.1.5.tgz" integrity sha1-zOBQX+H/uAUD5vnkbMZORqEqliE= dependencies: call-bind "^1.0.2" @@ -5181,70 +6465,80 @@ function.prototype.name@^1.1.5: functional-red-black-tree@^1.0.1: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/functional-red-black-tree/download/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + resolved "https://registry.npm.alibaba-inc.com/functional-red-black-tree/download/functional-red-black-tree-1.0.1.tgz" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= functions-have-names@^1.2.2: version "1.2.3" - resolved "https://registry.npm.alibaba-inc.com/functions-have-names/download/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + resolved "https://registry.npm.alibaba-inc.com/functions-have-names/download/functions-have-names-1.2.3.tgz" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== gensync@^1.0.0-beta.2: version "1.0.0-beta.2" - resolved "https://registry.npm.alibaba-inc.com/gensync/download/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + resolved "https://registry.npm.alibaba-inc.com/gensync/download/gensync-1.0.0-beta.2.tgz" integrity sha1-MqbudsPX9S1GsrGuXZP+qFgKJeA= get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" - resolved "https://registry.npm.alibaba-inc.com/get-caller-file/download/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + resolved "https://registry.npm.alibaba-inc.com/get-caller-file/download/get-caller-file-2.0.5.tgz" integrity sha1-T5RBKoLbMvNuOwuXQfipf+sDH34= get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: version "1.1.3" - resolved "https://registry.npm.alibaba-inc.com/get-intrinsic/download/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" + resolved "https://registry.npm.alibaba-inc.com/get-intrinsic/download/get-intrinsic-1.1.3.tgz" integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== dependencies: function-bind "^1.1.1" has "^1.0.3" has-symbols "^1.0.3" +get-intrinsic@^1.2.0, get-intrinsic@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" - resolved "https://registry.npm.alibaba-inc.com/get-own-enumerable-property-symbols/download/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" + resolved "https://registry.npm.alibaba-inc.com/get-own-enumerable-property-symbols/download/get-own-enumerable-property-symbols-3.0.2.tgz" integrity sha1-tf3nfyLL4185C04ImSLFC85u9mQ= get-package-type@^0.1.0: version "0.1.0" - resolved "https://registry.npm.alibaba-inc.com/get-package-type/download/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + resolved "https://registry.npm.alibaba-inc.com/get-package-type/download/get-package-type-0.1.0.tgz" integrity sha1-jeLYA8/0TfO8bEVuZmizbDkm4Ro= get-stdin@^8.0.0: version "8.0.0" - resolved "https://registry.npm.alibaba-inc.com/get-stdin/download/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53" + resolved "https://registry.npm.alibaba-inc.com/get-stdin/download/get-stdin-8.0.0.tgz" integrity sha1-y61qc/63X27rIrqeAfiaooqpelM= get-stream@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/get-stream/download/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + resolved "https://registry.npm.alibaba-inc.com/get-stream/download/get-stream-3.0.0.tgz" integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= get-stream@^4.0.0: version "4.1.0" - resolved "https://registry.npm.alibaba-inc.com/get-stream/download/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + resolved "https://registry.npm.alibaba-inc.com/get-stream/download/get-stream-4.1.0.tgz" integrity sha1-wbJVV189wh1Zv8ec09K0axw6VLU= dependencies: pump "^3.0.0" get-stream@^5.0.0: version "5.2.0" - resolved "https://registry.npm.alibaba-inc.com/get-stream/download/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + resolved "https://registry.npm.alibaba-inc.com/get-stream/download/get-stream-5.2.0.tgz" integrity sha1-SWaheV7lrOZecGxLe+txJX1uItM= dependencies: pump "^3.0.0" get-symbol-description@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/get-symbol-description/download/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + resolved "https://registry.npm.alibaba-inc.com/get-symbol-description/download/get-symbol-description-1.0.0.tgz" integrity sha1-f9uByQAQH71WTdXxowr1qtweWNY= dependencies: call-bind "^1.0.2" @@ -5252,24 +6546,47 @@ get-symbol-description@^1.0.0: get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" - resolved "https://registry.npm.alibaba-inc.com/get-value/download/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + resolved "https://registry.npm.alibaba-inc.com/get-value/download/get-value-2.0.6.tgz" integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= git-hooks-list@1.0.3: version "1.0.3" - resolved "https://registry.npm.alibaba-inc.com/git-hooks-list/download/git-hooks-list-1.0.3.tgz#be5baaf78203ce342f2f844a9d2b03dba1b45156" + resolved "https://registry.npm.alibaba-inc.com/git-hooks-list/download/git-hooks-list-1.0.3.tgz" integrity sha1-vluq94IDzjQvL4RKnSsD26G0UVY= +gl-matrix@^3.0.0, gl-matrix@^3.1.0, gl-matrix@^3.3.0, gl-matrix@^3.4.3: + version "3.4.3" + resolved "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz" + integrity sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA== + +gl-vec2@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/gl-vec2/-/gl-vec2-1.3.0.tgz" + integrity sha512-YiqaAuNsheWmUV0Sa8k94kBB0D6RWjwZztyO+trEYS8KzJ6OQB/4686gdrf59wld4hHFIvaxynO3nRxpk1Ij/A== + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz" + integrity sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA== + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + glob-parent@^5.1.2, glob-parent@~5.1.0: version "5.1.2" - resolved "https://registry.npm.alibaba-inc.com/glob-parent/download/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + resolved "https://registry.npm.alibaba-inc.com/glob-parent/download/glob-parent-5.1.2.tgz" integrity sha1-hpgyxYA0/mikCTwX3BXoNA2EAcQ= dependencies: is-glob "^4.0.1" +glob-to-regexp@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz" + integrity sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig== + glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.3" - resolved "https://registry.npm.alibaba-inc.com/glob/download/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + resolved "https://registry.npm.alibaba-inc.com/glob/download/glob-7.2.3.tgz" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" @@ -5281,14 +6598,14 @@ glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: global-modules@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/global-modules/download/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + resolved "https://registry.npm.alibaba-inc.com/global-modules/download/global-modules-2.0.0.tgz" integrity sha1-mXYFrSNF8n9RU5vqJldEISFcd4A= dependencies: global-prefix "^3.0.0" global-prefix@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/global-prefix/download/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + resolved "https://registry.npm.alibaba-inc.com/global-prefix/download/global-prefix-3.0.0.tgz" integrity sha1-/IX3MGTfafUEIfR/iD/luRO6m5c= dependencies: ini "^1.3.5" @@ -5297,7 +6614,7 @@ global-prefix@^3.0.0: global@^4.3.1, global@^4.3.2, global@^4.4.0, global@~4.4.0: version "4.4.0" - resolved "https://registry.npm.alibaba-inc.com/global/download/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" + resolved "https://registry.npm.alibaba-inc.com/global/download/global-4.4.0.tgz" integrity sha1-PnsQUXkAajI+1xqvyj6cV6XMZAY= dependencies: min-document "^2.19.0" @@ -5305,19 +6622,26 @@ global@^4.3.1, global@^4.3.2, global@^4.4.0, global@~4.4.0: globals@^11.1.0: version "11.12.0" - resolved "https://registry.npm.alibaba-inc.com/globals/download/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + resolved "https://registry.npm.alibaba-inc.com/globals/download/globals-11.12.0.tgz" integrity sha1-q4eVM4hooLq9hSV1gBjCp+uVxC4= globals@^13.6.0, globals@^13.9.0: version "13.18.0" - resolved "https://registry.npm.alibaba-inc.com/globals/download/globals-13.18.0.tgz#fb224daeeb2bb7d254cd2c640f003528b8d0c1dc" + resolved "https://registry.npm.alibaba-inc.com/globals/download/globals-13.18.0.tgz" integrity sha512-/mR4KI8Ps2spmoc0Ulu9L7agOF0du1CZNQ3dke8yItYlyKNmGrkONemBbd6V8UTc1Wgcqn21t3WYB7dbRmh6/A== dependencies: type-fest "^0.20.2" +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + globby@10.0.0: version "10.0.0" - resolved "https://registry.npm.alibaba-inc.com/globby/download/globby-10.0.0.tgz#abfcd0630037ae174a88590132c2f6804e291072" + resolved "https://registry.npm.alibaba-inc.com/globby/download/globby-10.0.0.tgz" integrity sha1-q/zQYwA3rhdKiFkBMsL2gE4pEHI= dependencies: "@types/glob" "^7.1.1" @@ -5329,9 +6653,9 @@ globby@10.0.0: merge2 "^1.2.3" slash "^3.0.0" -globby@^11.0.3, globby@^11.1.0: +globby@^11.0.0, globby@^11.0.3, globby@^11.1.0: version "11.1.0" - resolved "https://registry.npm.alibaba-inc.com/globby/download/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + resolved "https://registry.npm.alibaba-inc.com/globby/download/globby-11.1.0.tgz" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" @@ -5341,75 +6665,120 @@ globby@^11.0.3, globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" +globby@^9.2.0: + version "9.2.0" + resolved "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz" + integrity sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg== + dependencies: + "@types/glob" "^7.1.1" + array-union "^1.0.2" + dir-glob "^2.2.2" + fast-glob "^2.2.6" + glob "^7.1.3" + ignore "^4.0.3" + pify "^4.0.1" + slash "^2.0.0" + globjoin@^0.1.4: version "0.1.4" - resolved "https://registry.npm.alibaba-inc.com/globjoin/download/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43" + resolved "https://registry.npm.alibaba-inc.com/globjoin/download/globjoin-0.1.4.tgz" integrity sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM= gonzales-pe@^4.3.0: version "4.3.0" - resolved "https://registry.npm.alibaba-inc.com/gonzales-pe/download/gonzales-pe-4.3.0.tgz#fe9dec5f3c557eead09ff868c65826be54d067b3" + resolved "https://registry.npm.alibaba-inc.com/gonzales-pe/download/gonzales-pe-4.3.0.tgz" integrity sha1-/p3sXzxVfurQn/hoxlgmvlTQZ7M= dependencies: minimist "^1.2.5" +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graceful-fs@^4.1.2: + version "4.2.11" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + graceful-fs@^4.2.4: version "4.2.10" - resolved "https://registry.npm.alibaba-inc.com/graceful-fs/download/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + resolved "https://registry.npm.alibaba-inc.com/graceful-fs/download/graceful-fs-4.2.10.tgz" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== +graphlib@^2.1.8: + version "2.1.8" + resolved "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz" + integrity sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A== + dependencies: + lodash "^4.17.15" + growly@^1.3.0: version "1.3.0" - resolved "https://registry.npm.alibaba-inc.com/growly/download/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" + resolved "https://registry.npm.alibaba-inc.com/growly/download/growly-1.3.0.tgz" integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= hard-rejection@^2.1.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/hard-rejection/download/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" + resolved "https://registry.npm.alibaba-inc.com/hard-rejection/download/hard-rejection-2.1.0.tgz" integrity sha1-HG7aXBaFxjlCdm15u0Cudzzs2IM= harmony-reflect@^1.4.6: version "1.6.2" - resolved "https://registry.npm.alibaba-inc.com/harmony-reflect/download/harmony-reflect-1.6.2.tgz#31ecbd32e648a34d030d86adb67d4d47547fe710" + resolved "https://registry.npm.alibaba-inc.com/harmony-reflect/download/harmony-reflect-1.6.2.tgz" integrity sha1-Mey9MuZIo00DDYattn1NR1R/5xA= has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/has-bigints/download/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + resolved "https://registry.npm.alibaba-inc.com/has-bigints/download/has-bigints-1.0.2.tgz" integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/has-flag/download/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + resolved "https://registry.npm.alibaba-inc.com/has-flag/download/has-flag-3.0.0.tgz" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/has-flag/download/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + resolved "https://registry.npm.alibaba-inc.com/has-flag/download/has-flag-4.0.0.tgz" integrity sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s= +has-glob@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/has-glob/-/has-glob-1.0.0.tgz" + integrity sha512-D+8A457fBShSEI3tFCj65PAbT++5sKiFtdCdOam0gnfBgw9D277OERk+HM9qYJXmdVLZ/znez10SqHN0BBQ50g== + dependencies: + is-glob "^3.0.0" + has-property-descriptors@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/has-property-descriptors/download/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + resolved "https://registry.npm.alibaba-inc.com/has-property-descriptors/download/has-property-descriptors-1.0.0.tgz" integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== dependencies: get-intrinsic "^1.1.1" -has-symbols@^1.0.2, has-symbols@^1.0.3: +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" - resolved "https://registry.npm.alibaba-inc.com/has-symbols/download/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + resolved "https://registry.npm.alibaba-inc.com/has-symbols/download/has-symbols-1.0.3.tgz" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== has-tostringtag@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/has-tostringtag/download/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + resolved "https://registry.npm.alibaba-inc.com/has-tostringtag/download/has-tostringtag-1.0.0.tgz" integrity sha1-fhM4GKfTlHNPlB5zw9P5KR5liyU= dependencies: has-symbols "^1.0.2" has-value@^0.3.1: version "0.3.1" - resolved "https://registry.npm.alibaba-inc.com/has-value/download/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + resolved "https://registry.npm.alibaba-inc.com/has-value/download/has-value-0.3.1.tgz" integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= dependencies: get-value "^2.0.3" @@ -5418,7 +6787,7 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/has-value/download/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + resolved "https://registry.npm.alibaba-inc.com/has-value/download/has-value-1.0.0.tgz" integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= dependencies: get-value "^2.0.6" @@ -5427,12 +6796,12 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" - resolved "https://registry.npm.alibaba-inc.com/has-values/download/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + resolved "https://registry.npm.alibaba-inc.com/has-values/download/has-values-0.1.4.tgz" integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= has-values@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/has-values/download/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + resolved "https://registry.npm.alibaba-inc.com/has-values/download/has-values-1.0.0.tgz" integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= dependencies: is-number "^3.0.0" @@ -5440,14 +6809,14 @@ has-values@^1.0.0: has@^1.0.3: version "1.0.3" - resolved "https://registry.npm.alibaba-inc.com/has/download/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + resolved "https://registry.npm.alibaba-inc.com/has/download/has-1.0.3.tgz" integrity sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y= dependencies: function-bind "^1.1.1" hash-base@^3.0.0: version "3.1.0" - resolved "https://registry.npm.alibaba-inc.com/hash-base/download/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + resolved "https://registry.npm.alibaba-inc.com/hash-base/download/hash-base-3.1.0.tgz" integrity sha1-VcOB2eBuHSmXqIO0o/3f5/DTrzM= dependencies: inherits "^2.0.4" @@ -5456,15 +6825,25 @@ hash-base@^3.0.0: hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" - resolved "https://registry.npm.alibaba-inc.com/hash.js/download/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + resolved "https://registry.npm.alibaba-inc.com/hash.js/download/hash.js-1.1.7.tgz" integrity sha1-C6vKU46NTuSg+JiNaIZlN6ADz0I= dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.1" +highlight.js@^11.8.0: + version "11.8.0" + resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-11.8.0.tgz" + integrity sha512-MedQhoqVdr0U6SSnWPzfiadUcDHfN/Wzq25AkXiQv9oiOO/sG0S7XkvpFIqWBl9Yq1UYyYOOVORs5UW2XlPyzg== + +highlightjs-solidity@^2.0.6: + version "2.0.6" + resolved "https://registry.npmjs.org/highlightjs-solidity/-/highlightjs-solidity-2.0.6.tgz" + integrity sha512-DySXWfQghjm2l6a/flF+cteroJqD4gI8GSdL4PtvxZSsAHie8m3yVe2JFoRg03ROKT6hp2Lc/BxXkqerNmtQYg== + history-with-query@4.10.4: version "4.10.4" - resolved "https://registry.npm.alibaba-inc.com/history-with-query/download/history-with-query-4.10.4.tgz#8161ff3c5044e29dfaeb73e7587eb3d4c1a8090e" + resolved "https://registry.npm.alibaba-inc.com/history-with-query/download/history-with-query-4.10.4.tgz" integrity sha1-gWH/PFBE4p3663PnWH6z1MGoCQ4= dependencies: "@babel/runtime" "^7.1.2" @@ -5477,14 +6856,14 @@ history-with-query@4.10.4: history@*: version "5.3.0" - resolved "https://registry.npm.alibaba-inc.com/history/download/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b" + resolved "https://registry.npm.alibaba-inc.com/history/download/history-5.3.0.tgz" integrity sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ== dependencies: "@babel/runtime" "^7.7.6" history@^4.10.1, history@^4.7.2, history@^4.9.0: version "4.10.1" - resolved "https://registry.npm.alibaba-inc.com/history/download/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" + resolved "https://registry.npm.alibaba-inc.com/history/download/history-4.10.1.tgz" integrity sha1-MzcaZeOoOyZ0NOKz87G0xYqtTPM= dependencies: "@babel/runtime" "^7.1.2" @@ -5496,7 +6875,7 @@ history@^4.10.1, history@^4.7.2, history@^4.9.0: hmac-drbg@^1.0.1: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/hmac-drbg/download/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + resolved "https://registry.npm.alibaba-inc.com/hmac-drbg/download/hmac-drbg-1.0.1.tgz" integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= dependencies: hash.js "^1.0.3" @@ -5505,48 +6884,48 @@ hmac-drbg@^1.0.1: hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: version "3.3.2" - resolved "https://registry.npm.alibaba-inc.com/hoist-non-react-statics/download/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + resolved "https://registry.npm.alibaba-inc.com/hoist-non-react-statics/download/hoist-non-react-statics-3.3.2.tgz" integrity sha1-7OCsr3HWLClpwuxZ/v9CpLGoW0U= dependencies: react-is "^16.7.0" hosted-git-info@^2.1.4: version "2.8.9" - resolved "https://registry.npm.alibaba-inc.com/hosted-git-info/download/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + resolved "https://registry.npm.alibaba-inc.com/hosted-git-info/download/hosted-git-info-2.8.9.tgz" integrity sha1-3/wL+aIcAiCQkPKqaUKeFBTa8/k= hosted-git-info@^4.0.1: version "4.1.0" - resolved "https://registry.npm.alibaba-inc.com/hosted-git-info/download/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" + resolved "https://registry.npm.alibaba-inc.com/hosted-git-info/download/hosted-git-info-4.1.0.tgz" integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== dependencies: lru-cache "^6.0.0" html-encoding-sniffer@^2.0.1: version "2.0.1" - resolved "https://registry.npm.alibaba-inc.com/html-encoding-sniffer/download/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" + resolved "https://registry.npm.alibaba-inc.com/html-encoding-sniffer/download/html-encoding-sniffer-2.0.1.tgz" integrity sha1-QqbcT9M/ACgRduiyN1nKTk+hhfM= dependencies: whatwg-encoding "^1.0.5" html-entities@^2.1.0: version "2.3.3" - resolved "https://registry.npm.alibaba-inc.com/html-entities/download/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" + resolved "https://registry.npm.alibaba-inc.com/html-entities/download/html-entities-2.3.3.tgz" integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA== html-escaper@^2.0.0: version "2.0.2" - resolved "https://registry.npm.alibaba-inc.com/html-escaper/download/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + resolved "https://registry.npm.alibaba-inc.com/html-escaper/download/html-escaper-2.0.2.tgz" integrity sha1-39YAJ9o2o238viNiYsAKWCJoFFM= html-tags@^3.1.0: version "3.2.0" - resolved "https://registry.npm.alibaba-inc.com/html-tags/download/html-tags-3.2.0.tgz#dbb3518d20b726524e4dd43de397eb0a95726961" + resolved "https://registry.npm.alibaba-inc.com/html-tags/download/html-tags-3.2.0.tgz" integrity sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg== htmlparser2@^3.10.0: version "3.10.1" - resolved "https://registry.npm.alibaba-inc.com/htmlparser2/download/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" + resolved "https://registry.npm.alibaba-inc.com/htmlparser2/download/htmlparser2-3.10.1.tgz" integrity sha1-vWedw/WYl7ajS7EHSchVu1OpOS8= dependencies: domelementtype "^1.3.1" @@ -5558,7 +6937,7 @@ htmlparser2@^3.10.0: http-errors@2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/http-errors/download/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + resolved "https://registry.npm.alibaba-inc.com/http-errors/download/http-errors-2.0.0.tgz" integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== dependencies: depd "2.0.0" @@ -5569,7 +6948,7 @@ http-errors@2.0.0: http-proxy-agent@^4.0.1: version "4.0.1" - resolved "https://registry.npm.alibaba-inc.com/http-proxy-agent/download/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" + resolved "https://registry.npm.alibaba-inc.com/http-proxy-agent/download/http-proxy-agent-4.0.1.tgz" integrity sha1-ioyO9/WTLM+VPClsqCkblap0qjo= dependencies: "@tootallnate/once" "1" @@ -5578,17 +6957,17 @@ http-proxy-agent@^4.0.1: http2-client@^1.2.5: version "1.3.5" - resolved "https://registry.npm.alibaba-inc.com/http2-client/download/http2-client-1.3.5.tgz#20c9dc909e3cc98284dd20af2432c524086df181" + resolved "https://registry.npm.alibaba-inc.com/http2-client/download/http2-client-1.3.5.tgz" integrity sha1-IMnckJ48yYKE3SCvJDLFJAht8YE= https-browserify@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/https-browserify/download/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + resolved "https://registry.npm.alibaba-inc.com/https-browserify/download/https-browserify-1.0.0.tgz" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= https-proxy-agent@^5.0.0: version "5.0.1" - resolved "https://registry.npm.alibaba-inc.com/https-proxy-agent/download/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + resolved "https://registry.npm.alibaba-inc.com/https-proxy-agent/download/https-proxy-agent-5.0.1.tgz" integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== dependencies: agent-base "6" @@ -5596,77 +6975,82 @@ https-proxy-agent@^5.0.0: human-signals@^1.1.1: version "1.1.1" - resolved "https://registry.npm.alibaba-inc.com/human-signals/download/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + resolved "https://registry.npm.alibaba-inc.com/human-signals/download/human-signals-1.1.1.tgz" integrity sha1-xbHNFPUK6uCatsWf5jujOV/k36M= hyphenate-style-name@^1.0.0: version "1.0.4" - resolved "https://registry.npm.alibaba-inc.com/hyphenate-style-name/download/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d" + resolved "https://registry.npm.alibaba-inc.com/hyphenate-style-name/download/hyphenate-style-name-1.0.4.tgz" integrity sha1-aRh5r44iCupXUOiCfbTvYqVONh0= -i18next@22.4.15: - version "22.4.15" - resolved "https://registry.npm.alibaba-inc.com/i18next/download/i18next-22.4.15.tgz#951882b751872994f8502b5a6ef6f796e6a7d7f8" - integrity sha512-yYudtbFrrmWKLEhl6jvKUYyYunj4bTBCe2qIUYAxbXoPusY7YmdwPvOE6fx6UIfWvmlbCWDItr7wIs8KEBZ5Zg== +i18next@^23.7.6: + version "23.7.6" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.7.6.tgz#7328e76c899052d5d33d930164612dd21e575f74" + integrity sha512-O66BhXBw0fH4bEJMA0/klQKPEbcwAp5wjXEL803pdAynNbg2f4qhLIYlNHJyE7icrL6XmSZKPYaaXwy11kJ6YQ== dependencies: - "@babel/runtime" "^7.20.6" + "@babel/runtime" "^7.23.2" iconv-lite@0.4.24: version "0.4.24" - resolved "https://registry.npm.alibaba-inc.com/iconv-lite/download/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + resolved "https://registry.npm.alibaba-inc.com/iconv-lite/download/iconv-lite-0.4.24.tgz" integrity sha1-ICK0sl+93CHS9SSXSkdKr+czkIs= dependencies: safer-buffer ">= 2.1.2 < 3" iconv-lite@^0.6.2: version "0.6.3" - resolved "https://registry.npm.alibaba-inc.com/iconv-lite/download/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + resolved "https://registry.npm.alibaba-inc.com/iconv-lite/download/iconv-lite-0.6.3.tgz" integrity sha1-pS+AvzjaGVLrXGgXkHGYcaGnJQE= dependencies: safer-buffer ">= 2.1.2 < 3.0.0" identity-obj-proxy@3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/identity-obj-proxy/download/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14" + resolved "https://registry.npm.alibaba-inc.com/identity-obj-proxy/download/identity-obj-proxy-3.0.0.tgz" integrity sha1-lNK9qWCERT7zb7xarsN+D3nx/BQ= dependencies: harmony-reflect "^1.4.6" ieee754@^1.1.4: version "1.2.1" - resolved "https://registry.npm.alibaba-inc.com/ieee754/download/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + resolved "https://registry.npm.alibaba-inc.com/ieee754/download/ieee754-1.2.1.tgz" integrity sha1-jrehCmP/8l0VpXsAFYbRd9Gw01I= -ignore@^4.0.6: +ignore@^4.0.3, ignore@^4.0.6: version "4.0.6" - resolved "https://registry.npm.alibaba-inc.com/ignore/download/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + resolved "https://registry.npm.alibaba-inc.com/ignore/download/ignore-4.0.6.tgz" integrity sha1-dQ49tYYgh7RzfrrIIH/9HvJ7Jfw= ignore@^5.1.1, ignore@^5.1.8, ignore@^5.2.0: version "5.2.0" - resolved "https://registry.npm.alibaba-inc.com/ignore/download/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + resolved "https://registry.npm.alibaba-inc.com/ignore/download/ignore-5.2.0.tgz" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== immer@^7.0.5: version "7.0.15" - resolved "https://registry.npm.alibaba-inc.com/immer/download/immer-7.0.15.tgz#dc3bc6db87401659d2e737c67a21b227c484a4ad" + resolved "https://registry.npm.alibaba-inc.com/immer/download/immer-7.0.15.tgz" integrity sha1-3DvG24dAFlnS5zfGeiGyJ8SEpK0= -immutable@^3.8.1: +immutable@^3.7.4, immutable@^3.8.1: version "3.8.2" - resolved "https://registry.npm.alibaba-inc.com/immutable/download/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3" - integrity sha1-wkOZUUVbs5kT2vKBN28VMOEErfM= + resolved "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz" + integrity sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg== + +immutable@~3.7.4: + version "3.7.6" + resolved "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz" + integrity sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw== import-cwd@^2.0.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/import-cwd/download/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" + resolved "https://registry.npm.alibaba-inc.com/import-cwd/download/import-cwd-2.1.0.tgz" integrity sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk= dependencies: import-from "^2.1.0" import-fresh@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/import-fresh/download/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + resolved "https://registry.npm.alibaba-inc.com/import-fresh/download/import-fresh-2.0.0.tgz" integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= dependencies: caller-path "^2.0.0" @@ -5674,7 +7058,7 @@ import-fresh@^2.0.0: import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" - resolved "https://registry.npm.alibaba-inc.com/import-fresh/download/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + resolved "https://registry.npm.alibaba-inc.com/import-fresh/download/import-fresh-3.3.0.tgz" integrity sha1-NxYsJfy566oublPVtNiM4X2eDCs= dependencies: parent-module "^1.0.0" @@ -5682,19 +7066,19 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: import-from@^2.1.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/import-from/download/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" + resolved "https://registry.npm.alibaba-inc.com/import-from/download/import-from-2.1.0.tgz" integrity sha1-M1238qev/VOqpHHUuAId7ja387E= dependencies: resolve-from "^3.0.0" import-lazy@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/import-lazy/download/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153" + resolved "https://registry.npm.alibaba-inc.com/import-lazy/download/import-lazy-4.0.0.tgz" integrity sha1-6OtidIOgpD2jwD8+NVSL5csMwVM= import-local@^3.0.2: version "3.1.0" - resolved "https://registry.npm.alibaba-inc.com/import-local/download/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + resolved "https://registry.npm.alibaba-inc.com/import-local/download/import-local-3.1.0.tgz" integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== dependencies: pkg-dir "^4.2.0" @@ -5702,32 +7086,32 @@ import-local@^3.0.2: import-modules@^2.0.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/import-modules/download/import-modules-2.1.0.tgz#abe7df297cb6c1f19b57246eb8b8bd9664b6d8c2" + resolved "https://registry.npm.alibaba-inc.com/import-modules/download/import-modules-2.1.0.tgz" integrity sha1-q+ffKXy2wfGbVyRuuLi9lmS22MI= imurmurhash@^0.1.4: version "0.1.4" - resolved "https://registry.npm.alibaba-inc.com/imurmurhash/download/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + resolved "https://registry.npm.alibaba-inc.com/imurmurhash/download/imurmurhash-0.1.4.tgz" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= indent-string@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/indent-string/download/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + resolved "https://registry.npm.alibaba-inc.com/indent-string/download/indent-string-4.0.0.tgz" integrity sha1-Yk+PRJfWGbLZdoUx1Y9BIoVNclE= indexes-of@^1.0.1: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/indexes-of/download/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + resolved "https://registry.npm.alibaba-inc.com/indexes-of/download/indexes-of-1.0.1.tgz" integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= individual@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/individual/download/individual-2.0.0.tgz#833b097dad23294e76117a98fb38e0d9ad61bb97" + resolved "https://registry.npm.alibaba-inc.com/individual/download/individual-2.0.0.tgz" integrity sha1-gzsJfa0jKU52EXqY+zjg2a1hu5c= inflight@^1.0.4: version "1.0.6" - resolved "https://registry.npm.alibaba-inc.com/inflight/download/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.npm.alibaba-inc.com/inflight/download/inflight-1.0.6.tgz" integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" @@ -5735,48 +7119,67 @@ inflight@^1.0.4: inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" - resolved "https://registry.npm.alibaba-inc.com/inherits/download/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + resolved "https://registry.npm.alibaba-inc.com/inherits/download/inherits-2.0.4.tgz" integrity sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w= inherits@2.0.1: version "2.0.1" - resolved "https://registry.npm.alibaba-inc.com/inherits/download/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + resolved "https://registry.npm.alibaba-inc.com/inherits/download/inherits-2.0.1.tgz" integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= inherits@2.0.3: version "2.0.3" - resolved "https://registry.npm.alibaba-inc.com/inherits/download/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + resolved "https://registry.npm.alibaba-inc.com/inherits/download/inherits-2.0.3.tgz" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= ini@^1.3.5: version "1.3.8" - resolved "https://registry.npm.alibaba-inc.com/ini/download/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + resolved "https://registry.npm.alibaba-inc.com/ini/download/ini-1.3.8.tgz" integrity sha1-op2kJbSIBvNHZ6Tvzjlyaa8oQyw= +insert-css@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/insert-css/-/insert-css-2.0.0.tgz" + integrity sha512-xGq5ISgcUP5cvGkS2MMFLtPDBtrtQPSFfC6gA6U8wHKqfjTIMZLZNxOItQnoSjdOzlXOLU/yD32RKC4SvjNbtA== + internal-slot@^1.0.3: version "1.0.3" - resolved "https://registry.npm.alibaba-inc.com/internal-slot/download/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + resolved "https://registry.npm.alibaba-inc.com/internal-slot/download/internal-slot-1.0.3.tgz" integrity sha1-c0fjB97uovqsKsYgXUvH00ln9Zw= dependencies: get-intrinsic "^1.1.0" has "^1.0.3" side-channel "^1.0.4" +internal-slot@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz" + integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== + dependencies: + get-intrinsic "^1.2.0" + has "^1.0.3" + side-channel "^1.0.4" + +intersection-observer@^0.7.0: + version "0.7.0" + resolved "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.7.0.tgz" + integrity sha512-Id0Fij0HsB/vKWGeBe9PxeY45ttRiBmhFyyt/geBdDHBYNctMRTE3dC1U3ujzz3lap+hVXlEcVaB56kZP/eEUg== + intl-format-cache@^4.2.21: version "4.3.1" - resolved "https://registry.npm.alibaba-inc.com/intl-format-cache/download/intl-format-cache-4.3.1.tgz#484d31a9872161e6c02139349b259a6229ade377" + resolved "https://registry.npm.alibaba-inc.com/intl-format-cache/download/intl-format-cache-4.3.1.tgz" integrity sha1-SE0xqYchYebAITk0myWaYimt43c= intl-messageformat-parser@^3.6.4: version "3.6.4" - resolved "https://registry.npm.alibaba-inc.com/intl-messageformat-parser/download/intl-messageformat-parser-3.6.4.tgz#5199d106d816c3dda26ee0694362a9cf823978fb" + resolved "https://registry.npm.alibaba-inc.com/intl-messageformat-parser/download/intl-messageformat-parser-3.6.4.tgz" integrity sha1-UZnRBtgWw92ibuBpQ2Kpz4I5ePs= dependencies: "@formatjs/intl-unified-numberformat" "^3.2.0" intl-messageformat@10.3.4: version "10.3.4" - resolved "https://registry.npm.alibaba-inc.com/intl-messageformat/download/intl-messageformat-10.3.4.tgz#20f064c28b46fa6d352a4c4ba5e9bfc597af3eba" + resolved "https://registry.npm.alibaba-inc.com/intl-messageformat/download/intl-messageformat-10.3.4.tgz" integrity sha512-/FxUIrlbPtuykSNX85CB5sp2FjLVeTmdD7TfRkVFPft2n4FgcSlAcilFytYiFAEmPHc+0PvpLCIPXeaGFzIvOg== dependencies: "@formatjs/ecma402-abstract" "1.14.3" @@ -5786,7 +7189,7 @@ intl-messageformat@10.3.4: intl-messageformat@^7.8.4: version "7.8.4" - resolved "https://registry.npm.alibaba-inc.com/intl-messageformat/download/intl-messageformat-7.8.4.tgz#c29146a06b9cd26662978a4d95fff2b133e3642f" + resolved "https://registry.npm.alibaba-inc.com/intl-messageformat/download/intl-messageformat-7.8.4.tgz" integrity sha1-wpFGoGuc0mZil4pNlf/ysTPjZC8= dependencies: intl-format-cache "^4.2.21" @@ -5794,75 +7197,94 @@ intl-messageformat@^7.8.4: intl@1.2.5: version "1.2.5" - resolved "https://registry.npm.alibaba-inc.com/intl/download/intl-1.2.5.tgz#82244a2190c4e419f8371f5aa34daa3420e2abde" + resolved "https://registry.npm.alibaba-inc.com/intl/download/intl-1.2.5.tgz" integrity sha1-giRKIZDE5Bn4Nx9ao02qNCDiq94= invariant@^2.2.1, invariant@^2.2.4: version "2.2.4" - resolved "https://registry.npm.alibaba-inc.com/invariant/download/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + resolved "https://registry.npm.alibaba-inc.com/invariant/download/invariant-2.2.4.tgz" integrity sha1-YQ88ksk1nOHbYW5TgAjSP/NRWOY= dependencies: loose-envify "^1.0.0" invert-kv@^3.0.0: version "3.0.1" - resolved "https://registry.npm.alibaba-inc.com/invert-kv/download/invert-kv-3.0.1.tgz#a93c7a3d4386a1dc8325b97da9bb1620c0282523" + resolved "https://registry.npm.alibaba-inc.com/invert-kv/download/invert-kv-3.0.1.tgz" integrity sha1-qTx6PUOGodyDJbl9qbsWIMAoJSM= irregular-plurals@^3.2.0: version "3.3.0" - resolved "https://registry.npm.alibaba-inc.com/irregular-plurals/download/irregular-plurals-3.3.0.tgz#67d0715d4361a60d9fd9ee80af3881c631a31ee2" + resolved "https://registry.npm.alibaba-inc.com/irregular-plurals/download/irregular-plurals-3.3.0.tgz" integrity sha1-Z9BxXUNhpg2f2e6ArziBxjGjHuI= is-accessor-descriptor@^0.1.6: version "0.1.6" - resolved "https://registry.npm.alibaba-inc.com/is-accessor-descriptor/download/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + resolved "https://registry.npm.alibaba-inc.com/is-accessor-descriptor/download/is-accessor-descriptor-0.1.6.tgz" integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= dependencies: kind-of "^3.0.2" is-accessor-descriptor@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + resolved "https://registry.npm.alibaba-inc.com/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz" integrity sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY= dependencies: kind-of "^6.0.0" is-alphabetical@^1.0.0: version "1.0.4" - resolved "https://registry.npm.alibaba-inc.com/is-alphabetical/download/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" + resolved "https://registry.npm.alibaba-inc.com/is-alphabetical/download/is-alphabetical-1.0.4.tgz" integrity sha1-nn1rlJFr4iFTdF0YTCmMv5hqaG0= is-alphanumerical@^1.0.0: version "1.0.4" - resolved "https://registry.npm.alibaba-inc.com/is-alphanumerical/download/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" + resolved "https://registry.npm.alibaba-inc.com/is-alphanumerical/download/is-alphanumerical-1.0.4.tgz" integrity sha1-frmiQx+FX2se8aeOMm31FWlsTb8= dependencies: is-alphabetical "^1.0.0" is-decimal "^1.0.0" +is-any-array@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/is-any-array/-/is-any-array-2.0.1.tgz" + integrity sha512-UtilS7hLRu++wb/WBAw9bNuP1Eg04Ivn1vERJck8zJthEvXCBEBpGR/33u/xLKWEQf95803oalHrVDptcAvFdQ== + +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz" + integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + is-typed-array "^1.1.10" + is-arrayish@^0.2.1: version "0.2.1" - resolved "https://registry.npm.alibaba-inc.com/is-arrayish/download/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + resolved "https://registry.npm.alibaba-inc.com/is-arrayish/download/is-arrayish-0.2.1.tgz" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + is-bigint@^1.0.1: version "1.0.4" - resolved "https://registry.npm.alibaba-inc.com/is-bigint/download/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + resolved "https://registry.npm.alibaba-inc.com/is-bigint/download/is-bigint-1.0.4.tgz" integrity sha1-CBR6GHW8KzIAXUHM2Ckd/8ZpHfM= dependencies: has-bigints "^1.0.1" is-binary-path@~2.1.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/is-binary-path/download/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + resolved "https://registry.npm.alibaba-inc.com/is-binary-path/download/is-binary-path-2.1.0.tgz" integrity sha1-6h9/O4DwZCNug0cPhsCcJU+0Wwk= dependencies: binary-extensions "^2.0.0" is-boolean-object@^1.1.0: version "1.1.2" - resolved "https://registry.npm.alibaba-inc.com/is-boolean-object/download/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + resolved "https://registry.npm.alibaba-inc.com/is-boolean-object/download/is-boolean-object-1.1.2.tgz" integrity sha1-XG3CACRt2TIa5LiFoRS7H3X2Nxk= dependencies: call-bind "^1.0.2" @@ -5870,69 +7292,69 @@ is-boolean-object@^1.1.0: is-buffer@^1.1.5: version "1.1.6" - resolved "https://registry.npm.alibaba-inc.com/is-buffer/download/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + resolved "https://registry.npm.alibaba-inc.com/is-buffer/download/is-buffer-1.1.6.tgz" integrity sha1-76ouqdqg16suoTqXsritUf776L4= is-buffer@^2.0.0: version "2.0.5" - resolved "https://registry.npm.alibaba-inc.com/is-buffer/download/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + resolved "https://registry.npm.alibaba-inc.com/is-buffer/download/is-buffer-2.0.5.tgz" integrity sha1-68JS5ADSL/jXf6CYiIIaJKZYwZE= -is-callable@^1.1.4, is-callable@^1.2.7: +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: version "1.2.7" - resolved "https://registry.npm.alibaba-inc.com/is-callable/download/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + resolved "https://registry.npm.alibaba-inc.com/is-callable/download/is-callable-1.2.7.tgz" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== is-ci@^1.0.10: version "1.2.1" - resolved "https://registry.npm.alibaba-inc.com/is-ci/download/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" + resolved "https://registry.npm.alibaba-inc.com/is-ci/download/is-ci-1.2.1.tgz" integrity sha1-43ecjuF/zPQoSI9uKBGH8uYyhBw= dependencies: ci-info "^1.5.0" is-ci@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/is-ci/download/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + resolved "https://registry.npm.alibaba-inc.com/is-ci/download/is-ci-2.0.0.tgz" integrity sha1-a8YzQYGBDgS1wis9WJ/cpVAmQEw= dependencies: ci-info "^2.0.0" is-core-module@^2.5.0, is-core-module@^2.9.0: version "2.11.0" - resolved "https://registry.npm.alibaba-inc.com/is-core-module/download/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + resolved "https://registry.npm.alibaba-inc.com/is-core-module/download/is-core-module-2.11.0.tgz" integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== dependencies: has "^1.0.3" is-data-descriptor@^0.1.4: version "0.1.4" - resolved "https://registry.npm.alibaba-inc.com/is-data-descriptor/download/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + resolved "https://registry.npm.alibaba-inc.com/is-data-descriptor/download/is-data-descriptor-0.1.4.tgz" integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= dependencies: kind-of "^3.0.2" is-data-descriptor@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + resolved "https://registry.npm.alibaba-inc.com/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz" integrity sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc= dependencies: kind-of "^6.0.0" is-date-object@^1.0.1: version "1.0.5" - resolved "https://registry.npm.alibaba-inc.com/is-date-object/download/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + resolved "https://registry.npm.alibaba-inc.com/is-date-object/download/is-date-object-1.0.5.tgz" integrity sha1-CEHVU25yTCVZe/bqYuG9OCmN8x8= dependencies: has-tostringtag "^1.0.0" is-decimal@^1.0.0: version "1.0.4" - resolved "https://registry.npm.alibaba-inc.com/is-decimal/download/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" + resolved "https://registry.npm.alibaba-inc.com/is-decimal/download/is-decimal-1.0.4.tgz" integrity sha1-ZaOllYocW2OnBuGzM9fNn2MNP6U= is-descriptor@^0.1.0: version "0.1.6" - resolved "https://registry.npm.alibaba-inc.com/is-descriptor/download/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + resolved "https://registry.npm.alibaba-inc.com/is-descriptor/download/is-descriptor-0.1.6.tgz" integrity sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco= dependencies: is-accessor-descriptor "^0.1.6" @@ -5941,7 +7363,7 @@ is-descriptor@^0.1.0: is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/is-descriptor/download/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + resolved "https://registry.npm.alibaba-inc.com/is-descriptor/download/is-descriptor-1.0.2.tgz" integrity sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw= dependencies: is-accessor-descriptor "^1.0.0" @@ -5950,117 +7372,124 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-directory@^0.3.1: version "0.3.1" - resolved "https://registry.npm.alibaba-inc.com/is-directory/download/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + resolved "https://registry.npm.alibaba-inc.com/is-directory/download/is-directory-0.3.1.tgz" integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= is-docker@^2.0.0: version "2.2.1" - resolved "https://registry.npm.alibaba-inc.com/is-docker/download/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + resolved "https://registry.npm.alibaba-inc.com/is-docker/download/is-docker-2.2.1.tgz" integrity sha1-M+6r4jz+hvFL3kQIoCwM+4U6zao= is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" - resolved "https://registry.npm.alibaba-inc.com/is-extendable/download/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + resolved "https://registry.npm.alibaba-inc.com/is-extendable/download/is-extendable-0.1.1.tgz" integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= is-extendable@^1.0.1: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/is-extendable/download/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + resolved "https://registry.npm.alibaba-inc.com/is-extendable/download/is-extendable-1.0.1.tgz" integrity sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ= dependencies: is-plain-object "^2.0.4" -is-extglob@^2.1.1: +is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.npm.alibaba-inc.com/is-extglob/download/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + resolved "https://registry.npm.alibaba-inc.com/is-extglob/download/is-extglob-2.1.1.tgz" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-fullwidth-code-point@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/is-fullwidth-code-point/download/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + resolved "https://registry.npm.alibaba-inc.com/is-fullwidth-code-point/download/is-fullwidth-code-point-3.0.0.tgz" integrity sha1-8Rb4Bk/pCz94RKOJl8C3UFEmnx0= is-function@^1.0.1: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/is-function/download/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" + resolved "https://registry.npm.alibaba-inc.com/is-function/download/is-function-1.0.2.tgz" integrity sha1-Twl/MKv2762smDOxfKXcA/gUTgg= is-generator-fn@^2.0.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/is-generator-fn/download/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + resolved "https://registry.npm.alibaba-inc.com/is-generator-fn/download/is-generator-fn-2.1.0.tgz" integrity sha1-fRQK3DiarzARqPKipM+m+q3/sRg= +is-glob@^3.0.0, is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz" + integrity sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw== + dependencies: + is-extglob "^2.1.0" + is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" - resolved "https://registry.npm.alibaba-inc.com/is-glob/download/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + resolved "https://registry.npm.alibaba-inc.com/is-glob/download/is-glob-4.0.3.tgz" integrity sha1-ZPYeQsu7LuwgcanawLKLoeZdUIQ= dependencies: is-extglob "^2.1.1" is-hexadecimal@^1.0.0: version "1.0.4" - resolved "https://registry.npm.alibaba-inc.com/is-hexadecimal/download/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" + resolved "https://registry.npm.alibaba-inc.com/is-hexadecimal/download/is-hexadecimal-1.0.4.tgz" integrity sha1-zDXJdYjaS9Saju3WvECC1E3LI6c= is-negative-zero@^2.0.2: version "2.0.2" - resolved "https://registry.npm.alibaba-inc.com/is-negative-zero/download/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + resolved "https://registry.npm.alibaba-inc.com/is-negative-zero/download/is-negative-zero-2.0.2.tgz" integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== is-number-object@^1.0.4: version "1.0.7" - resolved "https://registry.npm.alibaba-inc.com/is-number-object/download/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + resolved "https://registry.npm.alibaba-inc.com/is-number-object/download/is-number-object-1.0.7.tgz" integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== dependencies: has-tostringtag "^1.0.0" is-number@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/is-number/download/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + resolved "https://registry.npm.alibaba-inc.com/is-number/download/is-number-3.0.0.tgz" integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= dependencies: kind-of "^3.0.2" is-number@^7.0.0: version "7.0.0" - resolved "https://registry.npm.alibaba-inc.com/is-number/download/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + resolved "https://registry.npm.alibaba-inc.com/is-number/download/is-number-7.0.0.tgz" integrity sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss= is-obj@^1.0.1: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/is-obj/download/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + resolved "https://registry.npm.alibaba-inc.com/is-obj/download/is-obj-1.0.1.tgz" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= is-plain-obj@2.1.0, is-plain-obj@^2.0.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/is-plain-obj/download/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + resolved "https://registry.npm.alibaba-inc.com/is-plain-obj/download/is-plain-obj-2.1.0.tgz" integrity sha1-ReQuN/zPH0Dajl927iFRWEDAkoc= is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/is-plain-obj/download/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + resolved "https://registry.npm.alibaba-inc.com/is-plain-obj/download/is-plain-obj-1.1.0.tgz" integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" - resolved "https://registry.npm.alibaba-inc.com/is-plain-object/download/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + resolved "https://registry.npm.alibaba-inc.com/is-plain-object/download/is-plain-object-2.0.4.tgz" integrity sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc= dependencies: isobject "^3.0.1" is-potential-custom-element-name@^1.0.1: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/is-potential-custom-element-name/download/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + resolved "https://registry.npm.alibaba-inc.com/is-potential-custom-element-name/download/is-potential-custom-element-name-1.0.1.tgz" integrity sha1-Fx7W8Z46xVQ5Tt94yqBXhKRb67U= is-promise@^2.2.2: version "2.2.2" - resolved "https://registry.npm.alibaba-inc.com/is-promise/download/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" + resolved "https://registry.npm.alibaba-inc.com/is-promise/download/is-promise-2.2.2.tgz" integrity sha1-OauVnMv5p3TPB597QMeib3YxNfE= is-regex@^1.1.4: version "1.1.4" - resolved "https://registry.npm.alibaba-inc.com/is-regex/download/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + resolved "https://registry.npm.alibaba-inc.com/is-regex/download/is-regex-1.1.4.tgz" integrity sha1-7vVmPNWfpMCuM5UFMj32hUuxWVg= dependencies: call-bind "^1.0.2" @@ -6068,104 +7497,121 @@ is-regex@^1.1.4: is-regexp@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/is-regexp/download/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" + resolved "https://registry.npm.alibaba-inc.com/is-regexp/download/is-regexp-1.0.0.tgz" integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= is-regexp@^2.0.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/is-regexp/download/is-regexp-2.1.0.tgz#cd734a56864e23b956bf4e7c66c396a4c0b22c2d" + resolved "https://registry.npm.alibaba-inc.com/is-regexp/download/is-regexp-2.1.0.tgz" integrity sha1-zXNKVoZOI7lWv058ZsOWpMCyLC0= is-shared-array-buffer@^1.0.2: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/is-shared-array-buffer/download/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + resolved "https://registry.npm.alibaba-inc.com/is-shared-array-buffer/download/is-shared-array-buffer-1.0.2.tgz" integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== dependencies: call-bind "^1.0.2" is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/is-stream/download/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + resolved "https://registry.npm.alibaba-inc.com/is-stream/download/is-stream-1.1.0.tgz" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= is-stream@^2.0.0: version "2.0.1" - resolved "https://registry.npm.alibaba-inc.com/is-stream/download/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + resolved "https://registry.npm.alibaba-inc.com/is-stream/download/is-stream-2.0.1.tgz" integrity sha1-+sHj1TuXrVqdCunO8jifWBClwHc= is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" - resolved "https://registry.npm.alibaba-inc.com/is-string/download/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + resolved "https://registry.npm.alibaba-inc.com/is-string/download/is-string-1.0.7.tgz" integrity sha1-DdEr8gBvJVu1j2lREO/3SR7rwP0= dependencies: has-tostringtag "^1.0.0" is-symbol@^1.0.2, is-symbol@^1.0.3: version "1.0.4" - resolved "https://registry.npm.alibaba-inc.com/is-symbol/download/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + resolved "https://registry.npm.alibaba-inc.com/is-symbol/download/is-symbol-1.0.4.tgz" integrity sha1-ptrJO2NbBjymhyI23oiRClevE5w= dependencies: has-symbols "^1.0.2" +is-typed-array@^1.1.10, is-typed-array@^1.1.9: + version "1.1.12" + resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz" + integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== + dependencies: + which-typed-array "^1.1.11" + is-typedarray@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/is-typedarray/download/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + resolved "https://registry.npm.alibaba-inc.com/is-typedarray/download/is-typedarray-1.0.0.tgz" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= is-unicode-supported@^0.1.0: version "0.1.0" - resolved "https://registry.npm.alibaba-inc.com/is-unicode-supported/download/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + resolved "https://registry.npm.alibaba-inc.com/is-unicode-supported/download/is-unicode-supported-0.1.0.tgz" integrity sha1-PybHaoCVk7Ur+i7LVxDtJ3m1Iqc= +is-url@^1.2.4: + version "1.2.4" + resolved "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + is-weakref@^1.0.2: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/is-weakref/download/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + resolved "https://registry.npm.alibaba-inc.com/is-weakref/download/is-weakref-1.0.2.tgz" integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== dependencies: call-bind "^1.0.2" is-windows@^1.0.2: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/is-windows/download/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + resolved "https://registry.npm.alibaba-inc.com/is-windows/download/is-windows-1.0.2.tgz" integrity sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0= is-wsl@^2.1.1, is-wsl@^2.2.0: version "2.2.0" - resolved "https://registry.npm.alibaba-inc.com/is-wsl/download/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + resolved "https://registry.npm.alibaba-inc.com/is-wsl/download/is-wsl-2.2.0.tgz" integrity sha1-dKTHbnfKn9P5MvKQwX6jJs0VcnE= dependencies: is-docker "^2.0.0" isarray@0.0.1: version "0.0.1" - resolved "https://registry.npm.alibaba-inc.com/isarray/download/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + resolved "https://registry.npm.alibaba-inc.com/isarray/download/isarray-0.0.1.tgz" integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/isarray/download/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + resolved "https://registry.npm.alibaba-inc.com/isarray/download/isarray-1.0.0.tgz" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + isexe@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/isexe/download/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + resolved "https://registry.npm.alibaba-inc.com/isexe/download/isexe-2.0.0.tgz" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= isobject@^2.0.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/isobject/download/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + resolved "https://registry.npm.alibaba-inc.com/isobject/download/isobject-2.1.0.tgz" integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" - resolved "https://registry.npm.alibaba-inc.com/isobject/download/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + resolved "https://registry.npm.alibaba-inc.com/isobject/download/isobject-3.0.1.tgz" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= isomorphic-fetch@^2.1.1, isomorphic-fetch@^2.2.1: version "2.2.1" - resolved "https://registry.npm.alibaba-inc.com/isomorphic-fetch/download/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" + resolved "https://registry.npm.alibaba-inc.com/isomorphic-fetch/download/isomorphic-fetch-2.2.1.tgz" integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk= dependencies: node-fetch "^1.0.1" @@ -6173,12 +7619,12 @@ isomorphic-fetch@^2.1.1, isomorphic-fetch@^2.2.1: istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: version "3.2.0" - resolved "https://registry.npm.alibaba-inc.com/istanbul-lib-coverage/download/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + resolved "https://registry.npm.alibaba-inc.com/istanbul-lib-coverage/download/istanbul-lib-coverage-3.2.0.tgz" integrity sha1-GJ55CdCjn6Wj361bA/cZR3cBkdM= istanbul-lib-instrument@^4.0.3: version "4.0.3" - resolved "https://registry.npm.alibaba-inc.com/istanbul-lib-instrument/download/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + resolved "https://registry.npm.alibaba-inc.com/istanbul-lib-instrument/download/istanbul-lib-instrument-4.0.3.tgz" integrity sha1-hzxv/4l0UBGCIndGlqPyiQLXfB0= dependencies: "@babel/core" "^7.7.5" @@ -6188,7 +7634,7 @@ istanbul-lib-instrument@^4.0.3: istanbul-lib-instrument@^5.0.4: version "5.2.1" - resolved "https://registry.npm.alibaba-inc.com/istanbul-lib-instrument/download/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + resolved "https://registry.npm.alibaba-inc.com/istanbul-lib-instrument/download/istanbul-lib-instrument-5.2.1.tgz" integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== dependencies: "@babel/core" "^7.12.3" @@ -6199,7 +7645,7 @@ istanbul-lib-instrument@^5.0.4: istanbul-lib-report@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/istanbul-lib-report/download/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + resolved "https://registry.npm.alibaba-inc.com/istanbul-lib-report/download/istanbul-lib-report-3.0.0.tgz" integrity sha1-dRj+UupE3jcvRgp2tezan/tz2KY= dependencies: istanbul-lib-coverage "^3.0.0" @@ -6208,7 +7654,7 @@ istanbul-lib-report@^3.0.0: istanbul-lib-source-maps@^4.0.0: version "4.0.1" - resolved "https://registry.npm.alibaba-inc.com/istanbul-lib-source-maps/download/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + resolved "https://registry.npm.alibaba-inc.com/istanbul-lib-source-maps/download/istanbul-lib-source-maps-4.0.1.tgz" integrity sha1-iV86cJ/PujTG3lpCk5Ai8+Q1hVE= dependencies: debug "^4.1.1" @@ -6217,7 +7663,7 @@ istanbul-lib-source-maps@^4.0.0: istanbul-reports@^3.0.2: version "3.1.5" - resolved "https://registry.npm.alibaba-inc.com/istanbul-reports/download/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" + resolved "https://registry.npm.alibaba-inc.com/istanbul-reports/download/istanbul-reports-3.1.5.tgz" integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== dependencies: html-escaper "^2.0.0" @@ -6225,12 +7671,12 @@ istanbul-reports@^3.0.2: javascript-stringify@^2.0.1: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/javascript-stringify/download/javascript-stringify-2.1.0.tgz#27c76539be14d8bd128219a2d731b09337904e79" + resolved "https://registry.npm.alibaba-inc.com/javascript-stringify/download/javascript-stringify-2.1.0.tgz" integrity sha1-J8dlOb4U2L0Sghmi1zGwkzeQTnk= jest-changed-files@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/jest-changed-files/download/jest-changed-files-26.6.2.tgz#f6198479e1cc66f22f9ae1e22acaa0b429c042d0" + resolved "https://registry.npm.alibaba-inc.com/jest-changed-files/download/jest-changed-files-26.6.2.tgz" integrity sha1-9hmEeeHMZvIvmuHiKsqgtCnAQtA= dependencies: "@jest/types" "^26.6.2" @@ -6239,7 +7685,7 @@ jest-changed-files@^26.6.2: jest-cli@^26.6.3: version "26.6.3" - resolved "https://registry.npm.alibaba-inc.com/jest-cli/download/jest-cli-26.6.3.tgz#43117cfef24bc4cd691a174a8796a532e135e92a" + resolved "https://registry.npm.alibaba-inc.com/jest-cli/download/jest-cli-26.6.3.tgz" integrity sha1-QxF8/vJLxM1pGhdKh5alMuE16So= dependencies: "@jest/core" "^26.6.3" @@ -6258,7 +7704,7 @@ jest-cli@^26.6.3: jest-config@^26.6.3: version "26.6.3" - resolved "https://registry.npm.alibaba-inc.com/jest-config/download/jest-config-26.6.3.tgz#64f41444eef9eb03dc51d5c53b75c8c71f645349" + resolved "https://registry.npm.alibaba-inc.com/jest-config/download/jest-config-26.6.3.tgz" integrity sha1-ZPQURO756wPcUdXFO3XIxx9kU0k= dependencies: "@babel/core" "^7.1.0" @@ -6282,7 +7728,7 @@ jest-config@^26.6.3: jest-diff@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/jest-diff/download/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" + resolved "https://registry.npm.alibaba-inc.com/jest-diff/download/jest-diff-26.6.2.tgz" integrity sha1-GqdGi1LDpo19XF/c381eSb0WQ5Q= dependencies: chalk "^4.0.0" @@ -6292,14 +7738,14 @@ jest-diff@^26.6.2: jest-docblock@^26.0.0: version "26.0.0" - resolved "https://registry.npm.alibaba-inc.com/jest-docblock/download/jest-docblock-26.0.0.tgz#3e2fa20899fc928cb13bd0ff68bd3711a36889b5" + resolved "https://registry.npm.alibaba-inc.com/jest-docblock/download/jest-docblock-26.0.0.tgz" integrity sha1-Pi+iCJn8koyxO9D/aL03EaNoibU= dependencies: detect-newline "^3.0.0" jest-each@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/jest-each/download/jest-each-26.6.2.tgz#02526438a77a67401c8a6382dfe5999952c167cb" + resolved "https://registry.npm.alibaba-inc.com/jest-each/download/jest-each-26.6.2.tgz" integrity sha1-AlJkOKd6Z0AcimOC3+WZmVLBZ8s= dependencies: "@jest/types" "^26.6.2" @@ -6310,7 +7756,7 @@ jest-each@^26.6.2: jest-environment-jsdom@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/jest-environment-jsdom/download/jest-environment-jsdom-26.6.2.tgz#78d09fe9cf019a357009b9b7e1f101d23bd1da3e" + resolved "https://registry.npm.alibaba-inc.com/jest-environment-jsdom/download/jest-environment-jsdom-26.6.2.tgz" integrity sha1-eNCf6c8BmjVwCbm34fEB0jvR2j4= dependencies: "@jest/environment" "^26.6.2" @@ -6323,7 +7769,7 @@ jest-environment-jsdom@^26.6.2: jest-environment-node@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/jest-environment-node/download/jest-environment-node-26.6.2.tgz#824e4c7fb4944646356f11ac75b229b0035f2b0c" + resolved "https://registry.npm.alibaba-inc.com/jest-environment-node/download/jest-environment-node-26.6.2.tgz" integrity sha1-gk5Mf7SURkY1bxGsdbIpsANfKww= dependencies: "@jest/environment" "^26.6.2" @@ -6335,12 +7781,12 @@ jest-environment-node@^26.6.2: jest-get-type@^26.3.0: version "26.3.0" - resolved "https://registry.npm.alibaba-inc.com/jest-get-type/download/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" + resolved "https://registry.npm.alibaba-inc.com/jest-get-type/download/jest-get-type-26.3.0.tgz" integrity sha1-6X3Dw/U8K0Bsp6+u1Ek7HQmRmeA= jest-haste-map@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/jest-haste-map/download/jest-haste-map-26.6.2.tgz#dd7e60fe7dc0e9f911a23d79c5ff7fb5c2cafeaa" + resolved "https://registry.npm.alibaba-inc.com/jest-haste-map/download/jest-haste-map-26.6.2.tgz" integrity sha1-3X5g/n3A6fkRoj15xf9/tcLK/qo= dependencies: "@jest/types" "^26.6.2" @@ -6361,7 +7807,7 @@ jest-haste-map@^26.6.2: jest-jasmine2@^26.6.3: version "26.6.3" - resolved "https://registry.npm.alibaba-inc.com/jest-jasmine2/download/jest-jasmine2-26.6.3.tgz#adc3cf915deacb5212c93b9f3547cd12958f2edd" + resolved "https://registry.npm.alibaba-inc.com/jest-jasmine2/download/jest-jasmine2-26.6.3.tgz" integrity sha1-rcPPkV3qy1ISyTufNUfNEpWPLt0= dependencies: "@babel/traverse" "^7.1.0" @@ -6385,7 +7831,7 @@ jest-jasmine2@^26.6.3: jest-leak-detector@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/jest-leak-detector/download/jest-leak-detector-26.6.2.tgz#7717cf118b92238f2eba65054c8a0c9c653a91af" + resolved "https://registry.npm.alibaba-inc.com/jest-leak-detector/download/jest-leak-detector-26.6.2.tgz" integrity sha1-dxfPEYuSI48uumUFTIoMnGU6ka8= dependencies: jest-get-type "^26.3.0" @@ -6393,7 +7839,7 @@ jest-leak-detector@^26.6.2: jest-matcher-utils@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/jest-matcher-utils/download/jest-matcher-utils-26.6.2.tgz#8e6fd6e863c8b2d31ac6472eeb237bc595e53e7a" + resolved "https://registry.npm.alibaba-inc.com/jest-matcher-utils/download/jest-matcher-utils-26.6.2.tgz" integrity sha1-jm/W6GPIstMaxkcu6yN7xZXlPno= dependencies: chalk "^4.0.0" @@ -6403,7 +7849,7 @@ jest-matcher-utils@^26.6.2: jest-message-util@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/jest-message-util/download/jest-message-util-26.6.2.tgz#58173744ad6fc0506b5d21150b9be56ef001ca07" + resolved "https://registry.npm.alibaba-inc.com/jest-message-util/download/jest-message-util-26.6.2.tgz" integrity sha1-WBc3RK1vwFBrXSEVC5vlbvABygc= dependencies: "@babel/code-frame" "^7.0.0" @@ -6418,7 +7864,7 @@ jest-message-util@^26.6.2: jest-mock@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/jest-mock/download/jest-mock-26.6.2.tgz#d6cb712b041ed47fe0d9b6fc3474bc6543feb302" + resolved "https://registry.npm.alibaba-inc.com/jest-mock/download/jest-mock-26.6.2.tgz" integrity sha1-1stxKwQe1H/g2bb8NHS8ZUP+swI= dependencies: "@jest/types" "^26.6.2" @@ -6426,17 +7872,17 @@ jest-mock@^26.6.2: jest-pnp-resolver@^1.2.2: version "1.2.3" - resolved "https://registry.npm.alibaba-inc.com/jest-pnp-resolver/download/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + resolved "https://registry.npm.alibaba-inc.com/jest-pnp-resolver/download/jest-pnp-resolver-1.2.3.tgz" integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== jest-regex-util@^26.0.0: version "26.0.0" - resolved "https://registry.npm.alibaba-inc.com/jest-regex-util/download/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" + resolved "https://registry.npm.alibaba-inc.com/jest-regex-util/download/jest-regex-util-26.0.0.tgz" integrity sha1-0l5xhLNuOf1GbDvEG+CXHoIf7ig= jest-resolve-dependencies@^26.6.3: version "26.6.3" - resolved "https://registry.npm.alibaba-inc.com/jest-resolve-dependencies/download/jest-resolve-dependencies-26.6.3.tgz#6680859ee5d22ee5dcd961fe4871f59f4c784fb6" + resolved "https://registry.npm.alibaba-inc.com/jest-resolve-dependencies/download/jest-resolve-dependencies-26.6.3.tgz" integrity sha1-ZoCFnuXSLuXc2WH+SHH1n0x4T7Y= dependencies: "@jest/types" "^26.6.2" @@ -6445,7 +7891,7 @@ jest-resolve-dependencies@^26.6.3: jest-resolve@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/jest-resolve/download/jest-resolve-26.6.2.tgz#a3ab1517217f469b504f1b56603c5bb541fbb507" + resolved "https://registry.npm.alibaba-inc.com/jest-resolve/download/jest-resolve-26.6.2.tgz" integrity sha1-o6sVFyF/RptQTxtWYDxbtUH7tQc= dependencies: "@jest/types" "^26.6.2" @@ -6459,7 +7905,7 @@ jest-resolve@^26.6.2: jest-runner@^26.6.3: version "26.6.3" - resolved "https://registry.npm.alibaba-inc.com/jest-runner/download/jest-runner-26.6.3.tgz#2d1fed3d46e10f233fd1dbd3bfaa3fe8924be159" + resolved "https://registry.npm.alibaba-inc.com/jest-runner/download/jest-runner-26.6.3.tgz" integrity sha1-LR/tPUbhDyM/0dvTv6o/6JJL4Vk= dependencies: "@jest/console" "^26.6.2" @@ -6485,7 +7931,7 @@ jest-runner@^26.6.3: jest-runtime@^26.6.3: version "26.6.3" - resolved "https://registry.npm.alibaba-inc.com/jest-runtime/download/jest-runtime-26.6.3.tgz#4f64efbcfac398331b74b4b3c82d27d401b8fa2b" + resolved "https://registry.npm.alibaba-inc.com/jest-runtime/download/jest-runtime-26.6.3.tgz" integrity sha1-T2TvvPrDmDMbdLSzyC0n1AG4+is= dependencies: "@jest/console" "^26.6.2" @@ -6518,7 +7964,7 @@ jest-runtime@^26.6.3: jest-serializer@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/jest-serializer/download/jest-serializer-26.6.2.tgz#d139aafd46957d3a448f3a6cdabe2919ba0742d1" + resolved "https://registry.npm.alibaba-inc.com/jest-serializer/download/jest-serializer-26.6.2.tgz" integrity sha1-0Tmq/UaVfTpEjzps2r4pGboHQtE= dependencies: "@types/node" "*" @@ -6526,7 +7972,7 @@ jest-serializer@^26.6.2: jest-snapshot@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/jest-snapshot/download/jest-snapshot-26.6.2.tgz#f3b0af1acb223316850bd14e1beea9837fb39c84" + resolved "https://registry.npm.alibaba-inc.com/jest-snapshot/download/jest-snapshot-26.6.2.tgz" integrity sha1-87CvGssiMxaFC9FOG+6pg3+znIQ= dependencies: "@babel/types" "^7.0.0" @@ -6548,7 +7994,7 @@ jest-snapshot@^26.6.2: jest-util@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/jest-util/download/jest-util-26.6.2.tgz#907535dbe4d5a6cb4c47ac9b926f6af29576cbc1" + resolved "https://registry.npm.alibaba-inc.com/jest-util/download/jest-util-26.6.2.tgz" integrity sha1-kHU12+TVpstMR6ybkm9q8pV2y8E= dependencies: "@jest/types" "^26.6.2" @@ -6560,7 +8006,7 @@ jest-util@^26.6.2: jest-validate@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/jest-validate/download/jest-validate-26.6.2.tgz#23d380971587150467342911c3d7b4ac57ab20ec" + resolved "https://registry.npm.alibaba-inc.com/jest-validate/download/jest-validate-26.6.2.tgz" integrity sha1-I9OAlxWHFQRnNCkRw9e0rFerIOw= dependencies: "@jest/types" "^26.6.2" @@ -6572,7 +8018,7 @@ jest-validate@^26.6.2: jest-watcher@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/jest-watcher/download/jest-watcher-26.6.2.tgz#a5b683b8f9d68dbcb1d7dae32172d2cca0592975" + resolved "https://registry.npm.alibaba-inc.com/jest-watcher/download/jest-watcher-26.6.2.tgz" integrity sha1-pbaDuPnWjbyx19rjIXLSzKBZKXU= dependencies: "@jest/test-result" "^26.6.2" @@ -6585,7 +8031,7 @@ jest-watcher@^26.6.2: jest-worker@24.9.0: version "24.9.0" - resolved "https://registry.npm.alibaba-inc.com/jest-worker/download/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5" + resolved "https://registry.npm.alibaba-inc.com/jest-worker/download/jest-worker-24.9.0.tgz" integrity sha1-Xb/bWy0yLphWeJgjipaXvM5ns+U= dependencies: merge-stream "^2.0.0" @@ -6593,7 +8039,7 @@ jest-worker@24.9.0: jest-worker@26.6.2, jest-worker@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/jest-worker/download/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" + resolved "https://registry.npm.alibaba-inc.com/jest-worker/download/jest-worker-26.6.2.tgz" integrity sha1-f3LLxNZDw2Xie5/XdfnQ6qnHqO0= dependencies: "@types/node" "*" @@ -6602,21 +8048,26 @@ jest-worker@26.6.2, jest-worker@^26.6.2: jest@^26.6.3: version "26.6.3" - resolved "https://registry.npm.alibaba-inc.com/jest/download/jest-26.6.3.tgz#40e8fdbe48f00dfa1f0ce8121ca74b88ac9148ef" + resolved "https://registry.npm.alibaba-inc.com/jest/download/jest-26.6.3.tgz" integrity sha1-QOj9vkjwDfofDOgSHKdLiKyRSO8= dependencies: "@jest/core" "^26.6.3" import-local "^3.0.2" jest-cli "^26.6.3" +js-cookie@^2.2.1: + version "2.2.1" + resolved "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz" + integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/js-tokens/download/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + resolved "https://registry.npm.alibaba-inc.com/js-tokens/download/js-tokens-4.0.0.tgz" integrity sha1-GSA/tZmR35jjoocFDUZHzerzJJk= js-yaml@^3.13.1: version "3.14.1" - resolved "https://registry.npm.alibaba-inc.com/js-yaml/download/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + resolved "https://registry.npm.alibaba-inc.com/js-yaml/download/js-yaml-3.14.1.tgz" integrity sha1-2ugS/bOCX6MGYJqHFzg8UMNqBTc= dependencies: argparse "^1.0.7" @@ -6624,7 +8075,7 @@ js-yaml@^3.13.1: jsdom@^16.4.0: version "16.7.0" - resolved "https://registry.npm.alibaba-inc.com/jsdom/download/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" + resolved "https://registry.npm.alibaba-inc.com/jsdom/download/jsdom-16.7.0.tgz" integrity sha1-kYrnGWVCSxl8gZ+Bg6dU4Yl3txA= dependencies: abab "^2.0.5" @@ -6657,120 +8108,125 @@ jsdom@^16.4.0: jsesc@^2.5.1: version "2.5.2" - resolved "https://registry.npm.alibaba-inc.com/jsesc/download/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + resolved "https://registry.npm.alibaba-inc.com/jsesc/download/jsesc-2.5.2.tgz" integrity sha1-gFZNLkg9rPbo7yCWUKZ98/DCg6Q= jsesc@~0.5.0: version "0.5.0" - resolved "https://registry.npm.alibaba-inc.com/jsesc/download/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + resolved "https://registry.npm.alibaba-inc.com/jsesc/download/jsesc-0.5.0.tgz" integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= json-parse-better-errors@^1.0.1: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/json-parse-better-errors/download/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + resolved "https://registry.npm.alibaba-inc.com/json-parse-better-errors/download/json-parse-better-errors-1.0.2.tgz" integrity sha1-u4Z8+zRQ5pEHwTHRxRS6s9yLyqk= json-parse-even-better-errors@^2.3.0: version "2.3.1" - resolved "https://registry.npm.alibaba-inc.com/json-parse-even-better-errors/download/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + resolved "https://registry.npm.alibaba-inc.com/json-parse-even-better-errors/download/json-parse-even-better-errors-2.3.1.tgz" integrity sha1-fEeAWpQxmSjgV3dAXcEuH3pO4C0= json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.npm.alibaba-inc.com/json-schema-traverse/download/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + resolved "https://registry.npm.alibaba-inc.com/json-schema-traverse/download/json-schema-traverse-0.4.1.tgz" integrity sha1-afaofZUTq4u4/mO9sJecRI5oRmA= json-schema-traverse@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/json-schema-traverse/download/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + resolved "https://registry.npm.alibaba-inc.com/json-schema-traverse/download/json-schema-traverse-1.0.0.tgz" integrity sha1-rnvLNlard6c7pcSb9lTzjmtoYOI= json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/json-stable-stringify-without-jsonify/download/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + resolved "https://registry.npm.alibaba-inc.com/json-stable-stringify-without-jsonify/download/json-stable-stringify-without-jsonify-1.0.1.tgz" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= json2mq@^0.2.0: version "0.2.0" - resolved "https://registry.npm.alibaba-inc.com/json2mq/download/json2mq-0.2.0.tgz#b637bd3ba9eabe122c83e9720483aeb10d2c904a" + resolved "https://registry.npm.alibaba-inc.com/json2mq/download/json2mq-0.2.0.tgz" integrity sha1-tje9O6nqvhIsg+lyBIOusQ0skEo= dependencies: string-convert "^0.2.0" json5@^1.0.1: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/json5/download/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + resolved "https://registry.npm.alibaba-inc.com/json5/download/json5-1.0.1.tgz" integrity sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4= dependencies: minimist "^1.2.0" -json5@^2.2.1, json5@^2.2.3: +json5@^2.2.1: version "2.2.3" - resolved "https://registry.npm.alibaba-inc.com/json5/download/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + resolved "https://registry.npm.alibaba-inc.com/json5/download/json5-2.2.3.tgz" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== "jsx-ast-utils@^2.4.1 || ^3.0.0": version "3.3.3" - resolved "https://registry.npm.alibaba-inc.com/jsx-ast-utils/download/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea" + resolved "https://registry.npm.alibaba-inc.com/jsx-ast-utils/download/jsx-ast-utils-3.3.3.tgz" integrity sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw== dependencies: array-includes "^3.1.5" object.assign "^4.1.3" +junk@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz" + integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ== + keycode@^2.2.0: version "2.2.1" - resolved "https://registry.npm.alibaba-inc.com/keycode/download/keycode-2.2.1.tgz#09c23b2be0611d26117ea2501c2c391a01f39eff" + resolved "https://registry.npm.alibaba-inc.com/keycode/download/keycode-2.2.1.tgz" integrity sha1-CcI7K+BhHSYRfqJQHCw5GgHznv8= kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" - resolved "https://registry.npm.alibaba-inc.com/kind-of/download/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + resolved "https://registry.npm.alibaba-inc.com/kind-of/download/kind-of-3.2.2.tgz" integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/kind-of/download/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + resolved "https://registry.npm.alibaba-inc.com/kind-of/download/kind-of-4.0.0.tgz" integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= dependencies: is-buffer "^1.1.5" kind-of@^5.0.0: version "5.1.0" - resolved "https://registry.npm.alibaba-inc.com/kind-of/download/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + resolved "https://registry.npm.alibaba-inc.com/kind-of/download/kind-of-5.1.0.tgz" integrity sha1-cpyR4thXt6QZofmqZWhcTDP1hF0= kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" - resolved "https://registry.npm.alibaba-inc.com/kind-of/download/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + resolved "https://registry.npm.alibaba-inc.com/kind-of/download/kind-of-6.0.3.tgz" integrity sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0= kleur@^3.0.3: version "3.0.3" - resolved "https://registry.npm.alibaba-inc.com/kleur/download/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + resolved "https://registry.npm.alibaba-inc.com/kleur/download/kleur-3.0.3.tgz" integrity sha1-p5yezIbuHOP6YgbRIWxQHxR/wH4= known-css-properties@^0.21.0: version "0.21.0" - resolved "https://registry.npm.alibaba-inc.com/known-css-properties/download/known-css-properties-0.21.0.tgz#15fbd0bbb83447f3ce09d8af247ed47c68ede80d" + resolved "https://registry.npm.alibaba-inc.com/known-css-properties/download/known-css-properties-0.21.0.tgz" integrity sha1-FfvQu7g0R/POCdivJH7UfGjt6A0= lcid@^3.0.0: version "3.1.1" - resolved "https://registry.npm.alibaba-inc.com/lcid/download/lcid-3.1.1.tgz#9030ec479a058fc36b5e8243ebaac8b6ac582fd0" + resolved "https://registry.npm.alibaba-inc.com/lcid/download/lcid-3.1.1.tgz" integrity sha1-kDDsR5oFj8NrXoJD66rItqxYL9A= dependencies: invert-kv "^3.0.0" leven@^3.1.0: version "3.1.0" - resolved "https://registry.npm.alibaba-inc.com/leven/download/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + resolved "https://registry.npm.alibaba-inc.com/leven/download/leven-3.1.0.tgz" integrity sha1-d4kd6DQGTMy6gq54QrtrFKE+1/I= levn@^0.4.1: version "0.4.1" - resolved "https://registry.npm.alibaba-inc.com/levn/download/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + resolved "https://registry.npm.alibaba-inc.com/levn/download/levn-0.4.1.tgz" integrity sha1-rkViwAdHO5MqYgDUAyaN0v/8at4= dependencies: prelude-ls "^1.2.1" @@ -6778,7 +8234,7 @@ levn@^0.4.1: levn@~0.3.0: version "0.3.0" - resolved "https://registry.npm.alibaba-inc.com/levn/download/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + resolved "https://registry.npm.alibaba-inc.com/levn/download/levn-0.3.0.tgz" integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= dependencies: prelude-ls "~1.1.2" @@ -6786,12 +8242,12 @@ levn@~0.3.0: lines-and-columns@^1.1.6: version "1.2.4" - resolved "https://registry.npm.alibaba-inc.com/lines-and-columns/download/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + resolved "https://registry.npm.alibaba-inc.com/lines-and-columns/download/lines-and-columns-1.2.4.tgz" integrity sha1-7KKE910pZQeTCdwK2SVauy68FjI= lint-staged@10.5.4: version "10.5.4" - resolved "https://registry.npm.alibaba-inc.com/lint-staged/download/lint-staged-10.5.4.tgz#cd153b5f0987d2371fc1d2847a409a2fe705b665" + resolved "https://registry.npm.alibaba-inc.com/lint-staged/download/lint-staged-10.5.4.tgz" integrity sha1-zRU7XwmH0jcfwdKEekCaL+cFtmU= dependencies: chalk "^4.1.0" @@ -6812,7 +8268,7 @@ lint-staged@10.5.4: listr2@^3.2.2: version "3.14.0" - resolved "https://registry.npm.alibaba-inc.com/listr2/download/listr2-3.14.0.tgz#23101cc62e1375fd5836b248276d1d2b51fdbe9e" + resolved "https://registry.npm.alibaba-inc.com/listr2/download/listr2-3.14.0.tgz" integrity sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g== dependencies: cli-truncate "^2.1.0" @@ -6826,7 +8282,7 @@ listr2@^3.2.2: loader-utils@^1.1.0: version "1.4.2" - resolved "https://registry.npm.alibaba-inc.com/loader-utils/download/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3" + resolved "https://registry.npm.alibaba-inc.com/loader-utils/download/loader-utils-1.4.2.tgz" integrity sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg== dependencies: big.js "^5.2.2" @@ -6835,59 +8291,99 @@ loader-utils@^1.1.0: locate-path@^5.0.0: version "5.0.0" - resolved "https://registry.npm.alibaba-inc.com/locate-path/download/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + resolved "https://registry.npm.alibaba-inc.com/locate-path/download/locate-path-5.0.0.tgz" integrity sha1-Gvujlq/WdqbUJQTQpno6frn2KqA= dependencies: p-locate "^4.1.0" +lodash._reinterpolate@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz" + integrity sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA== + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + +lodash.curry@^4.0.1: + version "4.1.1" + resolved "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz" + integrity sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA== + lodash.debounce@^4.0.8: version "4.0.8" - resolved "https://registry.npm.alibaba-inc.com/lodash.debounce/download/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + resolved "https://registry.npm.alibaba-inc.com/lodash.debounce/download/lodash.debounce-4.0.8.tgz" integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= +lodash.flow@^3.3.0: + version "3.5.0" + resolved "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz" + integrity sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw== + lodash.get@^4.4.2: version "4.4.2" - resolved "https://registry.npm.alibaba-inc.com/lodash.get/download/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + resolved "https://registry.npm.alibaba-inc.com/lodash.get/download/lodash.get-4.4.2.tgz" integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= lodash.isequal@^4.5.0: version "4.5.0" - resolved "https://registry.npm.alibaba-inc.com/lodash.isequal/download/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + resolved "https://registry.npm.alibaba-inc.com/lodash.isequal/download/lodash.isequal-4.5.0.tgz" integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= lodash.merge@^4.6.2: version "4.6.2" - resolved "https://registry.npm.alibaba-inc.com/lodash.merge/download/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + resolved "https://registry.npm.alibaba-inc.com/lodash.merge/download/lodash.merge-4.6.2.tgz" integrity sha1-VYqlO0O2YeGSWgr9+japoQhf5Xo= -lodash.throttle@^4.1.1: +lodash.template@^4.5.0: + version "4.5.0" + resolved "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz" + integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.templatesettings "^4.0.0" + +lodash.templatesettings@^4.0.0: + version "4.2.0" + resolved "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz" + integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== + dependencies: + lodash._reinterpolate "^3.0.0" + +lodash.throttle@^4.1.1: version "4.1.1" - resolved "https://registry.npm.alibaba-inc.com/lodash.throttle/download/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + resolved "https://registry.npm.alibaba-inc.com/lodash.throttle/download/lodash.throttle-4.1.1.tgz" integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= lodash.tonumber@^4.0.3: version "4.0.3" - resolved "https://registry.npm.alibaba-inc.com/lodash.tonumber/download/lodash.tonumber-4.0.3.tgz#0b96b31b35672793eb7f5a63ee791f1b9e9025d9" + resolved "https://registry.npm.alibaba-inc.com/lodash.tonumber/download/lodash.tonumber-4.0.3.tgz" integrity sha1-C5azGzVnJ5Prf1pj7nkfG56QJdk= lodash.truncate@^4.4.2: version "4.4.2" - resolved "https://registry.npm.alibaba-inc.com/lodash.truncate/download/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + resolved "https://registry.npm.alibaba-inc.com/lodash.truncate/download/lodash.truncate-4.4.2.tgz" integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= +lodash.upperfirst@^4.3.1: + version "4.3.1" + resolved "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz" + integrity sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg== + lodash.zip@^4.2.0: version "4.2.0" - resolved "https://registry.npm.alibaba-inc.com/lodash.zip/download/lodash.zip-4.2.0.tgz#ec6662e4896408ed4ab6c542a3990b72cc080020" + resolved "https://registry.npm.alibaba-inc.com/lodash.zip/download/lodash.zip-4.2.0.tgz" integrity sha1-7GZi5IlkCO1KtsVCo5kLcswIACA= -lodash@^4.0.1, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: +lodash@^4.0.1, lodash@^4.16.5, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0: version "4.17.21" - resolved "https://registry.npm.alibaba-inc.com/lodash/download/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + resolved "https://registry.npm.alibaba-inc.com/lodash/download/lodash-4.17.21.tgz" integrity sha1-Z5WRxWTDv/quhFTPCz3zcMPWkRw= log-symbols@^4.0.0, log-symbols@^4.1.0: version "4.1.0" - resolved "https://registry.npm.alibaba-inc.com/log-symbols/download/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + resolved "https://registry.npm.alibaba-inc.com/log-symbols/download/log-symbols-4.1.0.tgz" integrity sha1-P727lbRoOsn8eFER55LlWNSr1QM= dependencies: chalk "^4.1.0" @@ -6895,7 +8391,7 @@ log-symbols@^4.0.0, log-symbols@^4.1.0: log-update@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/log-update/download/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" + resolved "https://registry.npm.alibaba-inc.com/log-update/download/log-update-4.0.0.tgz" integrity sha1-WJ7NNSRx8qHAxXAodUOmTf0g4KE= dependencies: ansi-escapes "^4.3.0" @@ -6905,24 +8401,29 @@ log-update@^4.0.0: longest-streak@^2.0.0: version "2.0.4" - resolved "https://registry.npm.alibaba-inc.com/longest-streak/download/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" + resolved "https://registry.npm.alibaba-inc.com/longest-streak/download/longest-streak-2.0.4.tgz" integrity sha1-uFmZV9pbXatk3uP+MW+ndFl9kOQ= loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" - resolved "https://registry.npm.alibaba-inc.com/loose-envify/download/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + resolved "https://registry.npm.alibaba-inc.com/loose-envify/download/loose-envify-1.4.0.tgz" integrity sha1-ce5R+nvkyuwaY4OffmgtgTLTDK8= dependencies: js-tokens "^3.0.0 || ^4.0.0" lottie-web@5.10.2: version "5.10.2" - resolved "https://registry.npm.alibaba-inc.com/lottie-web/download/lottie-web-5.10.2.tgz#a1c952b6734759fcd369eba73b6b7e3d9a76ce0b" + resolved "https://registry.npm.alibaba-inc.com/lottie-web/download/lottie-web-5.10.2.tgz" integrity sha512-d0PFIGiwuMsJYaF4uPo+qG8dEorlI+xFI2zrrFtE1bGO4WoLIz+NjremxEq1swpR7juR10aeOtmNh3d6G3ub0A== +lottie-web@^5.12.2: + version "5.12.2" + resolved "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz" + integrity sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg== + lru-cache@^4.0.1: version "4.1.5" - resolved "https://registry.npm.alibaba-inc.com/lru-cache/download/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + resolved "https://registry.npm.alibaba-inc.com/lru-cache/download/lru-cache-4.1.5.tgz" integrity sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80= dependencies: pseudomap "^1.0.2" @@ -6930,21 +8431,21 @@ lru-cache@^4.0.1: lru-cache@^6.0.0: version "6.0.0" - resolved "https://registry.npm.alibaba-inc.com/lru-cache/download/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + resolved "https://registry.npm.alibaba-inc.com/lru-cache/download/lru-cache-6.0.0.tgz" integrity sha1-bW/mVw69lqr5D8rR2vo7JWbbOpQ= dependencies: yallist "^4.0.0" lru-queue@^0.1.0: version "0.1.0" - resolved "https://registry.npm.alibaba-inc.com/lru-queue/download/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" + resolved "https://registry.npm.alibaba-inc.com/lru-queue/download/lru-queue-0.1.0.tgz" integrity sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM= dependencies: es5-ext "~0.10.2" m3u8-parser@4.7.1: version "4.7.1" - resolved "https://registry.npm.alibaba-inc.com/m3u8-parser/download/m3u8-parser-4.7.1.tgz#d6df2c940bb19a01112a04ccc4ff44886a945305" + resolved "https://registry.npm.alibaba-inc.com/m3u8-parser/download/m3u8-parser-4.7.1.tgz" integrity sha512-pbrQwiMiq+MmI9bl7UjtPT3AK603PV9bogNlr83uC+X9IoxqL5E4k7kU7fMQ0dpRgxgeSMygqUa0IMLQNXLBNA== dependencies: "@babel/runtime" "^7.12.5" @@ -6953,7 +8454,7 @@ m3u8-parser@4.7.1: m3u8-parser@4.8.0: version "4.8.0" - resolved "https://registry.npm.alibaba-inc.com/m3u8-parser/download/m3u8-parser-4.8.0.tgz#4a2d591fdf6f2579d12a327081198df8af83083d" + resolved "https://registry.npm.alibaba-inc.com/m3u8-parser/download/m3u8-parser-4.8.0.tgz" integrity sha512-UqA2a/Pw3liR6Df3gwxrqghCP17OpPlQj6RBPLYygf/ZSQ4MoSgvdvhvt35qV+3NaaA0FSZx93Ix+2brT1U7cA== dependencies: "@babel/runtime" "^7.12.5" @@ -6962,62 +8463,62 @@ m3u8-parser@4.8.0: make-dir@^3.0.0: version "3.1.0" - resolved "https://registry.npm.alibaba-inc.com/make-dir/download/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + resolved "https://registry.npm.alibaba-inc.com/make-dir/download/make-dir-3.1.0.tgz" integrity sha1-QV6WcEazp/HRhSd9hKpYIDcmoT8= dependencies: semver "^6.0.0" makeerror@1.0.12: version "1.0.12" - resolved "https://registry.npm.alibaba-inc.com/makeerror/download/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + resolved "https://registry.npm.alibaba-inc.com/makeerror/download/makeerror-1.0.12.tgz" integrity sha1-Pl3SB5qC6BLpg8xmEMSiyw6qgBo= dependencies: tmpl "1.0.5" map-age-cleaner@^0.1.3: version "0.1.3" - resolved "https://registry.npm.alibaba-inc.com/map-age-cleaner/download/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + resolved "https://registry.npm.alibaba-inc.com/map-age-cleaner/download/map-age-cleaner-0.1.3.tgz" integrity sha1-fVg6cwZDTAVf5HSw9FB45uG0uSo= dependencies: p-defer "^1.0.0" map-cache@^0.2.2: version "0.2.2" - resolved "https://registry.npm.alibaba-inc.com/map-cache/download/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + resolved "https://registry.npm.alibaba-inc.com/map-cache/download/map-cache-0.2.2.tgz" integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= map-obj@^1.0.0: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/map-obj/download/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + resolved "https://registry.npm.alibaba-inc.com/map-obj/download/map-obj-1.0.1.tgz" integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= map-obj@^4.0.0: version "4.3.0" - resolved "https://registry.npm.alibaba-inc.com/map-obj/download/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" + resolved "https://registry.npm.alibaba-inc.com/map-obj/download/map-obj-4.3.0.tgz" integrity sha1-kwT5Buk/qucIgNoQKp8d8OqLsFo= map-visit@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/map-visit/download/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + resolved "https://registry.npm.alibaba-inc.com/map-visit/download/map-visit-1.0.0.tgz" integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= dependencies: object-visit "^1.0.0" matchmediaquery@^0.3.0: version "0.3.1" - resolved "https://registry.npm.alibaba-inc.com/matchmediaquery/download/matchmediaquery-0.3.1.tgz#8247edc47e499ebb7c58f62a9ff9ccf5b815c6d7" + resolved "https://registry.npm.alibaba-inc.com/matchmediaquery/download/matchmediaquery-0.3.1.tgz" integrity sha1-gkftxH5Jnrt8WPYqn/nM9bgVxtc= dependencies: css-mediaquery "^0.1.2" mathml-tag-names@^2.1.3: version "2.1.3" - resolved "https://registry.npm.alibaba-inc.com/mathml-tag-names/download/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" + resolved "https://registry.npm.alibaba-inc.com/mathml-tag-names/download/mathml-tag-names-2.1.3.tgz" integrity sha1-TdrdZzCOeAzxakdoWHjuJ7c2oKM= md5.js@^1.3.4: version "1.3.5" - resolved "https://registry.npm.alibaba-inc.com/md5.js/download/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + resolved "https://registry.npm.alibaba-inc.com/md5.js/download/md5.js-1.3.5.tgz" integrity sha1-tdB7jjIW4+J81yjXL3DR5qNCAF8= dependencies: hash-base "^3.0.0" @@ -7026,7 +8527,7 @@ md5.js@^1.3.4: mdast-util-from-markdown@^0.8.0: version "0.8.5" - resolved "https://registry.npm.alibaba-inc.com/mdast-util-from-markdown/download/mdast-util-from-markdown-0.8.5.tgz#d1ef2ca42bc377ecb0463a987910dae89bd9a28c" + resolved "https://registry.npm.alibaba-inc.com/mdast-util-from-markdown/download/mdast-util-from-markdown-0.8.5.tgz" integrity sha1-0e8spCvDd+ywRjqYeRDa6JvZoow= dependencies: "@types/mdast" "^3.0.0" @@ -7037,7 +8538,7 @@ mdast-util-from-markdown@^0.8.0: mdast-util-to-markdown@^0.6.0: version "0.6.5" - resolved "https://registry.npm.alibaba-inc.com/mdast-util-to-markdown/download/mdast-util-to-markdown-0.6.5.tgz#b33f67ca820d69e6cc527a93d4039249b504bebe" + resolved "https://registry.npm.alibaba-inc.com/mdast-util-to-markdown/download/mdast-util-to-markdown-0.6.5.tgz" integrity sha1-sz9nyoINaebMUnqT1AOSSbUEvr4= dependencies: "@types/unist" "^2.0.0" @@ -7049,12 +8550,22 @@ mdast-util-to-markdown@^0.6.0: mdast-util-to-string@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/mdast-util-to-string/download/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" + resolved "https://registry.npm.alibaba-inc.com/mdast-util-to-string/download/mdast-util-to-string-2.0.0.tgz" integrity sha1-uM/mpxPhCRy1tyj8SIhaR2f4uXs= +mdn-data@2.0.14: + version "2.0.14" + resolved "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz" + integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== + +mdn-data@2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz" + integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== + mem@^5.0.0: version "5.1.1" - resolved "https://registry.npm.alibaba-inc.com/mem/download/mem-5.1.1.tgz#7059b67bf9ac2c924c9f1cff7155a064394adfb3" + resolved "https://registry.npm.alibaba-inc.com/mem/download/mem-5.1.1.tgz" integrity sha1-cFm2e/msLJJMnxz/cVWgZDlK37M= dependencies: map-age-cleaner "^0.1.3" @@ -7063,12 +8574,12 @@ mem@^5.0.0: memoize-one@^5.1.1: version "5.2.1" - resolved "https://registry.npm.alibaba-inc.com/memoize-one/download/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" + resolved "https://registry.npm.alibaba-inc.com/memoize-one/download/memoize-one-5.2.1.tgz" integrity sha1-gzeqPEM1WBg57AHD1ZQJDOvo8A4= memoizee@^0.4.15: version "0.4.15" - resolved "https://registry.npm.alibaba-inc.com/memoizee/download/memoizee-0.4.15.tgz#e6f3d2da863f318d02225391829a6c5956555b72" + resolved "https://registry.npm.alibaba-inc.com/memoizee/download/memoizee-0.4.15.tgz" integrity sha1-5vPS2oY/MY0CIlORgppsWVZVW3I= dependencies: d "^1.0.1" @@ -7082,7 +8593,7 @@ memoizee@^0.4.15: meow@^9.0.0: version "9.0.0" - resolved "https://registry.npm.alibaba-inc.com/meow/download/meow-9.0.0.tgz#cd9510bc5cac9dee7d03c73ee1f9ad959f4ea364" + resolved "https://registry.npm.alibaba-inc.com/meow/download/meow-9.0.0.tgz" integrity sha1-zZUQvFysne59A8c+4fmtlZ9Oo2Q= dependencies: "@types/minimist" "^1.2.0" @@ -7100,26 +8611,26 @@ meow@^9.0.0: merge-stream@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/merge-stream/download/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + resolved "https://registry.npm.alibaba-inc.com/merge-stream/download/merge-stream-2.0.0.tgz" integrity sha1-UoI2KaFN0AyXcPtq1H3GMQ8sH2A= merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" - resolved "https://registry.npm.alibaba-inc.com/merge2/download/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + resolved "https://registry.npm.alibaba-inc.com/merge2/download/merge2-1.4.1.tgz" integrity sha1-Q2iJL4hekHRVpv19xVwMnUBJkK4= micromark@~2.11.0: version "2.11.4" - resolved "https://registry.npm.alibaba-inc.com/micromark/download/micromark-2.11.4.tgz#d13436138eea826383e822449c9a5c50ee44665a" + resolved "https://registry.npm.alibaba-inc.com/micromark/download/micromark-2.11.4.tgz" integrity sha1-0TQ2E47qgmOD6CJEnJpcUO5EZlo= dependencies: debug "^4.0.0" parse-entities "^2.0.0" -micromatch@^3.1.4: +micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" - resolved "https://registry.npm.alibaba-inc.com/micromatch/download/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha1-cIWbyVyYQJUvNZoGij/En57PrCM= + resolved "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -7137,7 +8648,7 @@ micromatch@^3.1.4: micromatch@^4.0.2, micromatch@^4.0.4: version "4.0.5" - resolved "https://registry.npm.alibaba-inc.com/micromatch/download/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + resolved "https://registry.npm.alibaba-inc.com/micromatch/download/micromatch-4.0.5.tgz" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== dependencies: braces "^3.0.2" @@ -7145,7 +8656,7 @@ micromatch@^4.0.2, micromatch@^4.0.4: miller-rabin@^4.0.0: version "4.0.1" - resolved "https://registry.npm.alibaba-inc.com/miller-rabin/download/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + resolved "https://registry.npm.alibaba-inc.com/miller-rabin/download/miller-rabin-4.0.1.tgz" integrity sha1-8IA1HIZbDcViqEYpZtqlNUPHik0= dependencies: bn.js "^4.0.0" @@ -7153,46 +8664,46 @@ miller-rabin@^4.0.0: mime-db@1.52.0: version "1.52.0" - resolved "https://registry.npm.alibaba-inc.com/mime-db/download/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + resolved "https://registry.npm.alibaba-inc.com/mime-db/download/mime-db-1.52.0.tgz" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== mime-types@^2.1.12: version "2.1.35" - resolved "https://registry.npm.alibaba-inc.com/mime-types/download/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + resolved "https://registry.npm.alibaba-inc.com/mime-types/download/mime-types-2.1.35.tgz" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" mime@1.4.1: version "1.4.1" - resolved "https://registry.npm.alibaba-inc.com/mime/download/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" + resolved "https://registry.npm.alibaba-inc.com/mime/download/mime-1.4.1.tgz" integrity sha1-Eh+evEnjdm8xGnbh+hyAA8SwOqY= mime@1.6.0: version "1.6.0" - resolved "https://registry.npm.alibaba-inc.com/mime/download/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + resolved "https://registry.npm.alibaba-inc.com/mime/download/mime-1.6.0.tgz" integrity sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE= mimic-fn@^2.1.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/mimic-fn/download/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + resolved "https://registry.npm.alibaba-inc.com/mimic-fn/download/mimic-fn-2.1.0.tgz" integrity sha1-ftLCzMyvhNP/y3pptXcR/CCDQBs= min-document@^2.19.0: version "2.19.0" - resolved "https://registry.npm.alibaba-inc.com/min-document/download/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + resolved "https://registry.npm.alibaba-inc.com/min-document/download/min-document-2.19.0.tgz" integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= dependencies: dom-walk "^0.1.0" min-indent@^1.0.0: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/min-indent/download/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + resolved "https://registry.npm.alibaba-inc.com/min-indent/download/min-indent-1.0.1.tgz" integrity sha1-pj9oFnOzBXH76LwlaGrnRu76mGk= mini-create-react-context@^0.3.0: version "0.3.3" - resolved "https://registry.npm.alibaba-inc.com/mini-create-react-context/download/mini-create-react-context-0.3.3.tgz#b1b2bc6604d3a6c5d9752bad7692615410ebb38e" + resolved "https://registry.npm.alibaba-inc.com/mini-create-react-context/download/mini-create-react-context-0.3.3.tgz" integrity sha1-sbK8ZgTTpsXZdSutdpJhVBDrs44= dependencies: "@babel/runtime" "^7.12.1" @@ -7200,7 +8711,7 @@ mini-create-react-context@^0.3.0: mini-create-react-context@^0.4.0: version "0.4.1" - resolved "https://registry.npm.alibaba-inc.com/mini-create-react-context/download/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e" + resolved "https://registry.npm.alibaba-inc.com/mini-create-react-context/download/mini-create-react-context-0.4.1.tgz" integrity sha1-ByFxVhv9ySLaCKYMIZekl8wtHV4= dependencies: "@babel/runtime" "^7.12.1" @@ -7208,24 +8719,24 @@ mini-create-react-context@^0.4.0: minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/minimalistic-assert/download/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + resolved "https://registry.npm.alibaba-inc.com/minimalistic-assert/download/minimalistic-assert-1.0.1.tgz" integrity sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc= minimalistic-crypto-utils@^1.0.1: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/minimalistic-crypto-utils/download/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + resolved "https://registry.npm.alibaba-inc.com/minimalistic-crypto-utils/download/minimalistic-crypto-utils-1.0.1.tgz" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" - resolved "https://registry.npm.alibaba-inc.com/minimatch/download/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + resolved "https://registry.npm.alibaba-inc.com/minimatch/download/minimatch-3.1.2.tgz" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" minimist-options@4.1.0: version "4.1.0" - resolved "https://registry.npm.alibaba-inc.com/minimist-options/download/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" + resolved "https://registry.npm.alibaba-inc.com/minimist-options/download/minimist-options-4.1.0.tgz" integrity sha1-wGVXE8U6ii69d/+iR9NCxA8BBhk= dependencies: arrify "^1.0.1" @@ -7234,37 +8745,80 @@ minimist-options@4.1.0: minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: version "1.2.7" - resolved "https://registry.npm.alibaba-inc.com/minimist/download/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + resolved "https://registry.npm.alibaba-inc.com/minimist/download/minimist-1.2.7.tgz" integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== +minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + mixin-deep@^1.2.0: version "1.3.2" - resolved "https://registry.npm.alibaba-inc.com/mixin-deep/download/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + resolved "https://registry.npm.alibaba-inc.com/mixin-deep/download/mixin-deep-1.3.2.tgz" integrity sha1-ESC0PcNZp4Xc5ltVuC4lfM9HlWY= dependencies: for-in "^1.0.2" is-extendable "^1.0.1" +mkdirp@~0.5.1: + version "0.5.6" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +ml-array-max@^1.2.4: + version "1.2.4" + resolved "https://registry.npmjs.org/ml-array-max/-/ml-array-max-1.2.4.tgz" + integrity sha512-BlEeg80jI0tW6WaPyGxf5Sa4sqvcyY6lbSn5Vcv44lp1I2GR6AWojfUvLnGTNsIXrZ8uqWmo8VcG1WpkI2ONMQ== + dependencies: + is-any-array "^2.0.0" + +ml-array-min@^1.2.3: + version "1.2.3" + resolved "https://registry.npmjs.org/ml-array-min/-/ml-array-min-1.2.3.tgz" + integrity sha512-VcZ5f3VZ1iihtrGvgfh/q0XlMobG6GQ8FsNyQXD3T+IlstDv85g8kfV0xUG1QPRO/t21aukaJowDzMTc7j5V6Q== + dependencies: + is-any-array "^2.0.0" + +ml-array-rescale@^1.3.7: + version "1.3.7" + resolved "https://registry.npmjs.org/ml-array-rescale/-/ml-array-rescale-1.3.7.tgz" + integrity sha512-48NGChTouvEo9KBctDfHC3udWnQKNKEWN0ziELvY3KG25GR5cA8K8wNVzracsqSW1QEkAXjTNx+ycgAv06/1mQ== + dependencies: + is-any-array "^2.0.0" + ml-array-max "^1.2.4" + ml-array-min "^1.2.3" + +ml-matrix@^6.5.0: + version "6.10.4" + resolved "https://registry.npmjs.org/ml-matrix/-/ml-matrix-6.10.4.tgz" + integrity sha512-rUyEhfNPzqFsltYwvjNeYQXlYEaVea3KgzcJKJteQUj2WVAGFx9fLNRjtMR9mg2B6bd5buxlmkZmxM4hmO+SKg== + dependencies: + is-any-array "^2.0.0" + ml-array-rescale "^1.3.7" + mock.js@^0.2.0: version "0.2.0" - resolved "https://registry.npm.alibaba-inc.com/mock.js/download/mock.js-0.2.0.tgz#c0d6ee5e58c7b6902c3030462c1eff3bd33f8bdd" + resolved "https://registry.npm.alibaba-inc.com/mock.js/download/mock.js-0.2.0.tgz" integrity sha1-wNbuXljHtpAsMDBGLB7/O9M/i90= mockjs@^1.1.0: version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/mockjs/download/mockjs-1.1.0.tgz#e6a0c378e91906dbaff20911cc0273b3c7d75b06" + resolved "https://registry.npm.alibaba-inc.com/mockjs/download/mockjs-1.1.0.tgz" integrity sha1-5qDDeOkZBtuv8gkRzAJzs8fXWwY= dependencies: commander "*" -moment@2.29.4, moment@^2.24.0, moment@^2.29.1, moment@^2.29.2: +moment@^2.24.0, moment@^2.29.1, moment@^2.29.2, moment@^2.29.4: version "2.29.4" - resolved "https://registry.npm.alibaba-inc.com/moment/download/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" + resolved "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz" integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== mpd-parser@0.21.1: version "0.21.1" - resolved "https://registry.npm.alibaba-inc.com/mpd-parser/download/mpd-parser-0.21.1.tgz#4f4834074ed0a8e265d8b04a5d2d7b5045a4fa55" + resolved "https://registry.npm.alibaba-inc.com/mpd-parser/download/mpd-parser-0.21.1.tgz" integrity sha512-BxlSXWbKE1n7eyEPBnTEkrzhS3PdmkkKdM1pgKbPnPOH0WFZIc0sPOWi7m0Uo3Wd2a4Or8Qf4ZbS7+ASqQ49fw== dependencies: "@babel/runtime" "^7.12.5" @@ -7274,7 +8828,7 @@ mpd-parser@0.21.1: mpd-parser@0.22.1, mpd-parser@^0.22.1: version "0.22.1" - resolved "https://registry.npm.alibaba-inc.com/mpd-parser/download/mpd-parser-0.22.1.tgz#bc2bf7d3e56368e4b0121035b055675401871521" + resolved "https://registry.npm.alibaba-inc.com/mpd-parser/download/mpd-parser-0.22.1.tgz" integrity sha512-fwBebvpyPUU8bOzvhX0VQZgSohncbgYwUyJJoTSNpmy7ccD2ryiCvM7oRkn/xQH5cv73/xU7rJSNCLjdGFor0Q== dependencies: "@babel/runtime" "^7.12.5" @@ -7284,27 +8838,27 @@ mpd-parser@0.22.1, mpd-parser@^0.22.1: ms@2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/ms/download/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + resolved "https://registry.npm.alibaba-inc.com/ms/download/ms-2.0.0.tgz" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= ms@2.1.2: version "2.1.2" - resolved "https://registry.npm.alibaba-inc.com/ms/download/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + resolved "https://registry.npm.alibaba-inc.com/ms/download/ms-2.1.2.tgz" integrity sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk= ms@2.1.3: version "2.1.3" - resolved "https://registry.npm.alibaba-inc.com/ms/download/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + resolved "https://registry.npm.alibaba-inc.com/ms/download/ms-2.1.3.tgz" integrity sha1-V0yBOM4dK1hh8LRFedut1gxmFbI= multimap@^1.1.0: version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/multimap/download/multimap-1.1.0.tgz#5263febc085a1791c33b59bb3afc6a76a2a10ca8" + resolved "https://registry.npm.alibaba-inc.com/multimap/download/multimap-1.1.0.tgz" integrity sha1-UmP+vAhaF5HDO1m7OvxqdqKhDKg= mux.js@6.0.1: version "6.0.1" - resolved "https://registry.npm.alibaba-inc.com/mux.js/download/mux.js-6.0.1.tgz#65ce0f7a961d56c006829d024d772902d28c7755" + resolved "https://registry.npm.alibaba-inc.com/mux.js/download/mux.js-6.0.1.tgz" integrity sha512-22CHb59rH8pWGcPGW5Og7JngJ9s+z4XuSlYvnxhLuc58cA1WqGDQPzuG8I+sPm1/p0CdgpzVTaKW408k5DNn8w== dependencies: "@babel/runtime" "^7.11.2" @@ -7312,12 +8866,12 @@ mux.js@6.0.1: nanoid@^3.3.4: version "3.3.4" - resolved "https://registry.npm.alibaba-inc.com/nanoid/download/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" + resolved "https://registry.npm.alibaba-inc.com/nanoid/download/nanoid-3.3.4.tgz" integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== nanomatch@^1.2.9: version "1.2.13" - resolved "https://registry.npm.alibaba-inc.com/nanomatch/download/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + resolved "https://registry.npm.alibaba-inc.com/nanomatch/download/nanomatch-1.2.13.tgz" integrity sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk= dependencies: arr-diff "^4.0.0" @@ -7334,34 +8888,39 @@ nanomatch@^1.2.9: natural-compare-lite@^1.4.0: version "1.4.0" - resolved "https://registry.npm.alibaba-inc.com/natural-compare-lite/download/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" + resolved "https://registry.npm.alibaba-inc.com/natural-compare-lite/download/natural-compare-lite-1.4.0.tgz" integrity sha1-F7CVgZiJef3a/gIB6TG6kzyWy7Q= natural-compare@^1.4.0: version "1.4.0" - resolved "https://registry.npm.alibaba-inc.com/natural-compare/download/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + resolved "https://registry.npm.alibaba-inc.com/natural-compare/download/natural-compare-1.4.0.tgz" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= +nested-error-stacks@^2.0.0, nested-error-stacks@^2.1.0: + version "2.1.1" + resolved "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz" + integrity sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw== + next-tick@1, next-tick@^1.1.0: version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/next-tick/download/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + resolved "https://registry.npm.alibaba-inc.com/next-tick/download/next-tick-1.1.0.tgz" integrity sha1-GDbuMK1W1n7ygbIr0Zn3CUSbNes= nice-try@^1.0.4: version "1.0.5" - resolved "https://registry.npm.alibaba-inc.com/nice-try/download/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + resolved "https://registry.npm.alibaba-inc.com/nice-try/download/nice-try-1.0.5.tgz" integrity sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y= node-fetch-h2@^2.3.0: version "2.3.0" - resolved "https://registry.npm.alibaba-inc.com/node-fetch-h2/download/node-fetch-h2-2.3.0.tgz#c6188325f9bd3d834020bf0f2d6dc17ced2241ac" + resolved "https://registry.npm.alibaba-inc.com/node-fetch-h2/download/node-fetch-h2-2.3.0.tgz" integrity sha1-xhiDJfm9PYNAIL8PLW3BfO0iQaw= dependencies: http2-client "^1.2.5" node-fetch@^1.0.1: version "1.7.3" - resolved "https://registry.npm.alibaba-inc.com/node-fetch/download/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + resolved "https://registry.npm.alibaba-inc.com/node-fetch/download/node-fetch-1.7.3.tgz" integrity sha1-mA9vcthSEaU0fGsrwYxbhMPrR+8= dependencies: encoding "^0.1.11" @@ -7369,19 +8928,26 @@ node-fetch@^1.0.1: node-fetch@^2.6.1: version "2.6.7" - resolved "https://registry.npm.alibaba-inc.com/node-fetch/download/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + resolved "https://registry.npm.alibaba-inc.com/node-fetch/download/node-fetch-2.6.7.tgz" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" +node-fetch@^2.6.12: + version "2.7.0" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-int64@^0.4.0: version "0.4.0" - resolved "https://registry.npm.alibaba-inc.com/node-int64/download/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + resolved "https://registry.npm.alibaba-inc.com/node-int64/download/node-int64-0.4.0.tgz" integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= node-libs-browser@2.2.1: version "2.2.1" - resolved "https://registry.npm.alibaba-inc.com/node-libs-browser/download/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + resolved "https://registry.npm.alibaba-inc.com/node-libs-browser/download/node-libs-browser-2.2.1.tgz" integrity sha1-tk9RPRgzhiX5A0bSew0jXmMfZCU= dependencies: assert "^1.1.1" @@ -7410,7 +8976,7 @@ node-libs-browser@2.2.1: node-notifier@^8.0.0: version "8.0.2" - resolved "https://registry.npm.alibaba-inc.com/node-notifier/download/node-notifier-8.0.2.tgz#f3167a38ef0d2c8a866a83e318c1ba0efeb702c5" + resolved "https://registry.npm.alibaba-inc.com/node-notifier/download/node-notifier-8.0.2.tgz" integrity sha1-8xZ6OO8NLIqGaoPjGMG6Dv63AsU= dependencies: growly "^1.3.0" @@ -7422,19 +8988,19 @@ node-notifier@^8.0.0: node-readfiles@^0.2.0: version "0.2.0" - resolved "https://registry.npm.alibaba-inc.com/node-readfiles/download/node-readfiles-0.2.0.tgz#dbbd4af12134e2e635c245ef93ffcf6f60673a5d" + resolved "https://registry.npm.alibaba-inc.com/node-readfiles/download/node-readfiles-0.2.0.tgz" integrity sha1-271K8SE04uY1wkXvk//Pb2BnOl0= dependencies: es6-promise "^3.2.1" node-releases@^2.0.6: version "2.0.6" - resolved "https://registry.npm.alibaba-inc.com/node-releases/download/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" + resolved "https://registry.npm.alibaba-inc.com/node-releases/download/node-releases-2.0.6.tgz" integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== normalize-package-data@^2.5.0: version "2.5.0" - resolved "https://registry.npm.alibaba-inc.com/normalize-package-data/download/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + resolved "https://registry.npm.alibaba-inc.com/normalize-package-data/download/normalize-package-data-2.5.0.tgz" integrity sha1-5m2xg4sgDB38IzIl0SyzZSDiNKg= dependencies: hosted-git-info "^2.1.4" @@ -7444,7 +9010,7 @@ normalize-package-data@^2.5.0: normalize-package-data@^3.0.0: version "3.0.3" - resolved "https://registry.npm.alibaba-inc.com/normalize-package-data/download/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e" + resolved "https://registry.npm.alibaba-inc.com/normalize-package-data/download/normalize-package-data-3.0.3.tgz" integrity sha1-28w+LaWVCaCYNCKITNFy7v36Ul4= dependencies: hosted-git-info "^4.0.1" @@ -7454,34 +9020,34 @@ normalize-package-data@^3.0.0: normalize-path@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/normalize-path/download/normalize-path-1.0.0.tgz#32d0e472f91ff345701c15a8311018d3b0a90379" + resolved "https://registry.npm.alibaba-inc.com/normalize-path/download/normalize-path-1.0.0.tgz" integrity sha1-MtDkcvkf80VwHBWoMRAY07CpA3k= normalize-path@^2.1.1: version "2.1.1" - resolved "https://registry.npm.alibaba-inc.com/normalize-path/download/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + resolved "https://registry.npm.alibaba-inc.com/normalize-path/download/normalize-path-2.1.1.tgz" integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= dependencies: remove-trailing-separator "^1.0.1" normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/normalize-path/download/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + resolved "https://registry.npm.alibaba-inc.com/normalize-path/download/normalize-path-3.0.0.tgz" integrity sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU= normalize-range@^0.1.2: version "0.1.2" - resolved "https://registry.npm.alibaba-inc.com/normalize-range/download/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + resolved "https://registry.npm.alibaba-inc.com/normalize-range/download/normalize-range-0.1.2.tgz" integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= normalize-selector@^0.2.0: version "0.2.0" - resolved "https://registry.npm.alibaba-inc.com/normalize-selector/download/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03" + resolved "https://registry.npm.alibaba-inc.com/normalize-selector/download/normalize-selector-0.2.0.tgz" integrity sha1-0LFF62kRicY6eNIB3E/bEpPvDAM= normalize-url@1.9.1: version "1.9.1" - resolved "https://registry.npm.alibaba-inc.com/normalize-url/download/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" + resolved "https://registry.npm.alibaba-inc.com/normalize-url/download/normalize-url-1.9.1.tgz" integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= dependencies: object-assign "^4.0.1" @@ -7491,36 +9057,43 @@ normalize-url@1.9.1: normalize.css@^7.0.0: version "7.0.0" - resolved "https://registry.npm.alibaba-inc.com/normalize.css/download/normalize.css-7.0.0.tgz#abfb1dd82470674e0322b53ceb1aaf412938e4bf" + resolved "https://registry.npm.alibaba-inc.com/normalize.css/download/normalize.css-7.0.0.tgz" integrity sha1-q/sd2CRwZ04DIrU86xqvQSk45L8= npm-run-path@^2.0.0: version "2.0.2" - resolved "https://registry.npm.alibaba-inc.com/npm-run-path/download/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + resolved "https://registry.npm.alibaba-inc.com/npm-run-path/download/npm-run-path-2.0.2.tgz" integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= dependencies: path-key "^2.0.0" npm-run-path@^4.0.0: version "4.0.1" - resolved "https://registry.npm.alibaba-inc.com/npm-run-path/download/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + resolved "https://registry.npm.alibaba-inc.com/npm-run-path/download/npm-run-path-4.0.1.tgz" integrity sha1-t+zR5e1T2o43pV4cImnguX7XSOo= dependencies: path-key "^3.0.0" +nth-check@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz" + integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== + dependencies: + boolbase "~1.0.0" + num2fraction@^1.2.2: version "1.2.2" - resolved "https://registry.npm.alibaba-inc.com/num2fraction/download/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + resolved "https://registry.npm.alibaba-inc.com/num2fraction/download/num2fraction-1.2.2.tgz" integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= number-precision@1.6.0: version "1.6.0" - resolved "https://registry.npm.alibaba-inc.com/number-precision/download/number-precision-1.6.0.tgz#e309d28f80871d36ac9f6ecd974e13afb1ec0de0" + resolved "https://registry.npm.alibaba-inc.com/number-precision/download/number-precision-1.6.0.tgz" integrity sha512-05OLPgbgmnixJw+VvEh18yNPUo3iyp4BEWJcrLu4X9W05KmMifN7Mu5exYvQXqxxeNWhvIF+j3Rij+HmddM/hQ== nunjucks@^3.2.2: version "3.2.3" - resolved "https://registry.npm.alibaba-inc.com/nunjucks/download/nunjucks-3.2.3.tgz#1b33615247290e94e28263b5d855ece765648a31" + resolved "https://registry.npm.alibaba-inc.com/nunjucks/download/nunjucks-3.2.3.tgz" integrity sha1-GzNhUkcpDpTigmO12FXs52VkijE= dependencies: a-sync-waterfall "^1.0.0" @@ -7529,19 +9102,19 @@ nunjucks@^3.2.2: nwsapi@^2.2.0: version "2.2.2" - resolved "https://registry.npm.alibaba-inc.com/nwsapi/download/nwsapi-2.2.2.tgz#e5418863e7905df67d51ec95938d67bf801f0bb0" + resolved "https://registry.npm.alibaba-inc.com/nwsapi/download/nwsapi-2.2.2.tgz" integrity sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw== oas-kit-common@^1.0.8: version "1.0.8" - resolved "https://registry.npm.alibaba-inc.com/oas-kit-common/download/oas-kit-common-1.0.8.tgz#6d8cacf6e9097967a4c7ea8bcbcbd77018e1f535" + resolved "https://registry.npm.alibaba-inc.com/oas-kit-common/download/oas-kit-common-1.0.8.tgz" integrity sha1-bYys9ukJeWekx+qLy8vXcBjh9TU= dependencies: fast-safe-stringify "^2.0.7" oas-linter@^3.2.2: version "3.2.2" - resolved "https://registry.npm.alibaba-inc.com/oas-linter/download/oas-linter-3.2.2.tgz#ab6a33736313490659035ca6802dc4b35d48aa1e" + resolved "https://registry.npm.alibaba-inc.com/oas-linter/download/oas-linter-3.2.2.tgz" integrity sha1-q2ozc2MTSQZZA1ymgC3Es11Iqh4= dependencies: "@exodus/schemasafe" "^1.0.0-rc.2" @@ -7550,7 +9123,7 @@ oas-linter@^3.2.2: oas-resolver@^2.5.6: version "2.5.6" - resolved "https://registry.npm.alibaba-inc.com/oas-resolver/download/oas-resolver-2.5.6.tgz#10430569cb7daca56115c915e611ebc5515c561b" + resolved "https://registry.npm.alibaba-inc.com/oas-resolver/download/oas-resolver-2.5.6.tgz" integrity sha1-EEMFact9rKVhFckV5hHrxVFcVhs= dependencies: node-fetch-h2 "^2.3.0" @@ -7561,12 +9134,12 @@ oas-resolver@^2.5.6: oas-schema-walker@^1.1.5: version "1.1.5" - resolved "https://registry.npm.alibaba-inc.com/oas-schema-walker/download/oas-schema-walker-1.1.5.tgz#74c3cd47b70ff8e0b19adada14455b5d3ac38a22" + resolved "https://registry.npm.alibaba-inc.com/oas-schema-walker/download/oas-schema-walker-1.1.5.tgz" integrity sha1-dMPNR7cP+OCxmtraFEVbXTrDiiI= oas-validator@^5.0.8: version "5.0.8" - resolved "https://registry.npm.alibaba-inc.com/oas-validator/download/oas-validator-5.0.8.tgz#387e90df7cafa2d3ffc83b5fb976052b87e73c28" + resolved "https://registry.npm.alibaba-inc.com/oas-validator/download/oas-validator-5.0.8.tgz" integrity sha1-OH6Q33yvotP/yDtfuXYFK4fnPCg= dependencies: call-me-maybe "^1.0.1" @@ -7580,12 +9153,12 @@ oas-validator@^5.0.8: object-assign@4.x, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" - resolved "https://registry.npm.alibaba-inc.com/object-assign/download/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + resolved "https://registry.npm.alibaba-inc.com/object-assign/download/object-assign-4.1.1.tgz" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= object-copy@^0.1.0: version "0.1.0" - resolved "https://registry.npm.alibaba-inc.com/object-copy/download/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + resolved "https://registry.npm.alibaba-inc.com/object-copy/download/object-copy-0.1.0.tgz" integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= dependencies: copy-descriptor "^0.1.0" @@ -7594,24 +9167,29 @@ object-copy@^0.1.0: object-inspect@^1.12.2, object-inspect@^1.9.0: version "1.12.2" - resolved "https://registry.npm.alibaba-inc.com/object-inspect/download/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" + resolved "https://registry.npm.alibaba-inc.com/object-inspect/download/object-inspect-1.12.2.tgz" integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== +object-inspect@^1.12.3: + version "1.12.3" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + object-keys@^1.1.1: version "1.1.1" - resolved "https://registry.npm.alibaba-inc.com/object-keys/download/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + resolved "https://registry.npm.alibaba-inc.com/object-keys/download/object-keys-1.1.1.tgz" integrity sha1-HEfyct8nfzsdrwYWd9nILiMixg4= object-visit@^1.0.0: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/object-visit/download/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + resolved "https://registry.npm.alibaba-inc.com/object-visit/download/object-visit-1.0.1.tgz" integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= dependencies: isobject "^3.0.0" object.assign@^4.1.3, object.assign@^4.1.4: version "4.1.4" - resolved "https://registry.npm.alibaba-inc.com/object.assign/download/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + resolved "https://registry.npm.alibaba-inc.com/object.assign/download/object.assign-4.1.4.tgz" integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== dependencies: call-bind "^1.0.2" @@ -7621,7 +9199,7 @@ object.assign@^4.1.3, object.assign@^4.1.4: object.entries@^1.1.6: version "1.1.6" - resolved "https://registry.npm.alibaba-inc.com/object.entries/download/object.entries-1.1.6.tgz#9737d0e5b8291edd340a3e3264bb8a3b00d5fa23" + resolved "https://registry.npm.alibaba-inc.com/object.entries/download/object.entries-1.1.6.tgz" integrity sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w== dependencies: call-bind "^1.0.2" @@ -7630,16 +9208,27 @@ object.entries@^1.1.6: object.fromentries@^2.0.6: version "2.0.6" - resolved "https://registry.npm.alibaba-inc.com/object.fromentries/download/object.fromentries-2.0.6.tgz#cdb04da08c539cffa912dcd368b886e0904bfa73" + resolved "https://registry.npm.alibaba-inc.com/object.fromentries/download/object.fromentries-2.0.6.tgz" integrity sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg== dependencies: call-bind "^1.0.2" define-properties "^1.1.4" es-abstract "^1.20.4" +object.getownpropertydescriptors@^2.1.0: + version "2.1.7" + resolved "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.7.tgz" + integrity sha512-PrJz0C2xJ58FNn11XV2lr4Jt5Gzl94qpy9Lu0JlfEj14z88sqbSBJCBEzdlNUCzY2gburhbrwOZ5BHCmuNUy0g== + dependencies: + array.prototype.reduce "^1.0.6" + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + safe-array-concat "^1.0.0" + object.hasown@^1.1.2: version "1.1.2" - resolved "https://registry.npm.alibaba-inc.com/object.hasown/download/object.hasown-1.1.2.tgz#f919e21fad4eb38a57bc6345b3afd496515c3f92" + resolved "https://registry.npm.alibaba-inc.com/object.hasown/download/object.hasown-1.1.2.tgz" integrity sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw== dependencies: define-properties "^1.1.4" @@ -7647,56 +9236,72 @@ object.hasown@^1.1.2: object.pick@^1.3.0: version "1.3.0" - resolved "https://registry.npm.alibaba-inc.com/object.pick/download/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + resolved "https://registry.npm.alibaba-inc.com/object.pick/download/object.pick-1.3.0.tgz" integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= dependencies: isobject "^3.0.1" +object.values@^1.1.0: + version "1.1.7" + resolved "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz" + integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + object.values@^1.1.6: version "1.1.6" - resolved "https://registry.npm.alibaba-inc.com/object.values/download/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" + resolved "https://registry.npm.alibaba-inc.com/object.values/download/object.values-1.1.6.tgz" integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== dependencies: call-bind "^1.0.2" define-properties "^1.1.4" es-abstract "^1.20.4" +omit.js@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/omit.js/-/omit.js-1.0.2.tgz" + integrity sha512-/QPc6G2NS+8d4L/cQhbk6Yit1WTB6Us2g84A7A/1+w9d/eRGHyEqC5kkQtHVoHZ5NFWGG7tUGgrhVZwgZanKrQ== + dependencies: + babel-runtime "^6.23.0" + omit.js@^2.0.2: version "2.0.2" - resolved "https://registry.npm.alibaba-inc.com/omit.js/download/omit.js-2.0.2.tgz#dd9b8436fab947a5f3ff214cb2538631e313ec2f" + resolved "https://registry.npm.alibaba-inc.com/omit.js/download/omit.js-2.0.2.tgz" integrity sha1-3ZuENvq5R6Xz/yFMslOGMeMT7C8= on-finished@2.4.1: version "2.4.1" - resolved "https://registry.npm.alibaba-inc.com/on-finished/download/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + resolved "https://registry.npm.alibaba-inc.com/on-finished/download/on-finished-2.4.1.tgz" integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== dependencies: ee-first "1.1.1" once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" - resolved "https://registry.npm.alibaba-inc.com/once/download/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.npm.alibaba-inc.com/once/download/once-1.4.0.tgz" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" onetime@^5.1.0: version "5.1.2" - resolved "https://registry.npm.alibaba-inc.com/onetime/download/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + resolved "https://registry.npm.alibaba-inc.com/onetime/download/onetime-5.1.2.tgz" integrity sha1-0Oluu1awdHbfHdnEgG5SN5hcpF4= dependencies: mimic-fn "^2.1.0" openapi3-ts@^2.0.1: version "2.0.2" - resolved "https://registry.npm.alibaba-inc.com/openapi3-ts/download/openapi3-ts-2.0.2.tgz#a200dd838bf24c9086c8eedcfeb380b7eb31e82a" + resolved "https://registry.npm.alibaba-inc.com/openapi3-ts/download/openapi3-ts-2.0.2.tgz" integrity sha512-TxhYBMoqx9frXyOgnRHufjQfPXomTIHYKhSKJ6jHfj13kS8OEIhvmE8CTuQyKtjjWttAjX5DPxM1vmalEpo8Qw== dependencies: yaml "^1.10.2" optionator@^0.8.1: version "0.8.3" - resolved "https://registry.npm.alibaba-inc.com/optionator/download/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + resolved "https://registry.npm.alibaba-inc.com/optionator/download/optionator-0.8.3.tgz" integrity sha1-hPodA2/p08fiHZmIS2ARZ+yPtJU= dependencies: deep-is "~0.1.3" @@ -7708,7 +9313,7 @@ optionator@^0.8.1: optionator@^0.9.1: version "0.9.1" - resolved "https://registry.npm.alibaba-inc.com/optionator/download/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + resolved "https://registry.npm.alibaba-inc.com/optionator/download/optionator-0.9.1.tgz" integrity sha1-TyNqY3Pa4FZqbUPhMmZ09QwpFJk= dependencies: deep-is "^0.1.3" @@ -7720,79 +9325,119 @@ optionator@^0.9.1: os-browserify@^0.3.0: version "0.3.0" - resolved "https://registry.npm.alibaba-inc.com/os-browserify/download/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + resolved "https://registry.npm.alibaba-inc.com/os-browserify/download/os-browserify-0.3.0.tgz" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= os-locale@^5.0.0: version "5.0.0" - resolved "https://registry.npm.alibaba-inc.com/os-locale/download/os-locale-5.0.0.tgz#6d26c1d95b6597c5d5317bf5fba37eccec3672e0" + resolved "https://registry.npm.alibaba-inc.com/os-locale/download/os-locale-5.0.0.tgz" integrity sha1-bSbB2Vtll8XVMXv1+6N+zOw2cuA= dependencies: execa "^4.0.0" lcid "^3.0.0" mem "^5.0.0" +p-all@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/p-all/-/p-all-2.1.0.tgz" + integrity sha512-HbZxz5FONzz/z2gJfk6bFca0BCiSRF8jU3yCsWOen/vR6lZjfPOu/e7L3uFzTW1i0H8TlC3vqQstEJPQL4/uLA== + dependencies: + p-map "^2.0.0" + p-defer@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/p-defer/download/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + resolved "https://registry.npm.alibaba-inc.com/p-defer/download/p-defer-1.0.0.tgz" integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= p-each-series@^2.1.0: version "2.2.0" - resolved "https://registry.npm.alibaba-inc.com/p-each-series/download/p-each-series-2.2.0.tgz#105ab0357ce72b202a8a8b94933672657b5e2a9a" + resolved "https://registry.npm.alibaba-inc.com/p-each-series/download/p-each-series-2.2.0.tgz" integrity sha1-EFqwNXznKyAqiouUkzZyZXteKpo= +p-event@^4.1.0: + version "4.2.0" + resolved "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz" + integrity sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ== + dependencies: + p-timeout "^3.1.0" + +p-filter@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz" + integrity sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw== + dependencies: + p-map "^2.0.0" + p-finally@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/p-finally/download/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + resolved "https://registry.npm.alibaba-inc.com/p-finally/download/p-finally-1.0.0.tgz" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= p-is-promise@^2.1.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/p-is-promise/download/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" + resolved "https://registry.npm.alibaba-inc.com/p-is-promise/download/p-is-promise-2.1.0.tgz" integrity sha1-kYzrrqJIpiz3/6uOO8qMX4gvxC4= p-limit@^2.2.0: version "2.3.0" - resolved "https://registry.npm.alibaba-inc.com/p-limit/download/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + resolved "https://registry.npm.alibaba-inc.com/p-limit/download/p-limit-2.3.0.tgz" integrity sha1-PdM8ZHohT9//2DWTPrCG2g3CHbE= dependencies: p-try "^2.0.0" p-locate@^4.1.0: version "4.1.0" - resolved "https://registry.npm.alibaba-inc.com/p-locate/download/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + resolved "https://registry.npm.alibaba-inc.com/p-locate/download/p-locate-4.1.0.tgz" integrity sha1-o0KLtwiLOmApL2aRkni3wpetTwc= dependencies: p-limit "^2.2.0" +p-map@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz" + integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== + +p-map@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz" + integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== + dependencies: + aggregate-error "^3.0.0" + p-map@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/p-map/download/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + resolved "https://registry.npm.alibaba-inc.com/p-map/download/p-map-4.0.0.tgz" integrity sha1-uy+Vpe2i7BaOySdOBqdHw+KQTSs= dependencies: aggregate-error "^3.0.0" +p-timeout@^3.1.0: + version "3.2.0" + resolved "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz" + integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg== + dependencies: + p-finally "^1.0.0" + p-try@^2.0.0: version "2.2.0" - resolved "https://registry.npm.alibaba-inc.com/p-try/download/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + resolved "https://registry.npm.alibaba-inc.com/p-try/download/p-try-2.2.0.tgz" integrity sha1-yyhoVA4xPWHeWPr741zpAE1VQOY= pako@~1.0.5: version "1.0.11" - resolved "https://registry.npm.alibaba-inc.com/pako/download/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + resolved "https://registry.npm.alibaba-inc.com/pako/download/pako-1.0.11.tgz" integrity sha1-bJWZ00DVTf05RjgCUqNXBaa5kr8= parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/parent-module/download/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + resolved "https://registry.npm.alibaba-inc.com/parent-module/download/parent-module-1.0.1.tgz" integrity sha1-aR0nCeeMefrjoVZiJFLQB2LKqqI= dependencies: callsites "^3.0.0" parse-asn1@^5.0.0, parse-asn1@^5.1.5: version "5.1.6" - resolved "https://registry.npm.alibaba-inc.com/parse-asn1/download/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + resolved "https://registry.npm.alibaba-inc.com/parse-asn1/download/parse-asn1-5.1.6.tgz" integrity sha1-OFCAo+wTy2KmLTlAnLPoiETNrtQ= dependencies: asn1.js "^5.2.0" @@ -7803,7 +9448,7 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5: parse-entities@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/parse-entities/download/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" + resolved "https://registry.npm.alibaba-inc.com/parse-entities/download/parse-entities-2.0.0.tgz" integrity sha1-U8brW5MUofTsmfoP33zgHs2gy+g= dependencies: character-entities "^1.0.0" @@ -7815,7 +9460,7 @@ parse-entities@^2.0.0: parse-json@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/parse-json/download/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + resolved "https://registry.npm.alibaba-inc.com/parse-json/download/parse-json-4.0.0.tgz" integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= dependencies: error-ex "^1.3.1" @@ -7823,7 +9468,7 @@ parse-json@^4.0.0: parse-json@^5.0.0: version "5.2.0" - resolved "https://registry.npm.alibaba-inc.com/parse-json/download/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + resolved "https://registry.npm.alibaba-inc.com/parse-json/download/parse-json-5.2.0.tgz" integrity sha1-x2/Gbe5UIxyWKyK8yKcs8vmXU80= dependencies: "@babel/code-frame" "^7.0.0" @@ -7833,69 +9478,93 @@ parse-json@^5.0.0: parse5@6.0.1: version "6.0.1" - resolved "https://registry.npm.alibaba-inc.com/parse5/download/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + resolved "https://registry.npm.alibaba-inc.com/parse5/download/parse5-6.0.1.tgz" integrity sha1-4aHAhcVps9wIMhGE8Zo5zCf3wws= +parse5@^7.0.0: + version "7.1.2" + resolved "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz" + integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== + dependencies: + entities "^4.4.0" + parseurl@~1.3.3: version "1.3.3" - resolved "https://registry.npm.alibaba-inc.com/parseurl/download/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + resolved "https://registry.npm.alibaba-inc.com/parseurl/download/parseurl-1.3.3.tgz" integrity sha1-naGee+6NEt/wUT7Vt2lXeTvC6NQ= pascalcase@^0.1.1: version "0.1.1" - resolved "https://registry.npm.alibaba-inc.com/pascalcase/download/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + resolved "https://registry.npm.alibaba-inc.com/pascalcase/download/pascalcase-0.1.1.tgz" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= path-browserify@0.0.1: version "0.0.1" - resolved "https://registry.npm.alibaba-inc.com/path-browserify/download/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + resolved "https://registry.npm.alibaba-inc.com/path-browserify/download/path-browserify-0.0.1.tgz" integrity sha1-5sTd1+06onxoogzE5Q4aTug7vEo= +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz" + integrity sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q== + path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/path-exists/download/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + resolved "https://registry.npm.alibaba-inc.com/path-exists/download/path-exists-4.0.0.tgz" integrity sha1-UTvb4tO5XXdi6METfvoZXGxhtbM= path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/path-is-absolute/download/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.npm.alibaba-inc.com/path-is-absolute/download/path-is-absolute-1.0.1.tgz" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" - resolved "https://registry.npm.alibaba-inc.com/path-key/download/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + resolved "https://registry.npm.alibaba-inc.com/path-key/download/path-key-2.0.1.tgz" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" - resolved "https://registry.npm.alibaba-inc.com/path-key/download/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + resolved "https://registry.npm.alibaba-inc.com/path-key/download/path-key-3.1.1.tgz" integrity sha1-WB9q3mWMu6ZaDTOA3ndTKVBU83U= path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.npm.alibaba-inc.com/path-parse/download/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + resolved "https://registry.npm.alibaba-inc.com/path-parse/download/path-parse-1.0.7.tgz" integrity sha1-+8EUtgykKzDZ2vWFjkvWi77bZzU= path-to-regexp@1.x, path-to-regexp@^1.7.0: version "1.8.0" - resolved "https://registry.npm.alibaba-inc.com/path-to-regexp/download/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" + resolved "https://registry.npm.alibaba-inc.com/path-to-regexp/download/path-to-regexp-1.8.0.tgz" integrity sha1-iHs7qdhDk+h6CgufTLdWGYtTVIo= dependencies: isarray "0.0.1" path-to-regexp@2.4.0: version "2.4.0" - resolved "https://registry.npm.alibaba-inc.com/path-to-regexp/download/path-to-regexp-2.4.0.tgz#35ce7f333d5616f1c1e1bfe266c3aba2e5b2e704" + resolved "https://registry.npm.alibaba-inc.com/path-to-regexp/download/path-to-regexp-2.4.0.tgz" integrity sha1-Nc5/Mz1WFvHB4b/iZsOrouWy5wQ= +path-to-regexp@^6.2.1: + version "6.2.1" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz" + integrity sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw== + +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz" + integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== + dependencies: + pify "^3.0.0" + path-type@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/path-type/download/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + resolved "https://registry.npm.alibaba-inc.com/path-type/download/path-type-4.0.0.tgz" integrity sha1-hO0BwKe6OAr+CdkKjBgNzZ0DBDs= pbkdf2@^3.0.3: version "3.1.2" - resolved "https://registry.npm.alibaba-inc.com/pbkdf2/download/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + resolved "https://registry.npm.alibaba-inc.com/pbkdf2/download/pbkdf2-3.1.2.tgz" integrity sha1-3YIqoIh1gOUvGgOdw+2hCO+uMHU= dependencies: create-hash "^1.1.2" @@ -7906,70 +9575,80 @@ pbkdf2@^3.0.3: performance-now@^2.1.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/performance-now/download/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + resolved "https://registry.npm.alibaba-inc.com/performance-now/download/performance-now-2.1.0.tgz" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= picocolors@^0.2.1: version "0.2.1" - resolved "https://registry.npm.alibaba-inc.com/picocolors/download/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" + resolved "https://registry.npm.alibaba-inc.com/picocolors/download/picocolors-0.2.1.tgz" integrity sha1-VwZw95NkaFHRuhNZlpYqutWHhZ8= picocolors@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/picocolors/download/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + resolved "https://registry.npm.alibaba-inc.com/picocolors/download/picocolors-1.0.0.tgz" integrity sha1-y1vcdP8/UYkiNur3nWi8RFZKuBw= picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" - resolved "https://registry.npm.alibaba-inc.com/picomatch/download/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + resolved "https://registry.npm.alibaba-inc.com/picomatch/download/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz" + integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + pirates@^4.0.1: version "4.0.5" - resolved "https://registry.npm.alibaba-inc.com/pirates/download/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" + resolved "https://registry.npm.alibaba-inc.com/pirates/download/pirates-4.0.5.tgz" integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== pkcs7@^1.0.4: version "1.0.4" - resolved "https://registry.npm.alibaba-inc.com/pkcs7/download/pkcs7-1.0.4.tgz#6090b9e71160dabf69209d719cbafa538b00a1cb" + resolved "https://registry.npm.alibaba-inc.com/pkcs7/download/pkcs7-1.0.4.tgz" integrity sha1-YJC55xFg2r9pIJ1xnLr6U4sAocs= dependencies: "@babel/runtime" "^7.5.5" pkg-dir@^4.2.0: version "4.2.0" - resolved "https://registry.npm.alibaba-inc.com/pkg-dir/download/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + resolved "https://registry.npm.alibaba-inc.com/pkg-dir/download/pkg-dir-4.2.0.tgz" integrity sha1-8JkTPfft5CLoHR2ESCcO6z5CYfM= dependencies: find-up "^4.0.0" please-upgrade-node@^3.2.0: version "3.2.0" - resolved "https://registry.npm.alibaba-inc.com/please-upgrade-node/download/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" + resolved "https://registry.npm.alibaba-inc.com/please-upgrade-node/download/please-upgrade-node-3.2.0.tgz" integrity sha1-rt3T+ZTJM+StmLmdmlVu+g4v6UI= dependencies: semver-compare "^1.0.0" plur@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/plur/download/plur-4.0.0.tgz#729aedb08f452645fe8c58ef115bf16b0a73ef84" + resolved "https://registry.npm.alibaba-inc.com/plur/download/plur-4.0.0.tgz" integrity sha1-cprtsI9FJkX+jFjvEVvxawpz74Q= dependencies: irregular-plurals "^3.2.0" pluralize@^8.0.0: version "8.0.0" - resolved "https://registry.npm.alibaba-inc.com/pluralize/download/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" + resolved "https://registry.npm.alibaba-inc.com/pluralize/download/pluralize-8.0.0.tgz" integrity sha1-Gm+hajjRKhkB4DIPoBcFHFOc47E= posix-character-classes@^0.1.0: version "0.1.1" - resolved "https://registry.npm.alibaba-inc.com/posix-character-classes/download/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + resolved "https://registry.npm.alibaba-inc.com/posix-character-classes/download/posix-character-classes-0.1.1.tgz" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= postcss-attribute-case-insensitive@^4.0.1: version "4.0.2" - resolved "https://registry.npm.alibaba-inc.com/postcss-attribute-case-insensitive/download/postcss-attribute-case-insensitive-4.0.2.tgz#d93e46b504589e94ac7277b0463226c68041a880" + resolved "https://registry.npm.alibaba-inc.com/postcss-attribute-case-insensitive/download/postcss-attribute-case-insensitive-4.0.2.tgz" integrity sha1-2T5GtQRYnpSscnewRjImxoBBqIA= dependencies: postcss "^7.0.2" @@ -7977,7 +9656,7 @@ postcss-attribute-case-insensitive@^4.0.1: postcss-color-functional-notation@^2.0.1: version "2.0.1" - resolved "https://registry.npm.alibaba-inc.com/postcss-color-functional-notation/download/postcss-color-functional-notation-2.0.1.tgz#5efd37a88fbabeb00a2966d1e53d98ced93f74e0" + resolved "https://registry.npm.alibaba-inc.com/postcss-color-functional-notation/download/postcss-color-functional-notation-2.0.1.tgz" integrity sha1-Xv03qI+6vrAKKWbR5T2Yztk/dOA= dependencies: postcss "^7.0.2" @@ -7985,7 +9664,7 @@ postcss-color-functional-notation@^2.0.1: postcss-color-gray@^5.0.0: version "5.0.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-color-gray/download/postcss-color-gray-5.0.0.tgz#532a31eb909f8da898ceffe296fdc1f864be8547" + resolved "https://registry.npm.alibaba-inc.com/postcss-color-gray/download/postcss-color-gray-5.0.0.tgz" integrity sha1-Uyox65CfjaiYzv/ilv3B+GS+hUc= dependencies: "@csstools/convert-colors" "^1.4.0" @@ -7994,7 +9673,7 @@ postcss-color-gray@^5.0.0: postcss-color-hex-alpha@^5.0.3: version "5.0.3" - resolved "https://registry.npm.alibaba-inc.com/postcss-color-hex-alpha/download/postcss-color-hex-alpha-5.0.3.tgz#a8d9ca4c39d497c9661e374b9c51899ef0f87388" + resolved "https://registry.npm.alibaba-inc.com/postcss-color-hex-alpha/download/postcss-color-hex-alpha-5.0.3.tgz" integrity sha1-qNnKTDnUl8lmHjdLnFGJnvD4c4g= dependencies: postcss "^7.0.14" @@ -8002,7 +9681,7 @@ postcss-color-hex-alpha@^5.0.3: postcss-color-mod-function@^3.0.3: version "3.0.3" - resolved "https://registry.npm.alibaba-inc.com/postcss-color-mod-function/download/postcss-color-mod-function-3.0.3.tgz#816ba145ac11cc3cb6baa905a75a49f903e4d31d" + resolved "https://registry.npm.alibaba-inc.com/postcss-color-mod-function/download/postcss-color-mod-function-3.0.3.tgz" integrity sha1-gWuhRawRzDy2uqkFp1pJ+QPk0x0= dependencies: "@csstools/convert-colors" "^1.4.0" @@ -8011,7 +9690,7 @@ postcss-color-mod-function@^3.0.3: postcss-color-rebeccapurple@^4.0.1: version "4.0.1" - resolved "https://registry.npm.alibaba-inc.com/postcss-color-rebeccapurple/download/postcss-color-rebeccapurple-4.0.1.tgz#c7a89be872bb74e45b1e3022bfe5748823e6de77" + resolved "https://registry.npm.alibaba-inc.com/postcss-color-rebeccapurple/download/postcss-color-rebeccapurple-4.0.1.tgz" integrity sha1-x6ib6HK7dORbHjAiv+V0iCPm3nc= dependencies: postcss "^7.0.2" @@ -8019,14 +9698,14 @@ postcss-color-rebeccapurple@^4.0.1: postcss-custom-media@^7.0.8: version "7.0.8" - resolved "https://registry.npm.alibaba-inc.com/postcss-custom-media/download/postcss-custom-media-7.0.8.tgz#fffd13ffeffad73621be5f387076a28b00294e0c" + resolved "https://registry.npm.alibaba-inc.com/postcss-custom-media/download/postcss-custom-media-7.0.8.tgz" integrity sha1-//0T/+/61zYhvl84cHaiiwApTgw= dependencies: postcss "^7.0.14" postcss-custom-properties@^8.0.11: version "8.0.11" - resolved "https://registry.npm.alibaba-inc.com/postcss-custom-properties/download/postcss-custom-properties-8.0.11.tgz#2d61772d6e92f22f5e0d52602df8fae46fa30d97" + resolved "https://registry.npm.alibaba-inc.com/postcss-custom-properties/download/postcss-custom-properties-8.0.11.tgz" integrity sha1-LWF3LW6S8i9eDVJgLfj65G+jDZc= dependencies: postcss "^7.0.17" @@ -8034,7 +9713,7 @@ postcss-custom-properties@^8.0.11: postcss-custom-selectors@^5.1.2: version "5.1.2" - resolved "https://registry.npm.alibaba-inc.com/postcss-custom-selectors/download/postcss-custom-selectors-5.1.2.tgz#64858c6eb2ecff2fb41d0b28c9dd7b3db4de7fba" + resolved "https://registry.npm.alibaba-inc.com/postcss-custom-selectors/download/postcss-custom-selectors-5.1.2.tgz" integrity sha1-ZIWMbrLs/y+0HQsoyd17PbTef7o= dependencies: postcss "^7.0.2" @@ -8042,7 +9721,7 @@ postcss-custom-selectors@^5.1.2: postcss-dir-pseudo-class@^5.0.0: version "5.0.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-dir-pseudo-class/download/postcss-dir-pseudo-class-5.0.0.tgz#6e3a4177d0edb3abcc85fdb6fbb1c26dabaeaba2" + resolved "https://registry.npm.alibaba-inc.com/postcss-dir-pseudo-class/download/postcss-dir-pseudo-class-5.0.0.tgz" integrity sha1-bjpBd9Dts6vMhf22+7HCbauuq6I= dependencies: postcss "^7.0.2" @@ -8050,7 +9729,7 @@ postcss-dir-pseudo-class@^5.0.0: postcss-double-position-gradients@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-double-position-gradients/download/postcss-double-position-gradients-1.0.0.tgz#fc927d52fddc896cb3a2812ebc5df147e110522e" + resolved "https://registry.npm.alibaba-inc.com/postcss-double-position-gradients/download/postcss-double-position-gradients-1.0.0.tgz" integrity sha1-/JJ9Uv3ciWyzooEuvF3xR+EQUi4= dependencies: postcss "^7.0.5" @@ -8058,7 +9737,7 @@ postcss-double-position-gradients@^1.0.0: postcss-env-function@^2.0.2: version "2.0.2" - resolved "https://registry.npm.alibaba-inc.com/postcss-env-function/download/postcss-env-function-2.0.2.tgz#0f3e3d3c57f094a92c2baf4b6241f0b0da5365d7" + resolved "https://registry.npm.alibaba-inc.com/postcss-env-function/download/postcss-env-function-2.0.2.tgz" integrity sha1-Dz49PFfwlKksK69LYkHwsNpTZdc= dependencies: postcss "^7.0.2" @@ -8066,49 +9745,49 @@ postcss-env-function@^2.0.2: postcss-flexbugs-fixes@4.2.1: version "4.2.1" - resolved "https://registry.npm.alibaba-inc.com/postcss-flexbugs-fixes/download/postcss-flexbugs-fixes-4.2.1.tgz#9218a65249f30897deab1033aced8578562a6690" + resolved "https://registry.npm.alibaba-inc.com/postcss-flexbugs-fixes/download/postcss-flexbugs-fixes-4.2.1.tgz" integrity sha1-khimUknzCJfeqxAzrO2FeFYqZpA= dependencies: postcss "^7.0.26" postcss-focus-visible@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-focus-visible/download/postcss-focus-visible-4.0.0.tgz#477d107113ade6024b14128317ade2bd1e17046e" + resolved "https://registry.npm.alibaba-inc.com/postcss-focus-visible/download/postcss-focus-visible-4.0.0.tgz" integrity sha1-R30QcROt5gJLFBKDF63ivR4XBG4= dependencies: postcss "^7.0.2" postcss-focus-within@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-focus-within/download/postcss-focus-within-3.0.0.tgz#763b8788596cee9b874c999201cdde80659ef680" + resolved "https://registry.npm.alibaba-inc.com/postcss-focus-within/download/postcss-focus-within-3.0.0.tgz" integrity sha1-djuHiFls7puHTJmSAc3egGWe9oA= dependencies: postcss "^7.0.2" postcss-font-variant@^4.0.0: version "4.0.1" - resolved "https://registry.npm.alibaba-inc.com/postcss-font-variant/download/postcss-font-variant-4.0.1.tgz#42d4c0ab30894f60f98b17561eb5c0321f502641" + resolved "https://registry.npm.alibaba-inc.com/postcss-font-variant/download/postcss-font-variant-4.0.1.tgz" integrity sha1-QtTAqzCJT2D5ixdWHrXAMh9QJkE= dependencies: postcss "^7.0.2" postcss-gap-properties@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-gap-properties/download/postcss-gap-properties-2.0.0.tgz#431c192ab3ed96a3c3d09f2ff615960f902c1715" + resolved "https://registry.npm.alibaba-inc.com/postcss-gap-properties/download/postcss-gap-properties-2.0.0.tgz" integrity sha1-QxwZKrPtlqPD0J8v9hWWD5AsFxU= dependencies: postcss "^7.0.2" postcss-html@^0.36.0: version "0.36.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-html/download/postcss-html-0.36.0.tgz#b40913f94eaacc2453fd30a1327ad6ee1f88b204" + resolved "https://registry.npm.alibaba-inc.com/postcss-html/download/postcss-html-0.36.0.tgz" integrity sha1-tAkT+U6qzCRT/TChMnrW7h+IsgQ= dependencies: htmlparser2 "^3.10.0" postcss-image-set-function@^3.0.1: version "3.0.1" - resolved "https://registry.npm.alibaba-inc.com/postcss-image-set-function/download/postcss-image-set-function-3.0.1.tgz#28920a2f29945bed4c3198d7df6496d410d3f288" + resolved "https://registry.npm.alibaba-inc.com/postcss-image-set-function/download/postcss-image-set-function-3.0.1.tgz" integrity sha1-KJIKLymUW+1MMZjX32SW1BDT8og= dependencies: postcss "^7.0.2" @@ -8116,14 +9795,14 @@ postcss-image-set-function@^3.0.1: postcss-initial@^3.0.0: version "3.0.4" - resolved "https://registry.npm.alibaba-inc.com/postcss-initial/download/postcss-initial-3.0.4.tgz#9d32069a10531fe2ecafa0b6ac750ee0bc7efc53" + resolved "https://registry.npm.alibaba-inc.com/postcss-initial/download/postcss-initial-3.0.4.tgz" integrity sha1-nTIGmhBTH+Lsr6C2rHUO4Lx+/FM= dependencies: postcss "^7.0.2" postcss-lab-function@^2.0.1: version "2.0.1" - resolved "https://registry.npm.alibaba-inc.com/postcss-lab-function/download/postcss-lab-function-2.0.1.tgz#bb51a6856cd12289ab4ae20db1e3821ef13d7d2e" + resolved "https://registry.npm.alibaba-inc.com/postcss-lab-function/download/postcss-lab-function-2.0.1.tgz" integrity sha1-u1GmhWzRIomrSuINseOCHvE9fS4= dependencies: "@csstools/convert-colors" "^1.4.0" @@ -8132,21 +9811,21 @@ postcss-lab-function@^2.0.1: postcss-less@^3.1.4: version "3.1.4" - resolved "https://registry.npm.alibaba-inc.com/postcss-less/download/postcss-less-3.1.4.tgz#369f58642b5928ef898ffbc1a6e93c958304c5ad" + resolved "https://registry.npm.alibaba-inc.com/postcss-less/download/postcss-less-3.1.4.tgz" integrity sha1-Np9YZCtZKO+Jj/vBpuk8lYMExa0= dependencies: postcss "^7.0.14" postcss-less@^4.0.0: version "4.0.1" - resolved "https://registry.npm.alibaba-inc.com/postcss-less/download/postcss-less-4.0.1.tgz#73caf5dac056d4b706f4cc136cefeaf4e79067a4" + resolved "https://registry.npm.alibaba-inc.com/postcss-less/download/postcss-less-4.0.1.tgz" integrity sha1-c8r12sBW1LcG9MwTbO/q9OeQZ6Q= dependencies: postcss "^8.1.2" postcss-load-config@^2.0.0: version "2.1.2" - resolved "https://registry.npm.alibaba-inc.com/postcss-load-config/download/postcss-load-config-2.1.2.tgz#c5ea504f2c4aef33c7359a34de3573772ad7502a" + resolved "https://registry.npm.alibaba-inc.com/postcss-load-config/download/postcss-load-config-2.1.2.tgz" integrity sha1-xepQTyxK7zPHNZo03jVzdyrXUCo= dependencies: cosmiconfig "^5.0.0" @@ -8154,7 +9833,7 @@ postcss-load-config@^2.0.0: postcss-loader@3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-loader/download/postcss-loader-3.0.0.tgz#6b97943e47c72d845fa9e03f273773d4e8dd6c2d" + resolved "https://registry.npm.alibaba-inc.com/postcss-loader/download/postcss-loader-3.0.0.tgz" integrity sha1-a5eUPkfHLYRfqeA/Jzdz1OjdbC0= dependencies: loader-utils "^1.1.0" @@ -8164,47 +9843,47 @@ postcss-loader@3.0.0: postcss-logical@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-logical/download/postcss-logical-3.0.0.tgz#2495d0f8b82e9f262725f75f9401b34e7b45d5b5" + resolved "https://registry.npm.alibaba-inc.com/postcss-logical/download/postcss-logical-3.0.0.tgz" integrity sha1-JJXQ+LgunyYnJfdflAGzTntF1bU= dependencies: postcss "^7.0.2" postcss-media-minmax@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-media-minmax/download/postcss-media-minmax-4.0.0.tgz#b75bb6cbc217c8ac49433e12f22048814a4f5ed5" + resolved "https://registry.npm.alibaba-inc.com/postcss-media-minmax/download/postcss-media-minmax-4.0.0.tgz" integrity sha1-t1u2y8IXyKxJQz4S8iBIgUpPXtU= dependencies: postcss "^7.0.2" postcss-media-query-parser@^0.2.3: version "0.2.3" - resolved "https://registry.npm.alibaba-inc.com/postcss-media-query-parser/download/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244" + resolved "https://registry.npm.alibaba-inc.com/postcss-media-query-parser/download/postcss-media-query-parser-0.2.3.tgz" integrity sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ= postcss-nesting@^7.0.0: version "7.0.1" - resolved "https://registry.npm.alibaba-inc.com/postcss-nesting/download/postcss-nesting-7.0.1.tgz#b50ad7b7f0173e5b5e3880c3501344703e04c052" + resolved "https://registry.npm.alibaba-inc.com/postcss-nesting/download/postcss-nesting-7.0.1.tgz" integrity sha1-tQrXt/AXPlteOIDDUBNEcD4EwFI= dependencies: postcss "^7.0.2" postcss-overflow-shorthand@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-overflow-shorthand/download/postcss-overflow-shorthand-2.0.0.tgz#31ecf350e9c6f6ddc250a78f0c3e111f32dd4c30" + resolved "https://registry.npm.alibaba-inc.com/postcss-overflow-shorthand/download/postcss-overflow-shorthand-2.0.0.tgz" integrity sha1-MezzUOnG9t3CUKePDD4RHzLdTDA= dependencies: postcss "^7.0.2" postcss-page-break@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-page-break/download/postcss-page-break-2.0.0.tgz#add52d0e0a528cabe6afee8b46e2abb277df46bf" + resolved "https://registry.npm.alibaba-inc.com/postcss-page-break/download/postcss-page-break-2.0.0.tgz" integrity sha1-rdUtDgpSjKvmr+6LRuKrsnffRr8= dependencies: postcss "^7.0.2" postcss-place@^4.0.1: version "4.0.1" - resolved "https://registry.npm.alibaba-inc.com/postcss-place/download/postcss-place-4.0.1.tgz#e9f39d33d2dc584e46ee1db45adb77ca9d1dcc62" + resolved "https://registry.npm.alibaba-inc.com/postcss-place/download/postcss-place-4.0.1.tgz" integrity sha1-6fOdM9LcWE5G7h20Wtt3yp0dzGI= dependencies: postcss "^7.0.2" @@ -8212,7 +9891,7 @@ postcss-place@^4.0.1: postcss-preset-env@6.7.0: version "6.7.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-preset-env/download/postcss-preset-env-6.7.0.tgz#c34ddacf8f902383b35ad1e030f178f4cdf118a5" + resolved "https://registry.npm.alibaba-inc.com/postcss-preset-env/download/postcss-preset-env-6.7.0.tgz" integrity sha1-w03az4+QI4OzWtHgMPF49M3xGKU= dependencies: autoprefixer "^9.6.1" @@ -8255,7 +9934,7 @@ postcss-preset-env@6.7.0: postcss-pseudo-class-any-link@^6.0.0: version "6.0.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-pseudo-class-any-link/download/postcss-pseudo-class-any-link-6.0.0.tgz#2ed3eed393b3702879dec4a87032b210daeb04d1" + resolved "https://registry.npm.alibaba-inc.com/postcss-pseudo-class-any-link/download/postcss-pseudo-class-any-link-6.0.0.tgz" integrity sha1-LtPu05OzcCh53sSocDKyENrrBNE= dependencies: postcss "^7.0.2" @@ -8263,26 +9942,26 @@ postcss-pseudo-class-any-link@^6.0.0: postcss-replace-overflow-wrap@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-replace-overflow-wrap/download/postcss-replace-overflow-wrap-3.0.0.tgz#61b360ffdaedca84c7c918d2b0f0d0ea559ab01c" + resolved "https://registry.npm.alibaba-inc.com/postcss-replace-overflow-wrap/download/postcss-replace-overflow-wrap-3.0.0.tgz" integrity sha1-YbNg/9rtyoTHyRjSsPDQ6lWasBw= dependencies: postcss "^7.0.2" postcss-resolve-nested-selector@^0.1.1: version "0.1.1" - resolved "https://registry.npm.alibaba-inc.com/postcss-resolve-nested-selector/download/postcss-resolve-nested-selector-0.1.1.tgz#29ccbc7c37dedfac304e9fff0bf1596b3f6a0e4e" + resolved "https://registry.npm.alibaba-inc.com/postcss-resolve-nested-selector/download/postcss-resolve-nested-selector-0.1.1.tgz" integrity sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4= postcss-safe-parser@4.0.2, postcss-safe-parser@^4.0.2: version "4.0.2" - resolved "https://registry.npm.alibaba-inc.com/postcss-safe-parser/download/postcss-safe-parser-4.0.2.tgz#a6d4e48f0f37d9f7c11b2a581bf00f8ba4870b96" + resolved "https://registry.npm.alibaba-inc.com/postcss-safe-parser/download/postcss-safe-parser-4.0.2.tgz" integrity sha1-ptTkjw832ffBGypYG/APi6SHC5Y= dependencies: postcss "^7.0.26" postcss-sass@^0.4.4: version "0.4.4" - resolved "https://registry.npm.alibaba-inc.com/postcss-sass/download/postcss-sass-0.4.4.tgz#91f0f3447b45ce373227a98b61f8d8f0785285a3" + resolved "https://registry.npm.alibaba-inc.com/postcss-sass/download/postcss-sass-0.4.4.tgz" integrity sha1-kfDzRHtFzjcyJ6mLYfjY8HhShaM= dependencies: gonzales-pe "^4.3.0" @@ -8290,14 +9969,14 @@ postcss-sass@^0.4.4: postcss-scss@^2.1.1: version "2.1.1" - resolved "https://registry.npm.alibaba-inc.com/postcss-scss/download/postcss-scss-2.1.1.tgz#ec3a75fa29a55e016b90bf3269026c53c1d2b383" + resolved "https://registry.npm.alibaba-inc.com/postcss-scss/download/postcss-scss-2.1.1.tgz" integrity sha1-7Dp1+imlXgFrkL8yaQJsU8HSs4M= dependencies: postcss "^7.0.6" postcss-selector-matches@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-selector-matches/download/postcss-selector-matches-4.0.0.tgz#71c8248f917ba2cc93037c9637ee09c64436fcff" + resolved "https://registry.npm.alibaba-inc.com/postcss-selector-matches/download/postcss-selector-matches-4.0.0.tgz" integrity sha1-ccgkj5F7osyTA3yWN+4JxkQ2/P8= dependencies: balanced-match "^1.0.0" @@ -8305,7 +9984,7 @@ postcss-selector-matches@^4.0.0: postcss-selector-not@^4.0.0: version "4.0.1" - resolved "https://registry.npm.alibaba-inc.com/postcss-selector-not/download/postcss-selector-not-4.0.1.tgz#263016eef1cf219e0ade9a913780fc1f48204cbf" + resolved "https://registry.npm.alibaba-inc.com/postcss-selector-not/download/postcss-selector-not-4.0.1.tgz" integrity sha1-JjAW7vHPIZ4K3pqRN4D8H0ggTL8= dependencies: balanced-match "^1.0.0" @@ -8313,7 +9992,7 @@ postcss-selector-not@^4.0.0: postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4: version "5.0.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-selector-parser/download/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" + resolved "https://registry.npm.alibaba-inc.com/postcss-selector-parser/download/postcss-selector-parser-5.0.0.tgz" integrity sha1-JJBENWaXsztk8aj3yAki3d7nGVw= dependencies: cssesc "^2.0.0" @@ -8322,7 +10001,7 @@ postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4: postcss-selector-parser@^6.0.2: version "6.0.10" - resolved "https://registry.npm.alibaba-inc.com/postcss-selector-parser/download/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d" + resolved "https://registry.npm.alibaba-inc.com/postcss-selector-parser/download/postcss-selector-parser-6.0.10.tgz" integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w== dependencies: cssesc "^3.0.0" @@ -8330,7 +10009,7 @@ postcss-selector-parser@^6.0.2: postcss-selector-parser@^6.0.5: version "6.0.11" - resolved "https://registry.npm.alibaba-inc.com/postcss-selector-parser/download/postcss-selector-parser-6.0.11.tgz#2e41dc39b7ad74046e1615185185cd0b17d0c8dc" + resolved "https://registry.npm.alibaba-inc.com/postcss-selector-parser/download/postcss-selector-parser-6.0.11.tgz" integrity sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g== dependencies: cssesc "^3.0.0" @@ -8338,24 +10017,24 @@ postcss-selector-parser@^6.0.5: postcss-sorting@6.0.0: version "6.0.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-sorting/download/postcss-sorting-6.0.0.tgz#2981c879bf324425ee5a19153c4d693cf60f94d5" + resolved "https://registry.npm.alibaba-inc.com/postcss-sorting/download/postcss-sorting-6.0.0.tgz" integrity sha1-KYHIeb8yRCXuWhkVPE1pPPYPlNU= dependencies: lodash "^4.17.20" postcss-syntax@^0.36.2: version "0.36.2" - resolved "https://registry.npm.alibaba-inc.com/postcss-syntax/download/postcss-syntax-0.36.2.tgz#f08578c7d95834574e5593a82dfbfa8afae3b51c" + resolved "https://registry.npm.alibaba-inc.com/postcss-syntax/download/postcss-syntax-0.36.2.tgz" integrity sha1-8IV4x9lYNFdOVZOoLfv6ivrjtRw= postcss-value-parser@^4.1.0: version "4.2.0" - resolved "https://registry.npm.alibaba-inc.com/postcss-value-parser/download/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + resolved "https://registry.npm.alibaba-inc.com/postcss-value-parser/download/postcss-value-parser-4.2.0.tgz" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: version "2.0.1" - resolved "https://registry.npm.alibaba-inc.com/postcss-values-parser/download/postcss-values-parser-2.0.1.tgz#da8b472d901da1e205b47bdc98637b9e9e550e5f" + resolved "https://registry.npm.alibaba-inc.com/postcss-values-parser/download/postcss-values-parser-2.0.1.tgz" integrity sha1-2otHLZAdoeIFtHvcmGN7np5VDl8= dependencies: flatten "^1.0.2" @@ -8364,7 +10043,7 @@ postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: postcss@7.0.32: version "7.0.32" - resolved "https://registry.npm.alibaba-inc.com/postcss/download/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" + resolved "https://registry.npm.alibaba-inc.com/postcss/download/postcss-7.0.32.tgz" integrity sha1-QxDW7jRwU9o0M9sr5JKIPWLOxZ0= dependencies: chalk "^2.4.2" @@ -8373,7 +10052,7 @@ postcss@7.0.32: postcss@^7.0.0, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.21, postcss@^7.0.26, postcss@^7.0.32, postcss@^7.0.35, postcss@^7.0.5, postcss@^7.0.6: version "7.0.39" - resolved "https://registry.npm.alibaba-inc.com/postcss/download/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309" + resolved "https://registry.npm.alibaba-inc.com/postcss/download/postcss-7.0.39.tgz" integrity sha1-liQ3XZZWMOLh8sAqk1yCpZy0gwk= dependencies: picocolors "^0.2.1" @@ -8381,7 +10060,7 @@ postcss@^7.0.0, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.2 postcss@^8.1.2, postcss@^8.3.6: version "8.4.19" - resolved "https://registry.npm.alibaba-inc.com/postcss/download/postcss-8.4.19.tgz#61178e2add236b17351897c8bcc0b4c8ecab56fc" + resolved "https://registry.npm.alibaba-inc.com/postcss/download/postcss-8.4.19.tgz" integrity sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA== dependencies: nanoid "^3.3.4" @@ -8390,29 +10069,29 @@ postcss@^8.1.2, postcss@^8.3.6: prelude-ls@^1.2.1: version "1.2.1" - resolved "https://registry.npm.alibaba-inc.com/prelude-ls/download/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + resolved "https://registry.npm.alibaba-inc.com/prelude-ls/download/prelude-ls-1.2.1.tgz" integrity sha1-3rxkidem5rDnYRiIzsiAM30xY5Y= prelude-ls@~1.1.2: version "1.1.2" - resolved "https://registry.npm.alibaba-inc.com/prelude-ls/download/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + resolved "https://registry.npm.alibaba-inc.com/prelude-ls/download/prelude-ls-1.1.2.tgz" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= prepend-http@^1.0.0: version "1.0.4" - resolved "https://registry.npm.alibaba-inc.com/prepend-http/download/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + resolved "https://registry.npm.alibaba-inc.com/prepend-http/download/prepend-http-1.0.4.tgz" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= prettier-plugin-packagejson@^2.2.18: version "2.3.0" - resolved "https://registry.npm.alibaba-inc.com/prettier-plugin-packagejson/download/prettier-plugin-packagejson-2.3.0.tgz#5c242a39627c227d813161618fa88e64e44e9c84" + resolved "https://registry.npm.alibaba-inc.com/prettier-plugin-packagejson/download/prettier-plugin-packagejson-2.3.0.tgz" integrity sha512-2SAPMMk1UDkqsB7DifWKcwCm6VC52JXMrzLHfbcQHJRWhRCj9zziOy+s+2XOyPBeyqFqS+A/1IKzOrxKFTo6pw== dependencies: sort-package-json "1.57.0" prettier-plugin-two-style-order@^1.0.0: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/prettier-plugin-two-style-order/download/prettier-plugin-two-style-order-1.0.1.tgz#a10c6a385f05cc79dbe5848cbcee89d58f0a885d" + resolved "https://registry.npm.alibaba-inc.com/prettier-plugin-two-style-order/download/prettier-plugin-two-style-order-1.0.1.tgz" integrity sha1-oQxqOF8FzHnb5YSMvO6J1Y8KiF0= dependencies: postcss "^8.3.6" @@ -8421,17 +10100,17 @@ prettier-plugin-two-style-order@^1.0.0: prettier@2.2.1: version "2.2.1" - resolved "https://registry.npm.alibaba-inc.com/prettier/download/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5" + resolved "https://registry.npm.alibaba-inc.com/prettier/download/prettier-2.2.1.tgz" integrity sha1-eVoaeN1S8HPaDNQrIfnJE4GSP/U= prettier@2.7.1, prettier@^2.2.1, prettier@^2.3.2: version "2.7.1" - resolved "https://registry.npm.alibaba-inc.com/prettier/download/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" + resolved "https://registry.npm.alibaba-inc.com/prettier/download/prettier-2.7.1.tgz" integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== pretty-format@^26.6.2: version "26.6.2" - resolved "https://registry.npm.alibaba-inc.com/pretty-format/download/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" + resolved "https://registry.npm.alibaba-inc.com/pretty-format/download/pretty-format-26.6.2.tgz" integrity sha1-41wnBfFMt/4v6U+geDRbREEg/JM= dependencies: "@jest/types" "^26.6.2" @@ -8439,31 +10118,41 @@ pretty-format@^26.6.2: ansi-styles "^4.0.0" react-is "^17.0.1" +probe.gl@^3.1.1: + version "3.6.0" + resolved "https://registry.npmjs.org/probe.gl/-/probe.gl-3.6.0.tgz" + integrity sha512-19JydJWI7+DtR4feV+pu4Mn1I5TAc0xojuxVgZdXIyfmTLfUaFnk4OloWK1bKbPtkgGKLr2lnbnCXmpZEcEp9g== + dependencies: + "@babel/runtime" "^7.0.0" + "@probe.gl/env" "3.6.0" + "@probe.gl/log" "3.6.0" + "@probe.gl/stats" "3.6.0" + process-nextick-args@~2.0.0: version "2.0.1" - resolved "https://registry.npm.alibaba-inc.com/process-nextick-args/download/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + resolved "https://registry.npm.alibaba-inc.com/process-nextick-args/download/process-nextick-args-2.0.1.tgz" integrity sha1-eCDZsWEgzFXKmud5JoCufbptf+I= process@^0.11.10: version "0.11.10" - resolved "https://registry.npm.alibaba-inc.com/process/download/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + resolved "https://registry.npm.alibaba-inc.com/process/download/process-0.11.10.tgz" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= progress@^2.0.0: version "2.0.3" - resolved "https://registry.npm.alibaba-inc.com/progress/download/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + resolved "https://registry.npm.alibaba-inc.com/progress/download/progress-2.0.3.tgz" integrity sha1-foz42PW48jnBvGi+tOt4Vn1XLvg= promise@^7.1.1: version "7.3.1" - resolved "https://registry.npm.alibaba-inc.com/promise/download/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + resolved "https://registry.npm.alibaba-inc.com/promise/download/promise-7.3.1.tgz" integrity sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078= dependencies: asap "~2.0.3" prompts@^2.0.1: version "2.4.2" - resolved "https://registry.npm.alibaba-inc.com/prompts/download/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + resolved "https://registry.npm.alibaba-inc.com/prompts/download/prompts-2.4.2.tgz" integrity sha1-e1fnOzpIAprRDr1E90sBcipMsGk= dependencies: kleur "^3.0.3" @@ -8471,7 +10160,7 @@ prompts@^2.0.1: prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" - resolved "https://registry.npm.alibaba-inc.com/prop-types/download/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + resolved "https://registry.npm.alibaba-inc.com/prop-types/download/prop-types-15.8.1.tgz" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== dependencies: loose-envify "^1.4.0" @@ -8480,17 +10169,17 @@ prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6, pr pseudomap@^1.0.2: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/pseudomap/download/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + resolved "https://registry.npm.alibaba-inc.com/pseudomap/download/pseudomap-1.0.2.tgz" integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.33: version "1.9.0" - resolved "https://registry.npm.alibaba-inc.com/psl/download/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + resolved "https://registry.npm.alibaba-inc.com/psl/download/psl-1.9.0.tgz" integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== public-encrypt@^4.0.0: version "4.0.3" - resolved "https://registry.npm.alibaba-inc.com/public-encrypt/download/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + resolved "https://registry.npm.alibaba-inc.com/public-encrypt/download/public-encrypt-4.0.3.tgz" integrity sha1-T8ydd6B+SLp1J+fL4N4z0HATMeA= dependencies: bn.js "^4.1.0" @@ -8502,7 +10191,7 @@ public-encrypt@^4.0.0: pump@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/pump/download/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + resolved "https://registry.npm.alibaba-inc.com/pump/download/pump-3.0.0.tgz" integrity sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ= dependencies: end-of-stream "^1.1.0" @@ -8510,36 +10199,51 @@ pump@^3.0.0: punycode@1.3.2: version "1.3.2" - resolved "https://registry.npm.alibaba-inc.com/punycode/download/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + resolved "https://registry.npm.alibaba-inc.com/punycode/download/punycode-1.3.2.tgz" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= punycode@^1.2.4: version "1.4.1" - resolved "https://registry.npm.alibaba-inc.com/punycode/download/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + resolved "https://registry.npm.alibaba-inc.com/punycode/download/punycode-1.4.1.tgz" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" - resolved "https://registry.npm.alibaba-inc.com/punycode/download/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + resolved "https://registry.npm.alibaba-inc.com/punycode/download/punycode-2.1.1.tgz" integrity sha1-tYsBCsQMIsVldhbI0sLALHv0eew= +pure-color@^1.2.0: + version "1.3.0" + resolved "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz" + integrity sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA== + +q@^1.1.2: + version "1.5.1" + resolved "https://registry.npmjs.org/q/-/q-1.5.1.tgz" + integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw== + +qrcode.react@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz" + integrity sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q== + qs@^6.9.0: version "6.11.1" - resolved "https://registry.npm.alibaba-inc.com/qs/download/qs-6.11.1.tgz#6c29dff97f0c0060765911ba65cbc9764186109f" + resolved "https://registry.npm.alibaba-inc.com/qs/download/qs-6.11.1.tgz" integrity sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ== dependencies: side-channel "^1.0.4" qs@^6.9.1: version "6.11.0" - resolved "https://registry.npm.alibaba-inc.com/qs/download/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + resolved "https://registry.npm.alibaba-inc.com/qs/download/qs-6.11.0.tgz" integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== dependencies: side-channel "^1.0.4" query-string@^4.1.0: version "4.3.4" - resolved "https://registry.npm.alibaba-inc.com/query-string/download/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" + resolved "https://registry.npm.alibaba-inc.com/query-string/download/query-string-4.3.4.tgz" integrity sha1-u7aTucqRXCMlFbIosaArYJBD2+s= dependencies: object-assign "^4.1.0" @@ -8547,7 +10251,7 @@ query-string@^4.1.0: query-string@^6.11.0: version "6.14.1" - resolved "https://registry.npm.alibaba-inc.com/query-string/download/query-string-6.14.1.tgz#7ac2dca46da7f309449ba0f86b1fd28255b0c86a" + resolved "https://registry.npm.alibaba-inc.com/query-string/download/query-string-6.14.1.tgz" integrity sha1-esLcpG2n8wlEm6D4ax/SglWwyGo= dependencies: decode-uri-component "^0.2.0" @@ -8555,56 +10259,70 @@ query-string@^6.11.0: split-on-first "^1.0.0" strict-uri-encode "^2.0.0" +query-string@^8.1.0: + version "8.1.0" + resolved "https://registry.npmjs.org/query-string/-/query-string-8.1.0.tgz" + integrity sha512-BFQeWxJOZxZGix7y+SByG3F36dA0AbTy9o6pSmKFcFz7DAj0re9Frkty3saBn3nHo3D0oZJ/+rx3r8H8r8Jbpw== + dependencies: + decode-uri-component "^0.4.1" + filter-obj "^5.1.0" + split-on-first "^3.0.0" + querystring-es3@^0.2.0: version "0.2.1" - resolved "https://registry.npm.alibaba-inc.com/querystring-es3/download/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + resolved "https://registry.npm.alibaba-inc.com/querystring-es3/download/querystring-es3-0.2.1.tgz" integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= querystring@0.2.0: version "0.2.0" - resolved "https://registry.npm.alibaba-inc.com/querystring/download/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + resolved "https://registry.npm.alibaba-inc.com/querystring/download/querystring-0.2.0.tgz" integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= querystringify@^2.1.1: version "2.2.0" - resolved "https://registry.npm.alibaba-inc.com/querystringify/download/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + resolved "https://registry.npm.alibaba-inc.com/querystringify/download/querystringify-2.2.0.tgz" integrity sha1-M0WUG0FTy50ILY7uTNogFqmu9/Y= queue-microtask@^1.2.2: version "1.2.3" - resolved "https://registry.npm.alibaba-inc.com/queue-microtask/download/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + resolved "https://registry.npm.alibaba-inc.com/queue-microtask/download/queue-microtask-1.2.3.tgz" integrity sha1-SSkii7xyTfrEPg77BYyve2z7YkM= quick-lru@^4.0.1: version "4.0.1" - resolved "https://registry.npm.alibaba-inc.com/quick-lru/download/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" + resolved "https://registry.npm.alibaba-inc.com/quick-lru/download/quick-lru-4.0.1.tgz" integrity sha1-W4h48ROlgheEjGSCAmxz4bpXcn8= raf@^3.1.0, raf@^3.3.2, raf@^3.4.0: version "3.4.1" - resolved "https://registry.npm.alibaba-inc.com/raf/download/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" + resolved "https://registry.npm.alibaba-inc.com/raf/download/raf-3.4.1.tgz" integrity sha1-B0LpmkplUvRF1z4+4DKK8P8e3jk= dependencies: performance-now "^2.1.0" -randexp@0.5.3: +ramda@^0.27.0: + version "0.27.2" + resolved "https://registry.npmjs.org/ramda/-/ramda-0.27.2.tgz" + integrity sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA== + +randexp@0.5.3, randexp@^0.5.3: version "0.5.3" - resolved "https://registry.npm.alibaba-inc.com/randexp/download/randexp-0.5.3.tgz#f31c2de3148b30bdeb84b7c3f59b0ebb9fec3738" - integrity sha1-8xwt4xSLML3rhLfD9ZsOu5/sNzg= + resolved "https://registry.npmjs.org/randexp/-/randexp-0.5.3.tgz" + integrity sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w== dependencies: drange "^1.0.2" ret "^0.2.0" randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/randombytes/download/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + resolved "https://registry.npm.alibaba-inc.com/randombytes/download/randombytes-2.1.0.tgz" integrity sha1-32+ENy8CcNxlzfYpE0mrekc9Tyo= dependencies: safe-buffer "^5.1.0" randomfill@^1.0.3: version "1.0.4" - resolved "https://registry.npm.alibaba-inc.com/randomfill/download/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + resolved "https://registry.npm.alibaba-inc.com/randomfill/download/randomfill-1.0.4.tgz" integrity sha1-ySGW/IarQr6YPxvzF3giSTHWFFg= dependencies: randombytes "^2.0.5" @@ -8612,12 +10330,12 @@ randomfill@^1.0.3: range-parser@~1.2.1: version "1.2.1" - resolved "https://registry.npm.alibaba-inc.com/range-parser/download/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + resolved "https://registry.npm.alibaba-inc.com/range-parser/download/range-parser-1.2.1.tgz" integrity sha1-PPNwI9GZ4cJNGlW4SADC8+ZGgDE= rc-align@^2.4.0: version "2.4.5" - resolved "https://registry.npm.alibaba-inc.com/rc-align/download/rc-align-2.4.5.tgz#c941a586f59d1017f23a428f0b468663fb7102ab" + resolved "https://registry.npm.alibaba-inc.com/rc-align/download/rc-align-2.4.5.tgz" integrity sha1-yUGlhvWdEBfyOkKPC0aGY/txAqs= dependencies: babel-runtime "^6.26.0" @@ -8627,7 +10345,7 @@ rc-align@^2.4.0: rc-align@^4.0.0: version "4.0.12" - resolved "https://registry.npm.alibaba-inc.com/rc-align/download/rc-align-4.0.12.tgz#065b5c68a1cc92a00800c9239320d9fdf5f16207" + resolved "https://registry.npm.alibaba-inc.com/rc-align/download/rc-align-4.0.12.tgz" integrity sha512-3DuwSJp8iC/dgHzwreOQl52soj40LchlfUHtgACOUtwGuoFIOVh6n/sCpfqCU8kO5+iz6qR0YKvjgB8iPdE3aQ== dependencies: "@babel/runtime" "^7.10.1" @@ -8637,10 +10355,10 @@ rc-align@^4.0.0: rc-util "^5.3.0" resize-observer-polyfill "^1.5.1" -rc-animate@2.x, rc-animate@^2.4.4: +rc-animate@2.x, rc-animate@^2.10.2, rc-animate@^2.3.0, rc-animate@^2.4.4: version "2.11.1" - resolved "https://registry.npm.alibaba-inc.com/rc-animate/download/rc-animate-2.11.1.tgz#2666eeb6f1f2a495a13b2af09e236712278fdb2c" - integrity sha1-JmbutvHypJWhOyrwniNnEieP2yw= + resolved "https://registry.npmjs.org/rc-animate/-/rc-animate-2.11.1.tgz" + integrity sha512-1NyuCGFJG/0Y+9RKh5y/i/AalUCA51opyyS/jO2seELpgymZm2u9QV3xwODwEuzkmeQ1BDPxMLmYLcTJedPlkQ== dependencies: babel-runtime "6.x" classnames "^2.2.6" @@ -8650,9 +10368,21 @@ rc-animate@2.x, rc-animate@^2.4.4: rc-util "^4.15.3" react-lifecycles-compat "^3.0.4" +rc-cascader@~3.16.0: + version "3.16.0" + resolved "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.16.0.tgz" + integrity sha512-c62glOhm66T0/Y8vOfIgZwHHTbqCyC7FvBTcNDuwbXZc8Dfbz6fB1yIuCB55z5rPA7nsUfMyNNuS8shReZWM+A== + dependencies: + "@babel/runtime" "^7.12.5" + array-tree-filter "^2.1.0" + classnames "^2.3.1" + rc-select "~14.8.0" + rc-tree "~5.7.0" + rc-util "^5.35.0" + rc-cascader@~3.7.0: version "3.7.0" - resolved "https://registry.npm.alibaba-inc.com/rc-cascader/download/rc-cascader-3.7.0.tgz#98134df578ce1cca22be8fb4319b04df4f3dca36" + resolved "https://registry.npm.alibaba-inc.com/rc-cascader/download/rc-cascader-3.7.0.tgz" integrity sha512-SFtGpwmYN7RaWEAGTS4Rkc62ZV/qmQGg/tajr/7mfIkleuu8ro9Hlk6J+aA0x1YS4zlaZBtTcSaXM01QMiEV/A== dependencies: "@babel/runtime" "^7.12.5" @@ -8664,7 +10394,7 @@ rc-cascader@~3.7.0: rc-checkbox@~2.0.0: version "2.0.3" - resolved "https://registry.npm.alibaba-inc.com/rc-checkbox/download/rc-checkbox-2.0.3.tgz#436a9d508948e224980f0535ea738b48177a8f25" + resolved "https://registry.npm.alibaba-inc.com/rc-checkbox/download/rc-checkbox-2.0.3.tgz" integrity sha1-Q2qdUIlI4iSYDwU16nOLSBd6jyU= dependencies: babel-runtime "^6.23.0" @@ -8674,15 +10404,24 @@ rc-checkbox@~2.0.0: rc-checkbox@~2.3.0: version "2.3.2" - resolved "https://registry.npm.alibaba-inc.com/rc-checkbox/download/rc-checkbox-2.3.2.tgz#f91b3678c7edb2baa8121c9483c664fa6f0aefc1" + resolved "https://registry.npm.alibaba-inc.com/rc-checkbox/download/rc-checkbox-2.3.2.tgz" integrity sha1-+Rs2eMftsrqoEhyUg8Zk+m8K78E= dependencies: "@babel/runtime" "^7.10.1" classnames "^2.2.1" +rc-checkbox@~3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.1.0.tgz" + integrity sha512-PAwpJFnBa3Ei+5pyqMMXdcKYKNBMS+TvSDiLdDnARnMJHC8ESxwPfm4Ao1gJiKtWLdmGfigascnCpwrHFgoOBQ== + dependencies: + "@babel/runtime" "^7.10.1" + classnames "^2.3.2" + rc-util "^5.25.2" + rc-collapse@~1.9.1: version "1.9.3" - resolved "https://registry.npm.alibaba-inc.com/rc-collapse/download/rc-collapse-1.9.3.tgz#d9741db06a823353e1fd1aec3ba4c0f9d8af4b26" + resolved "https://registry.npm.alibaba-inc.com/rc-collapse/download/rc-collapse-1.9.3.tgz" integrity sha1-2XQdsGqCM1Ph/RrsO6TA+divSyY= dependencies: classnames "2.x" @@ -8692,7 +10431,7 @@ rc-collapse@~1.9.1: rc-collapse@~3.4.2: version "3.4.2" - resolved "https://registry.npm.alibaba-inc.com/rc-collapse/download/rc-collapse-3.4.2.tgz#1310be7ad4cd0dcfc622c45f6c3b5ffdee403ad7" + resolved "https://registry.npm.alibaba-inc.com/rc-collapse/download/rc-collapse-3.4.2.tgz" integrity sha512-jpTwLgJzkhAgp2Wpi3xmbTbbYExg6fkptL67Uu5LCRVEj6wqmy0DHTjjeynsjOLsppHGHu41t1ELntZ0lEvS/Q== dependencies: "@babel/runtime" "^7.10.1" @@ -8701,9 +10440,19 @@ rc-collapse@~3.4.2: rc-util "^5.2.1" shallowequal "^1.1.0" +rc-collapse@~3.7.1: + version "3.7.1" + resolved "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.7.1.tgz" + integrity sha512-N/7ejyiTf3XElNJBBpxqnZBUuMsQWEOPjB2QkfNvZ/Ca54eAvJXuOD1EGbCWCk2m7v/MSxku7mRpdeaLOCd4Gg== + dependencies: + "@babel/runtime" "^7.10.1" + classnames "2.x" + rc-motion "^2.3.4" + rc-util "^5.27.0" + rc-dialog@~9.0.0, rc-dialog@~9.0.2: version "9.0.2" - resolved "https://registry.npm.alibaba-inc.com/rc-dialog/download/rc-dialog-9.0.2.tgz#aadfebdeba145f256c1fac9b9f509f893cdbb5b8" + resolved "https://registry.npm.alibaba-inc.com/rc-dialog/download/rc-dialog-9.0.2.tgz" integrity sha512-s3U+24xWUuB6Bn2Lk/Qt6rufy+uT+QvWkiFhNBcO9APLxcFFczWamaq7x9h8SCuhfc1nHcW4y8NbMsnAjNnWyg== dependencies: "@babel/runtime" "^7.10.1" @@ -8712,9 +10461,20 @@ rc-dialog@~9.0.0, rc-dialog@~9.0.2: rc-motion "^2.3.0" rc-util "^5.21.0" +rc-dialog@~9.2.0: + version "9.2.0" + resolved "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.2.0.tgz" + integrity sha512-dL2tklMou/QfK77+0CTH3FTnKCvIiYv9Df7PfFfg8YVXhYAGmuIkV4ooQYHAIR4juL3Ywcm5oQflF2vDDuGlUg== + dependencies: + "@babel/runtime" "^7.10.1" + "@rc-component/portal" "^1.0.0-8" + classnames "^2.2.6" + rc-motion "^2.3.0" + rc-util "^5.21.0" + rc-drawer@~6.0.0: version "6.0.1" - resolved "https://registry.npm.alibaba-inc.com/rc-drawer/download/rc-drawer-6.0.1.tgz#437040ac7ba305b5d964ba51e88f30797671e8f8" + resolved "https://registry.npm.alibaba-inc.com/rc-drawer/download/rc-drawer-6.0.1.tgz" integrity sha512-ibWXGf8I+KRPXE03X4s0/xXzQI37YWXUV+oPy+R29GKxkjr98UTMgwvoQDKlZTm5AiaRuVFqhTKm0kNHqJh+TQ== dependencies: "@babel/runtime" "^7.10.1" @@ -8723,9 +10483,20 @@ rc-drawer@~6.0.0: rc-motion "^2.6.1" rc-util "^5.21.2" +rc-drawer@~6.4.1: + version "6.4.1" + resolved "https://registry.npmjs.org/rc-drawer/-/rc-drawer-6.4.1.tgz" + integrity sha512-QIbNMjiZy322o9uEpJHsSZ5rS/zuxqam3lYVPDzjztoqsoDzTNNxWN77QVpOfQ0UC9/87+qu25zocJ+O9bK2Tg== + dependencies: + "@babel/runtime" "^7.10.1" + "@rc-component/portal" "^1.1.1" + classnames "^2.2.6" + rc-motion "^2.6.1" + rc-util "^5.36.0" + rc-dropdown@~4.0.0: version "4.0.1" - resolved "https://registry.npm.alibaba-inc.com/rc-dropdown/download/rc-dropdown-4.0.1.tgz#f65d9d3d89750241057db59d5a75e43cd4576b68" + resolved "https://registry.npm.alibaba-inc.com/rc-dropdown/download/rc-dropdown-4.0.1.tgz" integrity sha512-OdpXuOcme1rm45cR0Jzgfl1otzmU4vuBVb+etXM8vcaULGokAKVpKlw8p6xzspG7jGd/XxShvq+N3VNEfk/l5g== dependencies: "@babel/runtime" "^7.18.3" @@ -8733,25 +10504,86 @@ rc-dropdown@~4.0.0: rc-trigger "^5.3.1" rc-util "^5.17.0" +rc-dropdown@~4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.1.0.tgz" + integrity sha512-VZjMunpBdlVzYpEdJSaV7WM7O0jf8uyDjirxXLZRNZ+tAC+NzD3PXPEtliFwGzVwBBdCmGuSqiS9DWcOLxQ9tw== + dependencies: + "@babel/runtime" "^7.18.3" + "@rc-component/trigger" "^1.7.0" + classnames "^2.2.6" + rc-util "^5.17.0" + +rc-editor-core@~0.8.3: + version "0.8.10" + resolved "https://registry.npmjs.org/rc-editor-core/-/rc-editor-core-0.8.10.tgz" + integrity sha512-T3aHpeMCIYA1sdAI7ynHHjXy5fqp83uPlD68ovZ0oClTSc3tbHmyCxXlA+Ti4YgmcpCYv7avF6a+TIbAka53kw== + dependencies: + babel-runtime "^6.26.0" + classnames "^2.2.5" + draft-js "^0.10.0" + immutable "^3.7.4" + lodash "^4.16.5" + prop-types "^15.5.8" + setimmediate "^1.0.5" + +rc-editor-mention@^1.1.13: + version "1.1.13" + resolved "https://registry.npmjs.org/rc-editor-mention/-/rc-editor-mention-1.1.13.tgz" + integrity sha512-3AOmGir91Fi2ogfRRaXLtqlNuIwQpvla7oUnGHS1+3eo7b+fUp5IlKcagqtwUBB5oDNofoySXkLBxzWvSYNp/Q== + dependencies: + babel-runtime "^6.23.0" + classnames "^2.2.5" + dom-scroll-into-view "^1.2.0" + draft-js "~0.10.0" + immutable "~3.7.4" + prop-types "^15.5.8" + rc-animate "^2.3.0" + rc-editor-core "~0.8.3" + rc-field-form@~1.27.0: version "1.27.3" - resolved "https://registry.npm.alibaba-inc.com/rc-field-form/download/rc-field-form-1.27.3.tgz#e5262796b91c80848a42a3e7a669bf459f08d63d" + resolved "https://registry.npm.alibaba-inc.com/rc-field-form/download/rc-field-form-1.27.3.tgz" integrity sha512-HGqxHnmGQgkPApEcikV4qTg3BLPC82uB/cwBDftDt1pYaqitJfSl5TFTTUMKVEJVT5RqJ2Zi68ME1HmIMX2HAw== dependencies: "@babel/runtime" "^7.18.0" async-validator "^4.1.0" rc-util "^5.8.0" +rc-field-form@~1.38.0: + version "1.38.0" + resolved "https://registry.npmjs.org/rc-field-form/-/rc-field-form-1.38.0.tgz" + integrity sha512-erYxHL6s382MShbAlP5kquQETqulZII0uJmhjtIwkIGqPowJDrQeoey43notZFhVjeJDtznoJlBzVjiVN99w8g== + dependencies: + "@babel/runtime" "^7.18.0" + async-validator "^4.1.0" + rc-util "^5.32.2" + +rc-form@^2.4.10: + version "2.4.12" + resolved "https://registry.npmjs.org/rc-form/-/rc-form-2.4.12.tgz" + integrity sha512-sHfyWRrnjCHkeCYfYAGop2GQBUC6CKMPcJF9h/gL/vTmZB/RN6fNOGKjXrXjFbwFwKXUWBoPtIDDDmXQW9xNdw== + dependencies: + async-validator "~1.11.3" + babel-runtime "6.x" + create-react-class "^15.5.3" + dom-scroll-into-view "1.x" + hoist-non-react-statics "^3.3.0" + lodash "^4.17.4" + rc-util "^4.15.3" + react-is "^16.13.1" + warning "^4.0.3" + rc-gesture@~0.0.18, rc-gesture@~0.0.22: version "0.0.22" - resolved "https://registry.npm.alibaba-inc.com/rc-gesture/download/rc-gesture-0.0.22.tgz#fbcbdd5b46387a978b3ede48b42748e8ff77dddd" + resolved "https://registry.npm.alibaba-inc.com/rc-gesture/download/rc-gesture-0.0.22.tgz" integrity sha1-+8vdW0Y4epeLPt5ItCdI6P933d0= dependencies: babel-runtime "6.x" rc-image@~5.12.0: version "5.12.0" - resolved "https://registry.npm.alibaba-inc.com/rc-image/download/rc-image-5.12.0.tgz#20bf4b7e8cfc63e05c47e8fb470a299ba83a7ca6" + resolved "https://registry.npm.alibaba-inc.com/rc-image/download/rc-image-5.12.0.tgz" integrity sha512-ubZIPfT81jmb0hLf/sIKbgi7kJT2+26RxWPshppDElhXoJZ9Xb0y+QRBcYGgCAPy76RIuaKT2RL5x8Owvhrcjg== dependencies: "@babel/runtime" "^7.11.2" @@ -8760,9 +10592,21 @@ rc-image@~5.12.0: rc-dialog "~9.0.0" rc-util "^5.0.6" +rc-image@~7.2.0: + version "7.2.0" + resolved "https://registry.npmjs.org/rc-image/-/rc-image-7.2.0.tgz" + integrity sha512-5Ug2hCVl6VcT0osR5XaZQ4zclTMEWPnbn3b4/TS/MR1QjRpEACLNFUzBGwr5mbAVhzvLWX5YZf4vO10xUA5IUA== + dependencies: + "@babel/runtime" "^7.11.2" + "@rc-component/portal" "^1.0.2" + classnames "^2.2.6" + rc-dialog "~9.2.0" + rc-motion "^2.6.2" + rc-util "^5.34.1" + rc-input-number@~7.3.9: version "7.3.11" - resolved "https://registry.npm.alibaba-inc.com/rc-input-number/download/rc-input-number-7.3.11.tgz#c7089705a220e1a59ba974fabf89693e00dd2442" + resolved "https://registry.npm.alibaba-inc.com/rc-input-number/download/rc-input-number-7.3.11.tgz" integrity sha512-aMWPEjFeles6PQnMqP5eWpxzsvHm9rh1jQOWXExUEIxhX62Fyl/ptifLHOn17+waDG1T/YUb6flfJbvwRhHrbA== dependencies: "@babel/runtime" "^7.10.1" @@ -8771,7 +10615,7 @@ rc-input-number@~7.3.9: rc-input-number@~7.4.0: version "7.4.2" - resolved "https://registry.npm.alibaba-inc.com/rc-input-number/download/rc-input-number-7.4.2.tgz#7c52d26b986461aa16e486d469dc0476d97c6ea3" + resolved "https://registry.npm.alibaba-inc.com/rc-input-number/download/rc-input-number-7.4.2.tgz" integrity sha512-yGturTw7WGP+M1GbJ+UTAO7L4buxeW6oilhL9Sq3DezsRS8/9qec4UiXUbeoiX9bzvRXH11JvgskBtxSp4YSNg== dependencies: "@babel/runtime" "^7.10.1" @@ -8779,18 +10623,38 @@ rc-input-number@~7.4.0: classnames "^2.2.5" rc-util "^5.28.0" +rc-input-number@~8.0.4: + version "8.0.4" + resolved "https://registry.npmjs.org/rc-input-number/-/rc-input-number-8.0.4.tgz" + integrity sha512-TP+G5b7mZtbwXJ/YEZXF/OgbEZ6iqD4+RSuxZJ8VGKGXDcdt0FKIvpFoNQr/knspdFC4OxA0OfsWfFWfN4XSyA== + dependencies: + "@babel/runtime" "^7.10.1" + "@rc-component/mini-decimal" "^1.0.1" + classnames "^2.2.5" + rc-input "~1.1.0" + rc-util "^5.28.0" + rc-input@~0.1.4: version "0.1.4" - resolved "https://registry.npm.alibaba-inc.com/rc-input/download/rc-input-0.1.4.tgz#45cb4ba209ae6cc835a2acb8629d4f8f0cb347e0" + resolved "https://registry.npm.alibaba-inc.com/rc-input/download/rc-input-0.1.4.tgz" integrity sha512-FqDdNz+fV2dKNgfXzcSLKvC+jEs1709t7nD+WdfjrdSaOcefpgc7BUJYadc3usaING+b7ediMTfKxuJBsEFbXA== dependencies: "@babel/runtime" "^7.11.1" classnames "^2.2.1" rc-util "^5.18.1" +rc-input@~1.1.0, rc-input@~1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/rc-input/-/rc-input-1.1.1.tgz" + integrity sha512-NTR1Z4em681L8/ewb2KR80RykSmN8I2mzqzJDCoUmTrV1BB9Hk5d7ha4TnfgdEPPL148N+603sW2LExSXk1IbA== + dependencies: + "@babel/runtime" "^7.11.1" + classnames "^2.2.1" + rc-util "^5.18.1" + rc-mentions@~1.11.0: version "1.11.0" - resolved "https://registry.npm.alibaba-inc.com/rc-mentions/download/rc-mentions-1.11.0.tgz#ffbe046af52a0ec057393073d0b1ca4210c3325e" + resolved "https://registry.npm.alibaba-inc.com/rc-mentions/download/rc-mentions-1.11.0.tgz" integrity sha512-0C78O4wvG8UwsT7DtcwV8j7k4T+urrM0VuRT9gmSGbX187Ftl/JbCXL6WMGHSWBYI+LxInw1x4gw0Zi6qOcaig== dependencies: "@babel/runtime" "^7.10.1" @@ -8802,7 +10666,7 @@ rc-mentions@~1.11.0: rc-mentions@~1.13.1: version "1.13.1" - resolved "https://registry.npm.alibaba-inc.com/rc-mentions/download/rc-mentions-1.13.1.tgz#c884b70e1505a197f1b32a7c6b39090db6992a72" + resolved "https://registry.npm.alibaba-inc.com/rc-mentions/download/rc-mentions-1.13.1.tgz" integrity sha512-FCkaWw6JQygtOz0+Vxz/M/NWqrWHB9LwqlY2RtcuFqWJNFK9njijOOzTSsBGANliGufVUzx/xuPHmZPBV0+Hgw== dependencies: "@babel/runtime" "^7.10.1" @@ -8812,9 +10676,34 @@ rc-mentions@~1.13.1: rc-trigger "^5.0.4" rc-util "^5.22.5" +rc-mentions@~2.7.0: + version "2.7.0" + resolved "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.7.0.tgz" + integrity sha512-tn0x79cpnVYP+MA+jyBqalmEni9Ct7xHuA9QHIf5vwd25FU+hngGZ8n6Dfua7XCr4LhkZYjfD/rZTGrvY2C1Xg== + dependencies: + "@babel/runtime" "^7.22.5" + "@rc-component/trigger" "^1.5.0" + classnames "^2.2.6" + rc-input "~1.1.0" + rc-menu "~9.12.0" + rc-textarea "~1.3.0" + rc-util "^5.34.1" + +rc-menu@~9.12.0: + version "9.12.0" + resolved "https://registry.npmjs.org/rc-menu/-/rc-menu-9.12.0.tgz" + integrity sha512-Apr/fRf5EcqWJ4nphHV6dTGZcLPaPzwY44q9hAtLJysY4rkC9Eg+ekj3uFx6opPWVruV2sJNWq/Po+HHtO48CA== + dependencies: + "@babel/runtime" "^7.10.1" + "@rc-component/trigger" "^1.6.2" + classnames "2.x" + rc-motion "^2.4.3" + rc-overflow "^1.3.1" + rc-util "^5.27.0" + rc-menu@~9.7.2: version "9.7.2" - resolved "https://registry.npm.alibaba-inc.com/rc-menu/download/rc-menu-9.7.2.tgz#0b400e2d81377c8001795559139cb29871143be1" + resolved "https://registry.npm.alibaba-inc.com/rc-menu/download/rc-menu-9.7.2.tgz" integrity sha512-zyri6Qwr955SOdjzDn7/ylz7Zj8r89wGyoRw0lV9G8K6a3VBfSrP2XMYEc0JgeC62OTghUcRWad7KFqNXysxaA== dependencies: "@babel/runtime" "^7.10.1" @@ -8827,7 +10716,7 @@ rc-menu@~9.7.2: rc-menu@~9.8.0: version "9.8.2" - resolved "https://registry.npm.alibaba-inc.com/rc-menu/download/rc-menu-9.8.2.tgz#179df4ea0fc46fffb7a21e18d3cddb901ce35986" + resolved "https://registry.npm.alibaba-inc.com/rc-menu/download/rc-menu-9.8.2.tgz" integrity sha512-EahOJVjLuEnJsThoPN+mGnVm431RzVzDLZWHRS/YnXTQULa7OsgdJa/Y7qXxc3Z5sz8mgT6xYtgpmBXLxrZFaQ== dependencies: "@babel/runtime" "^7.10.1" @@ -8839,16 +10728,25 @@ rc-menu@~9.8.0: rc-motion@^2.0.0, rc-motion@^2.0.1, rc-motion@^2.2.0, rc-motion@^2.3.0, rc-motion@^2.3.4, rc-motion@^2.4.3, rc-motion@^2.4.4, rc-motion@^2.6.0, rc-motion@^2.6.1, rc-motion@^2.6.2: version "2.6.2" - resolved "https://registry.npm.alibaba-inc.com/rc-motion/download/rc-motion-2.6.2.tgz#3d31f97e41fb8e4f91a4a4189b6a98ac63342869" + resolved "https://registry.npm.alibaba-inc.com/rc-motion/download/rc-motion-2.6.2.tgz" integrity sha512-4w1FaX3dtV749P8GwfS4fYnFG4Rb9pxvCYPc/b2fw1cmlHJWNNgOFIz7ysiD+eOrzJSvnLJWlNQQncpNMXwwpg== dependencies: "@babel/runtime" "^7.11.1" classnames "^2.2.1" rc-util "^5.21.0" +rc-motion@^2.9.0: + version "2.9.0" + resolved "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.0.tgz" + integrity sha512-XIU2+xLkdIr1/h6ohPZXyPBMvOmuyFZQ/T0xnawz+Rh+gh4FINcnZmMT5UTIj6hgI0VLDjTaPeRd+smJeSPqiQ== + dependencies: + "@babel/runtime" "^7.11.1" + classnames "^2.2.1" + rc-util "^5.21.0" + rc-notification@~4.6.0: version "4.6.1" - resolved "https://registry.npm.alibaba-inc.com/rc-notification/download/rc-notification-4.6.1.tgz#068e8674f4bd7926a447eca512915d4b41b15c91" + resolved "https://registry.npm.alibaba-inc.com/rc-notification/download/rc-notification-4.6.1.tgz" integrity sha512-NSmFYwrrdY3+un1GvDAJQw62Xi9LNMSsoQyo95tuaYrcad5Bn9gJUL8AREufRxSQAQnr64u3LtP3EUyLYT6bhw== dependencies: "@babel/runtime" "^7.10.1" @@ -8858,7 +10756,7 @@ rc-notification@~4.6.0: rc-notification@~5.0.0-alpha.9: version "5.0.0-alpha.9" - resolved "https://registry.npm.alibaba-inc.com/rc-notification/download/rc-notification-5.0.0-alpha.9.tgz#e6fbf5cc786e508f022691a61a03c0473f5ca7b0" + resolved "https://registry.npm.alibaba-inc.com/rc-notification/download/rc-notification-5.0.0-alpha.9.tgz" integrity sha512-QPvq8VHe2M0SE5DHJf7ADWlvfWKnTsj5FVxcu39gdjX98kKmi+BHY1eTPAQkkdGqd6ZXv6xXHl8qKHyWhQcFPA== dependencies: "@babel/runtime" "^7.10.1" @@ -8866,9 +10764,19 @@ rc-notification@~5.0.0-alpha.9: rc-motion "^2.6.0" rc-util "^5.20.1" +rc-notification@~5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/rc-notification/-/rc-notification-5.1.1.tgz" + integrity sha512-BPnded/WmWFE57ubqhVCgRSuedfQQNeSOYqdwppyr2B/Wt909gYFKyWAkFJVXuppAjsOGop05a93UaxjmUFdkg== + dependencies: + "@babel/runtime" "^7.10.1" + classnames "2.x" + rc-motion "^2.6.0" + rc-util "^5.20.1" + rc-overflow@^1.0.0, rc-overflow@^1.2.8: version "1.2.8" - resolved "https://registry.npm.alibaba-inc.com/rc-overflow/download/rc-overflow-1.2.8.tgz#40f140fabc244118543e627cdd1ef750d9481a88" + resolved "https://registry.npm.alibaba-inc.com/rc-overflow/download/rc-overflow-1.2.8.tgz" integrity sha512-QJ0UItckWPQ37ZL1dMEBAdY1dhfTXFL9k6oTTcyydVwoUNMnMqCGqnRNA98axSr/OeDKqR6DVFyi8eA5RQI/uQ== dependencies: "@babel/runtime" "^7.11.1" @@ -8876,17 +10784,36 @@ rc-overflow@^1.0.0, rc-overflow@^1.2.8: rc-resize-observer "^1.0.0" rc-util "^5.19.2" +rc-overflow@^1.3.1: + version "1.3.2" + resolved "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.3.2.tgz" + integrity sha512-nsUm78jkYAoPygDAcGZeC2VwIg/IBGSodtOY3pMof4W3M9qRJgqaDYm03ZayHlde3I6ipliAxbN0RUcGf5KOzw== + dependencies: + "@babel/runtime" "^7.11.1" + classnames "^2.2.1" + rc-resize-observer "^1.0.0" + rc-util "^5.37.0" + rc-pagination@~3.2.0: version "3.2.0" - resolved "https://registry.npm.alibaba-inc.com/rc-pagination/download/rc-pagination-3.2.0.tgz#4f2fdba9fdac0f48e5c9fb1141973818138af7e1" + resolved "https://registry.npm.alibaba-inc.com/rc-pagination/download/rc-pagination-3.2.0.tgz" integrity sha512-5tIXjB670WwwcAJzAqp2J+cOBS9W3cH/WU1EiYwXljuZ4vtZXKlY2Idq8FZrnYBz8KhN3vwPo9CoV/SJS6SL1w== dependencies: "@babel/runtime" "^7.10.1" classnames "^2.2.1" +rc-pagination@~3.6.1: + version "3.6.1" + resolved "https://registry.npmjs.org/rc-pagination/-/rc-pagination-3.6.1.tgz" + integrity sha512-R/sUnKKXx1Nm4kZfUKS3YKa7yEPF1ZkVB/AynQaHt+nMER7h9wPTfliDJFdYo+RM/nk2JD4Yc5QpUq8fIQHeug== + dependencies: + "@babel/runtime" "^7.10.1" + classnames "^2.2.1" + rc-util "^5.32.2" + rc-picker@~2.7.0: version "2.7.0" - resolved "https://registry.npm.alibaba-inc.com/rc-picker/download/rc-picker-2.7.0.tgz#3c19881da27a0c5ee4c7e7504e21b552bd43a94c" + resolved "https://registry.npm.alibaba-inc.com/rc-picker/download/rc-picker-2.7.0.tgz" integrity sha512-oZH6FZ3j4iuBxHB4NvQ6ABRsS2If/Kpty1YFFsji7/aej6ruGmfM7WnJWQ88AoPfpJ++ya5z+nVEA8yCRYGKyw== dependencies: "@babel/runtime" "^7.10.1" @@ -8900,7 +10827,7 @@ rc-picker@~2.7.0: rc-picker@~3.1.1: version "3.1.5" - resolved "https://registry.npm.alibaba-inc.com/rc-picker/download/rc-picker-3.1.5.tgz#49953655a92cda3dee59678f4cbcdee61f5b0f0c" + resolved "https://registry.npm.alibaba-inc.com/rc-picker/download/rc-picker-3.1.5.tgz" integrity sha512-Hh3ml+u+5mxLfl4ahVWlRGiX5+0EJrALR6tSW9yP0eea+6j+YjvjfetbvuVidViMDMweZa38dr8HTfAFLG6GFw== dependencies: "@babel/runtime" "^7.10.1" @@ -8908,27 +10835,55 @@ rc-picker@~3.1.1: rc-trigger "^5.0.4" rc-util "^5.27.0" +rc-picker@~3.13.2: + version "3.13.2" + resolved "https://registry.npmjs.org/rc-picker/-/rc-picker-3.13.2.tgz" + integrity sha512-jvmmwo9d2/rUJXx8dydmcReAGF7f2wzbR7GDUgZXymbw0cqxNqXen5GGQIsX0x92JJROKyKb+J/E7bn967Ok9A== + dependencies: + "@babel/runtime" "^7.10.1" + "@rc-component/trigger" "^1.5.0" + classnames "^2.2.1" + rc-util "^5.30.0" + rc-progress@~3.4.1: version "3.4.1" - resolved "https://registry.npm.alibaba-inc.com/rc-progress/download/rc-progress-3.4.1.tgz#a9ffe099e88a4fc03afb09d8603162bf0760d743" + resolved "https://registry.npm.alibaba-inc.com/rc-progress/download/rc-progress-3.4.1.tgz" integrity sha512-eAFDHXlk8aWpoXl0llrenPMt9qKHQXphxcVsnKs0FHC6eCSk1ebJtyaVjJUzKe0233ogiLDeEFK1Uihz3s67hw== dependencies: "@babel/runtime" "^7.10.1" classnames "^2.2.6" rc-util "^5.16.1" +rc-progress@~3.5.1: + version "3.5.1" + resolved "https://registry.npmjs.org/rc-progress/-/rc-progress-3.5.1.tgz" + integrity sha512-V6Amx6SbLRwPin/oD+k1vbPrO8+9Qf8zW1T8A7o83HdNafEVvAxPV5YsgtKFP+Ud5HghLj33zKOcEHrcrUGkfw== + dependencies: + "@babel/runtime" "^7.10.1" + classnames "^2.2.6" + rc-util "^5.16.1" + +rc-rate@~2.12.0: + version "2.12.0" + resolved "https://registry.npmjs.org/rc-rate/-/rc-rate-2.12.0.tgz" + integrity sha512-g092v5iZCdVzbjdn28FzvWebK2IutoVoiTeqoLTj9WM7SjA/gOJIw5/JFZMRyJYYVe1jLAU2UhAfstIpCNRozg== + dependencies: + "@babel/runtime" "^7.10.1" + classnames "^2.2.5" + rc-util "^5.0.1" + rc-rate@~2.9.0: version "2.9.2" - resolved "https://registry.npm.alibaba-inc.com/rc-rate/download/rc-rate-2.9.2.tgz#4a58965d1ecf91896ebae01d458b59056df0b4ea" + resolved "https://registry.npm.alibaba-inc.com/rc-rate/download/rc-rate-2.9.2.tgz" integrity sha512-SaiZFyN8pe0Fgphv8t3+kidlej+cq/EALkAJAc3A0w0XcPaH2L1aggM8bhe1u6GAGuQNAoFvTLjw4qLPGRKV5g== dependencies: "@babel/runtime" "^7.10.1" classnames "^2.2.5" rc-util "^5.0.1" -rc-resize-observer@^0.2.1: +rc-resize-observer@^0.2.1, rc-resize-observer@^0.2.3: version "0.2.6" - resolved "https://registry.npm.alibaba-inc.com/rc-resize-observer/download/rc-resize-observer-0.2.6.tgz#c1b642f6d1293e34c4e3715f47f69443a167b825" + resolved "https://registry.npm.alibaba-inc.com/rc-resize-observer/download/rc-resize-observer-0.2.6.tgz" integrity sha1-wbZC9tEpPjTE43FfR/aUQ6FnuCU= dependencies: "@babel/runtime" "^7.10.1" @@ -8938,7 +10893,7 @@ rc-resize-observer@^0.2.1: rc-resize-observer@^1.0.0, rc-resize-observer@^1.1.0, rc-resize-observer@^1.2.0: version "1.2.0" - resolved "https://registry.npm.alibaba-inc.com/rc-resize-observer/download/rc-resize-observer-1.2.0.tgz#9f46052f81cdf03498be35144cb7c53fd282c4c7" + resolved "https://registry.npm.alibaba-inc.com/rc-resize-observer/download/rc-resize-observer-1.2.0.tgz" integrity sha512-6W+UzT3PyDM0wVCEHfoW3qTHPTvbdSgiA43buiy8PzmeMnfgnDeb9NjdimMXMl3/TcrvvWl5RRVdp+NqcR47pQ== dependencies: "@babel/runtime" "^7.10.1" @@ -8946,9 +10901,19 @@ rc-resize-observer@^1.0.0, rc-resize-observer@^1.1.0, rc-resize-observer@^1.2.0: rc-util "^5.15.0" resize-observer-polyfill "^1.5.1" +rc-resize-observer@^1.3.1: + version "1.3.1" + resolved "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.3.1.tgz" + integrity sha512-iFUdt3NNhflbY3mwySv5CA1TC06zdJ+pfo0oc27xpf4PIOvfZwZGtD9Kz41wGYqC4SLio93RVAirSSpYlV/uYg== + dependencies: + "@babel/runtime" "^7.20.7" + classnames "^2.2.1" + rc-util "^5.27.0" + resize-observer-polyfill "^1.5.1" + rc-segmented@~2.1.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/rc-segmented/download/rc-segmented-2.1.0.tgz#0e0afe646c1a0e44a0e18785f518c42633ec8efc" + resolved "https://registry.npm.alibaba-inc.com/rc-segmented/download/rc-segmented-2.1.0.tgz" integrity sha512-hUlonro+pYoZcwrH6Vm56B2ftLfQh046hrwif/VwLIw1j3zGt52p5mREBwmeVzXnSwgnagpOpfafspzs1asjGw== dependencies: "@babel/runtime" "^7.11.1" @@ -8956,9 +10921,19 @@ rc-segmented@~2.1.0: rc-motion "^2.4.4" rc-util "^5.17.0" +rc-segmented@~2.2.2: + version "2.2.2" + resolved "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.2.2.tgz" + integrity sha512-Mq52M96QdHMsNdE/042ibT5vkcGcD5jxKp7HgPC2SRofpia99P5fkfHy1pEaajLMF/kj0+2Lkq1UZRvqzo9mSA== + dependencies: + "@babel/runtime" "^7.11.1" + classnames "^2.2.1" + rc-motion "^2.4.4" + rc-util "^5.17.0" + rc-select@~14.1.0, rc-select@~14.1.13: version "14.1.13" - resolved "https://registry.npm.alibaba-inc.com/rc-select/download/rc-select-14.1.13.tgz#7eb53d00be82fb8e5050de3094e72edcf27ce6f6" + resolved "https://registry.npm.alibaba-inc.com/rc-select/download/rc-select-14.1.13.tgz" integrity sha512-WMEsC3gTwA1dbzWOdVIXDmWyidYNLq68AwvvUlRROw790uGUly0/vmqDozXrIr0QvN/A3CEULx12o+WtLCAefg== dependencies: "@babel/runtime" "^7.10.1" @@ -8969,9 +10944,22 @@ rc-select@~14.1.0, rc-select@~14.1.13: rc-util "^5.16.1" rc-virtual-list "^3.2.0" +rc-select@~14.8.0, rc-select@~14.8.1: + version "14.8.1" + resolved "https://registry.npmjs.org/rc-select/-/rc-select-14.8.1.tgz" + integrity sha512-+MDaHteiKRL4iID9Osm8zAZTe+g7/t5CjIfJJ4QhPAvwGUaNCa2kvkMqiXfOfGevscVa+agha1Ov938MeAotfQ== + dependencies: + "@babel/runtime" "^7.10.1" + "@rc-component/trigger" "^1.5.0" + classnames "2.x" + rc-motion "^2.0.1" + rc-overflow "^1.3.1" + rc-util "^5.16.1" + rc-virtual-list "^3.5.2" + rc-slider@~10.0.0: version "10.0.1" - resolved "https://registry.npm.alibaba-inc.com/rc-slider/download/rc-slider-10.0.1.tgz#7058c68ff1e1aa4e7c3536e5e10128bdbccb87f9" + resolved "https://registry.npm.alibaba-inc.com/rc-slider/download/rc-slider-10.0.1.tgz" integrity sha512-igTKF3zBet7oS/3yNiIlmU8KnZ45npmrmHlUUio8PNbIhzMcsh+oE/r2UD42Y6YD2D/s+kzCQkzQrPD6RY435Q== dependencies: "@babel/runtime" "^7.10.1" @@ -8979,9 +10967,18 @@ rc-slider@~10.0.0: rc-util "^5.18.1" shallowequal "^1.1.0" +rc-slider@~10.2.1: + version "10.2.1" + resolved "https://registry.npmjs.org/rc-slider/-/rc-slider-10.2.1.tgz" + integrity sha512-l355C/65iV4UFp7mXq5xBTNX2/tF2g74VWiTVlTpNp+6vjE/xaHHNiQq5Af+Uu28uUiqCuH/QXs5HfADL9KJ/A== + dependencies: + "@babel/runtime" "^7.10.1" + classnames "^2.2.5" + rc-util "^5.27.0" + rc-slider@~8.2.0: version "8.2.0" - resolved "https://registry.npm.alibaba-inc.com/rc-slider/download/rc-slider-8.2.0.tgz#ae37d17144cad60e1da6eac0ee4ffcfea0b0a6e8" + resolved "https://registry.npm.alibaba-inc.com/rc-slider/download/rc-slider-8.2.0.tgz" integrity sha1-rjfRcUTK1g4dpurA7k/8/qCwpug= dependencies: babel-runtime "6.x" @@ -8994,7 +10991,7 @@ rc-slider@~8.2.0: rc-steps@~5.0.0-alpha.2: version "5.0.0" - resolved "https://registry.npm.alibaba-inc.com/rc-steps/download/rc-steps-5.0.0.tgz#2e2403f2dd69eb3966d65f461f7e3a8ee1ef69fe" + resolved "https://registry.npm.alibaba-inc.com/rc-steps/download/rc-steps-5.0.0.tgz" integrity sha512-9TgRvnVYirdhbV0C3syJFj9EhCRqoJAsxt4i1rED5o8/ZcSv5TLIYyo4H8MCjLPvbe2R+oBAm/IYBEtC+OS1Rw== dependencies: "@babel/runtime" "^7.16.7" @@ -9003,16 +11000,25 @@ rc-steps@~5.0.0-alpha.2: rc-steps@~6.0.0-alpha.2: version "6.0.0-alpha.2" - resolved "https://registry.npm.alibaba-inc.com/rc-steps/download/rc-steps-6.0.0-alpha.2.tgz#505e64177111becd911cef4d24f15477438c9e59" + resolved "https://registry.npm.alibaba-inc.com/rc-steps/download/rc-steps-6.0.0-alpha.2.tgz" integrity sha512-d/GPx7ATlPbtFeOVt5FB19W11OBCmRd7lLknt4aSoCI6ukwJqpEhWu2INN4pDOQqN04y3PDsWl1q9hnw+ZC5AA== dependencies: "@babel/runtime" "^7.16.7" classnames "^2.2.3" rc-util "^5.16.1" +rc-steps@~6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/rc-steps/-/rc-steps-6.0.1.tgz" + integrity sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g== + dependencies: + "@babel/runtime" "^7.16.7" + classnames "^2.2.3" + rc-util "^5.16.1" + rc-swipeout@~2.0.0: version "2.0.11" - resolved "https://registry.npm.alibaba-inc.com/rc-swipeout/download/rc-swipeout-2.0.11.tgz#dfad9c7b38a15ea0376e39cb3356e36fed7a4155" + resolved "https://registry.npm.alibaba-inc.com/rc-swipeout/download/rc-swipeout-2.0.11.tgz" integrity sha1-362cezihXqA3bjnLM1bjb+16QVU= dependencies: babel-runtime "6.x" @@ -9022,7 +11028,7 @@ rc-swipeout@~2.0.0: rc-switch@~3.2.0: version "3.2.2" - resolved "https://registry.npm.alibaba-inc.com/rc-switch/download/rc-switch-3.2.2.tgz#d001f77f12664d52595b4f6fb425dd9e66fba8e8" + resolved "https://registry.npm.alibaba-inc.com/rc-switch/download/rc-switch-3.2.2.tgz" integrity sha1-0AH3fxJmTVJZW09vtCXdnmb7qOg= dependencies: "@babel/runtime" "^7.10.1" @@ -9031,16 +11037,25 @@ rc-switch@~3.2.0: rc-switch@~4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/rc-switch/download/rc-switch-4.0.0.tgz#55fbf99fc2d680791175037d379e170ba51fbe78" + resolved "https://registry.npm.alibaba-inc.com/rc-switch/download/rc-switch-4.0.0.tgz" integrity sha512-IfrYC99vN0gKaTyjQdqYuADU0eH00SAFHg3jOp8HrmUpJruhV1SohJzrCbPqPraZeX/6X/QKkdLfkdnUub05WA== dependencies: "@babel/runtime" "^7.10.1" classnames "^2.2.1" rc-util "^5.0.1" +rc-switch@~4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/rc-switch/-/rc-switch-4.1.0.tgz" + integrity sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg== + dependencies: + "@babel/runtime" "^7.21.0" + classnames "^2.2.1" + rc-util "^5.30.0" + rc-table@~7.26.0: version "7.26.0" - resolved "https://registry.npm.alibaba-inc.com/rc-table/download/rc-table-7.26.0.tgz#9d517e7fa512e7571fdcc453eb1bf19edfac6fbc" + resolved "https://registry.npm.alibaba-inc.com/rc-table/download/rc-table-7.26.0.tgz" integrity sha512-0cD8e6S+DTGAt5nBZQIPFYEaIukn17sfa5uFL98faHlH/whZzD8ii3dbFL4wmUDEL4BLybhYop+QUfZJ4CPvNQ== dependencies: "@babel/runtime" "^7.10.1" @@ -9049,9 +11064,34 @@ rc-table@~7.26.0: rc-util "^5.22.5" shallowequal "^1.1.0" +rc-table@~7.33.1: + version "7.33.4" + resolved "https://registry.npmjs.org/rc-table/-/rc-table-7.33.4.tgz" + integrity sha512-zgWcNPcI4vCBjvdInjF7PCt3loqDDLIZwVyw7R+Et1nwIGW26UNbdSw/C+pkTOppQd9kRiu9JD/z9xAjhTLE2w== + dependencies: + "@babel/runtime" "^7.10.1" + "@rc-component/context" "^1.4.0" + classnames "^2.2.5" + rc-resize-observer "^1.1.0" + rc-util "^5.36.0" + rc-virtual-list "^3.10.7" + +rc-tabs@~12.12.1: + version "12.12.1" + resolved "https://registry.npmjs.org/rc-tabs/-/rc-tabs-12.12.1.tgz" + integrity sha512-e10VBjEkECdPl4XZSs9to81SE+mgclBTM7J8/LMsFqmJoi05Tci91bRnmeeDtrcOCx2PuZdJv57XUlC4d8PEIw== + dependencies: + "@babel/runtime" "^7.11.2" + classnames "2.x" + rc-dropdown "~4.1.0" + rc-menu "~9.12.0" + rc-motion "^2.6.2" + rc-resize-observer "^1.0.0" + rc-util "^5.34.1" + rc-tabs@~12.3.0: version "12.3.0" - resolved "https://registry.npm.alibaba-inc.com/rc-tabs/download/rc-tabs-12.3.0.tgz#a346cafa7eafbe5faeeeb8c07b8ad95197f985dc" + resolved "https://registry.npm.alibaba-inc.com/rc-tabs/download/rc-tabs-12.3.0.tgz" integrity sha512-/mOHuq4h/mNC0QmB3iEOrYeiNMvciosSo/v7SMtvoc+jfk63AzZtQzwsC50t6kkL9ViEqyjDqj4bFfxKdQtozA== dependencies: "@babel/runtime" "^7.11.2" @@ -9064,7 +11104,7 @@ rc-tabs@~12.3.0: rc-tabs@~12.4.2: version "12.4.2" - resolved "https://registry.npm.alibaba-inc.com/rc-tabs/download/rc-tabs-12.4.2.tgz#487a1b3f8d8cf0bfc121224013dab00d4a8e0532" + resolved "https://registry.npm.alibaba-inc.com/rc-tabs/download/rc-tabs-12.4.2.tgz" integrity sha512-FFlGwuTjQUznWzJtyhmHc6KAp5lRQFxKUv9Aj1UtsOYe2e7WGmuzcrd+/LQchuPe0VjhaZPdGkmFGcqGqNO6ow== dependencies: "@babel/runtime" "^7.11.2" @@ -9077,7 +11117,7 @@ rc-tabs@~12.4.2: rc-textarea@^0.4.0, rc-textarea@~0.4.5: version "0.4.6" - resolved "https://registry.npm.alibaba-inc.com/rc-textarea/download/rc-textarea-0.4.6.tgz#65a46c9bb45da65c2acb9b071551eb420f6568e4" + resolved "https://registry.npm.alibaba-inc.com/rc-textarea/download/rc-textarea-0.4.6.tgz" integrity sha512-HEKCu8nouXXayqYelQnhQm8fdH7v92pAQvfVCz+jhIPv2PHTyBxVrmoZJMn3B8cU+wdyuvRGkshngO3/TzBn4w== dependencies: "@babel/runtime" "^7.10.1" @@ -9086,9 +11126,20 @@ rc-textarea@^0.4.0, rc-textarea@~0.4.5: rc-util "^5.24.4" shallowequal "^1.1.0" +rc-textarea@~1.3.0, rc-textarea@~1.3.4: + version "1.3.4" + resolved "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.3.4.tgz" + integrity sha512-wn0YjTpvcVolcfXa0HtzL+jgV2QcwtfB29RwNAKj8hMgZOju1V24M3TfEDjABeQEAQbUGbjMbISREOX/YSVKhg== + dependencies: + "@babel/runtime" "^7.10.1" + classnames "^2.2.1" + rc-input "~1.1.0" + rc-resize-observer "^1.0.0" + rc-util "^5.27.0" + rc-tooltip@^3.4.2: version "3.7.3" - resolved "https://registry.npm.alibaba-inc.com/rc-tooltip/download/rc-tooltip-3.7.3.tgz#280aec6afcaa44e8dff0480fbaff9e87fc00aecc" + resolved "https://registry.npm.alibaba-inc.com/rc-tooltip/download/rc-tooltip-3.7.3.tgz" integrity sha1-KArsavyqROjf8EgPuv+eh/wArsw= dependencies: babel-runtime "6.x" @@ -9097,16 +11148,36 @@ rc-tooltip@^3.4.2: rc-tooltip@~5.2.0: version "5.2.2" - resolved "https://registry.npm.alibaba-inc.com/rc-tooltip/download/rc-tooltip-5.2.2.tgz#e5cafa8ecebf78108936a0bcb93c150fa81ac93b" + resolved "https://registry.npm.alibaba-inc.com/rc-tooltip/download/rc-tooltip-5.2.2.tgz" integrity sha512-jtQzU/18S6EI3lhSGoDYhPqNpWajMtS5VV/ld1LwyfrDByQpYmw/LW6U7oFXXLukjfDHQ7Ju705A82PRNFWYhg== dependencies: "@babel/runtime" "^7.11.2" classnames "^2.3.1" rc-trigger "^5.0.0" +rc-tooltip@~6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.0.1.tgz" + integrity sha512-MdvPlsD1fDSxKp9+HjXrc/CxLmA/s11QYIh1R7aExxfodKP7CZA++DG1AjrW80F8IUdHYcR43HAm0Y2BYPelHA== + dependencies: + "@babel/runtime" "^7.11.2" + "@rc-component/trigger" "^1.0.4" + classnames "^2.3.1" + +rc-tree-select@~5.12.1: + version "5.12.1" + resolved "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.12.1.tgz" + integrity sha512-/IC6gRgRoUBCOwZASOiF3onp1484fb+Gke5zuxgsi3ViP+O2UTUByS1jTZzjNooidRgdwiQJksq1zVaVYw2TPg== + dependencies: + "@babel/runtime" "^7.10.1" + classnames "2.x" + rc-select "~14.8.0" + rc-tree "~5.7.0" + rc-util "^5.16.1" + rc-tree-select@~5.5.0: version "5.5.4" - resolved "https://registry.npm.alibaba-inc.com/rc-tree-select/download/rc-tree-select-5.5.4.tgz#5eef6845fd71085c52c042553abb3bfe7a0108f3" + resolved "https://registry.npm.alibaba-inc.com/rc-tree-select/download/rc-tree-select-5.5.4.tgz" integrity sha512-RdqOm3o+ybpdD3Jc+fYJ2hXlcODcMQIqSytjWzdTh7n2h5i7yIjSx4mprdbrF/buykU6kg1LURseWz9S2e6P2Q== dependencies: "@babel/runtime" "^7.10.1" @@ -9117,7 +11188,7 @@ rc-tree-select@~5.5.0: rc-tree-select@~5.5.4: version "5.5.5" - resolved "https://registry.npm.alibaba-inc.com/rc-tree-select/download/rc-tree-select-5.5.5.tgz#d28b3b45da1e820cd21762ba0ee93c19429bb369" + resolved "https://registry.npm.alibaba-inc.com/rc-tree-select/download/rc-tree-select-5.5.5.tgz" integrity sha512-k2av7jF6tW9bIO4mQhaVdV4kJ1c54oxV3/hHVU+oD251Gb5JN+m1RbJFTMf1o0rAFqkvto33rxMdpafaGKQRJw== dependencies: "@babel/runtime" "^7.10.1" @@ -9128,7 +11199,7 @@ rc-tree-select@~5.5.4: rc-tree@~5.7.0: version "5.7.0" - resolved "https://registry.npm.alibaba-inc.com/rc-tree/download/rc-tree-5.7.0.tgz#d0e316eeeac2ba4a1c36b2b2201d84884f1c76a1" + resolved "https://registry.npm.alibaba-inc.com/rc-tree/download/rc-tree-5.7.0.tgz" integrity sha512-F+Ewkv/UcutshnVBMISP+lPdHDlcsL+YH/MQDVWbk+QdkfID7vXiwrHMEZn31+2Rbbm21z/HPceGS8PXGMmnQg== dependencies: "@babel/runtime" "^7.10.1" @@ -9137,9 +11208,20 @@ rc-tree@~5.7.0: rc-util "^5.16.1" rc-virtual-list "^3.4.8" +rc-tree@~5.7.10: + version "5.7.10" + resolved "https://registry.npmjs.org/rc-tree/-/rc-tree-5.7.10.tgz" + integrity sha512-n4UkMQY3bzvJUNnbw6e3YI7sy2kE9c9vAYbSt94qAhcPKtMOThONNr1LIaFB/M5XeFYYrWVbvRVoT8k38eFuSQ== + dependencies: + "@babel/runtime" "^7.10.1" + classnames "2.x" + rc-motion "^2.0.1" + rc-util "^5.16.1" + rc-virtual-list "^3.5.1" + rc-trigger@^2.2.2: version "2.6.5" - resolved "https://registry.npm.alibaba-inc.com/rc-trigger/download/rc-trigger-2.6.5.tgz#140a857cf28bd0fa01b9aecb1e26a50a700e9885" + resolved "https://registry.npm.alibaba-inc.com/rc-trigger/download/rc-trigger-2.6.5.tgz" integrity sha1-FAqFfPKL0PoBua7LHialCnAOmIU= dependencies: babel-runtime "6.x" @@ -9152,7 +11234,7 @@ rc-trigger@^2.2.2: rc-trigger@^5.0.0, rc-trigger@^5.0.4, rc-trigger@^5.1.2, rc-trigger@^5.2.10, rc-trigger@^5.3.1: version "5.3.3" - resolved "https://registry.npm.alibaba-inc.com/rc-trigger/download/rc-trigger-5.3.3.tgz#166013df79e6a4ce64515391bd6d4f8386839761" + resolved "https://registry.npm.alibaba-inc.com/rc-trigger/download/rc-trigger-5.3.3.tgz" integrity sha512-IC4nuTSAME7RJSgwvHCNDQrIzhvGMKf6NDu5veX+zk1MG7i1UnwTWWthcP9WHw3+FZfP3oZGvkrHFPu/EGkFKw== dependencies: "@babel/runtime" "^7.18.3" @@ -9161,18 +11243,18 @@ rc-trigger@^5.0.0, rc-trigger@^5.0.4, rc-trigger@^5.1.2, rc-trigger@^5.2.10, rc- rc-motion "^2.0.0" rc-util "^5.19.2" -rc-upload@~4.3.0: +rc-upload@~4.3.0, rc-upload@~4.3.4: version "4.3.4" - resolved "https://registry.npm.alibaba-inc.com/rc-upload/download/rc-upload-4.3.4.tgz#83ff7d3867631c37adbfd72ea3d1fd7e97ca84af" + resolved "https://registry.npm.alibaba-inc.com/rc-upload/download/rc-upload-4.3.4.tgz" integrity sha512-uVbtHFGNjHG/RyAfm9fluXB6pvArAGyAx8z7XzXXyorEgVIWj6mOlriuDm0XowDHYz4ycNK0nE0oP3cbFnzxiQ== dependencies: "@babel/runtime" "^7.18.3" classnames "^2.2.5" rc-util "^5.2.0" -rc-util@4.x, rc-util@^4.0.4, rc-util@^4.15.3, rc-util@^4.19.0, rc-util@^4.4.0: +rc-util@4.x, rc-util@^4.0.4, rc-util@^4.10.0, rc-util@^4.15.3, rc-util@^4.19.0, rc-util@^4.4.0: version "4.21.1" - resolved "https://registry.npm.alibaba-inc.com/rc-util/download/rc-util-4.21.1.tgz#88602d0c3185020aa1053d9a1e70eac161becb05" + resolved "https://registry.npm.alibaba-inc.com/rc-util/download/rc-util-4.21.1.tgz" integrity sha1-iGAtDDGFAgqhBT2aHnDqwWG+ywU= dependencies: add-dom-event-listener "^1.1.0" @@ -9183,7 +11265,7 @@ rc-util@4.x, rc-util@^4.0.4, rc-util@^4.15.3, rc-util@^4.19.0, rc-util@^4.4.0: rc-util@^5.0.0: version "5.30.0" - resolved "https://registry.npm.alibaba-inc.com/rc-util/download/rc-util-5.30.0.tgz#76ae9019ff72a5b519ce51465cd77b2e451207e3" + resolved "https://registry.npm.alibaba-inc.com/rc-util/download/rc-util-5.30.0.tgz" integrity sha512-uaWpF/CZGyXuhQG71MWxkU+0bWkPEgqZUxEv251Cu7p3kpHDNm5+Ygu/U8ux0a/zbfGW8PsKcJL0XVBOMrlIZg== dependencies: "@babel/runtime" "^7.18.3" @@ -9191,7 +11273,7 @@ rc-util@^5.0.0: rc-util@^5.0.1, rc-util@^5.0.6, rc-util@^5.12.0, rc-util@^5.15.0, rc-util@^5.16.0, rc-util@^5.16.1, rc-util@^5.17.0, rc-util@^5.18.1, rc-util@^5.19.2, rc-util@^5.2.0, rc-util@^5.2.1, rc-util@^5.20.1, rc-util@^5.21.0, rc-util@^5.21.2, rc-util@^5.22.5, rc-util@^5.23.0, rc-util@^5.24.4, rc-util@^5.3.0, rc-util@^5.4.0, rc-util@^5.6.1, rc-util@^5.8.0, rc-util@^5.9.4: version "5.24.4" - resolved "https://registry.npm.alibaba-inc.com/rc-util/download/rc-util-5.24.4.tgz#a4126f01358c86f17c1bf380a1d83d6c9155ae65" + resolved "https://registry.npm.alibaba-inc.com/rc-util/download/rc-util-5.24.4.tgz" integrity sha512-2a4RQnycV9eV7lVZPEJ7QwJRPlZNc06J7CwcwZo4vIHr3PfUqtYgl1EkUV9ETAc6VRRi8XZOMFhYG63whlIC9Q== dependencies: "@babel/runtime" "^7.18.3" @@ -9200,7 +11282,7 @@ rc-util@^5.0.1, rc-util@^5.0.6, rc-util@^5.12.0, rc-util@^5.15.0, rc-util@^5.16. rc-util@^5.24.2: version "5.24.5" - resolved "https://registry.npm.alibaba-inc.com/rc-util/download/rc-util-5.24.5.tgz#d486fada224fcaf7146e06e961d30c1c774e6209" + resolved "https://registry.npm.alibaba-inc.com/rc-util/download/rc-util-5.24.5.tgz" integrity sha512-Y5b6qQ2/tZKRT8MvL0/ky++JOMAijZPvepTMbt20eRDDMqXUbmIR+lkjcTfzDu845ysEyq0YGdRsaae3hrpnQg== dependencies: "@babel/runtime" "^7.18.3" @@ -9209,15 +11291,33 @@ rc-util@^5.24.2: rc-util@^5.25.2, rc-util@^5.27.0, rc-util@^5.28.0: version "5.28.0" - resolved "https://registry.npm.alibaba-inc.com/rc-util/download/rc-util-5.28.0.tgz#9e5e441d5875b8bf0ba56c2f295042a28dcff580" + resolved "https://registry.npm.alibaba-inc.com/rc-util/download/rc-util-5.28.0.tgz" integrity sha512-KYDjhGodswVj29v0TRciKTqRPgumIFvFDndbCD227pitQ+0Cei196rxk+OXb/blu6V8zdTRK5RjCJn+WmHLvBA== dependencies: "@babel/runtime" "^7.18.3" react-is "^16.12.0" +rc-util@^5.30.0, rc-util@^5.31.1, rc-util@^5.32.2, rc-util@^5.33.0, rc-util@^5.34.1, rc-util@^5.35.0, rc-util@^5.36.0, rc-util@^5.37.0: + version "5.37.0" + resolved "https://registry.npmjs.org/rc-util/-/rc-util-5.37.0.tgz" + integrity sha512-cPMV8DzaHI1KDaS7XPRXAf4J7mtBqjvjikLpQieaeOO7+cEbqY2j7Kso/T0R0OiEZTNcLS/8Zl9YrlXiO9UbjQ== + dependencies: + "@babel/runtime" "^7.18.3" + react-is "^16.12.0" + +rc-virtual-list@^3.10.7, rc-virtual-list@^3.5.1, rc-virtual-list@^3.5.2: + version "3.10.7" + resolved "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.10.7.tgz" + integrity sha512-NZl8nsNV2kf0k9o4SHt6u/2kFBhE0SRTh71msUZkUB/rfNTBRKnhLXf8bD2jayT7TkprnbHBCPQbPqwJo2BSJw== + dependencies: + "@babel/runtime" "^7.20.0" + classnames "^2.2.6" + rc-resize-observer "^1.0.0" + rc-util "^5.36.0" + rc-virtual-list@^3.2.0, rc-virtual-list@^3.4.8: version "3.4.11" - resolved "https://registry.npm.alibaba-inc.com/rc-virtual-list/download/rc-virtual-list-3.4.11.tgz#97f5e947380d546a2ca8ad229d8e41e9b33b20c6" + resolved "https://registry.npm.alibaba-inc.com/rc-virtual-list/download/rc-virtual-list-3.4.11.tgz" integrity sha512-BvUUH60kkeTBPigN5F89HtGaA5jSP4y2aM6cJ4dk9Y42I9yY+h6i08wF6UKeDcxdfOU8j3I5HxkSS/xA77J3wA== dependencies: "@babel/runtime" "^7.20.0" @@ -9225,9 +11325,19 @@ rc-virtual-list@^3.2.0, rc-virtual-list@^3.4.8: rc-resize-observer "^1.0.0" rc-util "^5.15.0" -react-copy-to-clipboard@^5.0.1: +react-base16-styling@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.6.0.tgz" + integrity sha512-yvh/7CArceR/jNATXOKDlvTnPKPmGZz7zsenQ3jUwLzHkNUR0CvY3yGYJbWJ/nnxsL8Sgmt5cO3/SILVuPO6TQ== + dependencies: + base16 "^1.0.0" + lodash.curry "^4.0.1" + lodash.flow "^3.3.0" + pure-color "^1.2.0" + +react-copy-to-clipboard@^5.0.1, react-copy-to-clipboard@^5.1.0: version "5.1.0" - resolved "https://registry.npm.alibaba-inc.com/react-copy-to-clipboard/download/react-copy-to-clipboard-5.1.0.tgz#09aae5ec4c62750ccb2e6421a58725eabc41255c" + resolved "https://registry.npm.alibaba-inc.com/react-copy-to-clipboard/download/react-copy-to-clipboard-5.1.0.tgz" integrity sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A== dependencies: copy-to-clipboard "^3.3.1" @@ -9235,7 +11345,7 @@ react-copy-to-clipboard@^5.0.1: react-dom@16.x: version "16.14.0" - resolved "https://registry.npm.alibaba-inc.com/react-dom/download/react-dom-16.14.0.tgz#7ad838ec29a777fb3c75c3a190f661cf92ab8b89" + resolved "https://registry.npm.alibaba-inc.com/react-dom/download/react-dom-16.14.0.tgz" integrity sha1-etg47Cmnd/s8dcOhkPZhz5Kri4k= dependencies: loose-envify "^1.1.0" @@ -9245,7 +11355,7 @@ react-dom@16.x: react-dom@17.0.2: version "17.0.2" - resolved "https://registry.npm.alibaba-inc.com/react-dom/download/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" + resolved "https://registry.npm.alibaba-inc.com/react-dom/download/react-dom-17.0.2.tgz" integrity sha1-7P+2hF462Nv83EmPDQqTlzZQLCM= dependencies: loose-envify "^1.1.0" @@ -9254,12 +11364,12 @@ react-dom@17.0.2: react-fast-compare@^3.1.1: version "3.2.0" - resolved "https://registry.npm.alibaba-inc.com/react-fast-compare/download/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" + resolved "https://registry.npm.alibaba-inc.com/react-fast-compare/download/react-fast-compare-3.2.0.tgz" integrity sha1-ZBqdqBtqYyDycOiXJPtFoLOeQ7s= react-helmet@^6.1.0: version "6.1.0" - resolved "https://registry.npm.alibaba-inc.com/react-helmet/download/react-helmet-6.1.0.tgz#a750d5165cb13cf213e44747502652e794468726" + resolved "https://registry.npm.alibaba-inc.com/react-helmet/download/react-helmet-6.1.0.tgz" integrity sha1-p1DVFlyxPPIT5EdHUCZS55RGhyY= dependencies: object-assign "^4.1.1" @@ -9269,7 +11379,7 @@ react-helmet@^6.1.0: react-intl@3.12.1: version "3.12.1" - resolved "https://registry.npm.alibaba-inc.com/react-intl/download/react-intl-3.12.1.tgz#e9a783ea20302e9da25e4eda59e5593a43d2ec80" + resolved "https://registry.npm.alibaba-inc.com/react-intl/download/react-intl-3.12.1.tgz" integrity sha1-6aeD6iAwLp2iXk7aWeVZOkPS7IA= dependencies: "@formatjs/intl-displaynames" "^1.2.0" @@ -9287,7 +11397,7 @@ react-intl@3.12.1: react-intl@6.4.1: version "6.4.1" - resolved "https://registry.npm.alibaba-inc.com/react-intl/download/react-intl-6.4.1.tgz#01e4bd5497cb93d87146e966d8eda25851d4d9b6" + resolved "https://registry.npm.alibaba-inc.com/react-intl/download/react-intl-6.4.1.tgz" integrity sha512-/aT5595AEMZ+Pjmt8W2R5/ZkYJmyyd6jTzHzqhJ1LnfeG36+N5huBtykxYhHqLc1BrIRQ1fTX1orYC0Ej5ojtg== dependencies: "@formatjs/ecma402-abstract" "1.14.3" @@ -9303,22 +11413,32 @@ react-intl@6.4.1: react-is@^16.12.0, react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: version "16.13.1" - resolved "https://registry.npm.alibaba-inc.com/react-is/download/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + resolved "https://registry.npm.alibaba-inc.com/react-is/download/react-is-16.13.1.tgz" integrity sha1-eJcppNw23imZ3BVt1sHZwYzqVqQ= react-is@^17.0.1, react-is@^17.0.2: version "17.0.2" - resolved "https://registry.npm.alibaba-inc.com/react-is/download/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + resolved "https://registry.npm.alibaba-inc.com/react-is/download/react-is-17.0.2.tgz" integrity sha1-5pHUqOnHiTZWVVOas3J2Kw77VPA= +react-json-view@^1.21.3: + version "1.21.3" + resolved "https://registry.npmjs.org/react-json-view/-/react-json-view-1.21.3.tgz" + integrity sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw== + dependencies: + flux "^4.0.1" + react-base16-styling "^0.6.0" + react-lifecycles-compat "^3.0.4" + react-textarea-autosize "^8.3.2" + react-lifecycles-compat@^3.0.4: version "3.0.4" - resolved "https://registry.npm.alibaba-inc.com/react-lifecycles-compat/download/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" + resolved "https://registry.npm.alibaba-inc.com/react-lifecycles-compat/download/react-lifecycles-compat-3.0.4.tgz" integrity sha1-TxonOv38jzSIqMUWv9p4+HI1I2I= react-native-swipeout@^2.2.2: version "2.3.6" - resolved "https://registry.npm.alibaba-inc.com/react-native-swipeout/download/react-native-swipeout-2.3.6.tgz#47dac8a835825cf3f2eef9e495574a3d9ab6d3fa" + resolved "https://registry.npm.alibaba-inc.com/react-native-swipeout/download/react-native-swipeout-2.3.6.tgz" integrity sha1-R9rIqDWCXPPy7vnklVdKPZq20/o= dependencies: create-react-class "^15.6.0" @@ -9327,7 +11447,7 @@ react-native-swipeout@^2.2.2: react-redux@^7.1.0: version "7.2.9" - resolved "https://registry.npm.alibaba-inc.com/react-redux/download/react-redux-7.2.9.tgz#09488fbb9416a4efe3735b7235055442b042481d" + resolved "https://registry.npm.alibaba-inc.com/react-redux/download/react-redux-7.2.9.tgz" integrity sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ== dependencies: "@babel/runtime" "^7.15.4" @@ -9339,12 +11459,12 @@ react-redux@^7.1.0: react-refresh@0.10.0: version "0.10.0" - resolved "https://registry.npm.alibaba-inc.com/react-refresh/download/react-refresh-0.10.0.tgz#2f536c9660c0b9b1d500684d9e52a65e7404f7e3" + resolved "https://registry.npm.alibaba-inc.com/react-refresh/download/react-refresh-0.10.0.tgz" integrity sha1-L1NslmDAubHVAGhNnlKmXnQE9+M= react-responsive@^8.0.1: version "8.2.0" - resolved "https://registry.npm.alibaba-inc.com/react-responsive/download/react-responsive-8.2.0.tgz#e0ffb306cfd8f38c9c12e26725b9e1245fa9debc" + resolved "https://registry.npm.alibaba-inc.com/react-responsive/download/react-responsive-8.2.0.tgz" integrity sha1-4P+zBs/Y84ycEuJnJbnhJF+p3rw= dependencies: hyphenate-style-name "^1.0.0" @@ -9354,14 +11474,14 @@ react-responsive@^8.0.1: react-router-config@5.1.1: version "5.1.1" - resolved "https://registry.npm.alibaba-inc.com/react-router-config/download/react-router-config-5.1.1.tgz#0f4263d1a80c6b2dc7b9c1902c9526478194a988" + resolved "https://registry.npm.alibaba-inc.com/react-router-config/download/react-router-config-5.1.1.tgz" integrity sha1-D0Jj0agMay3HucGQLJUmR4GUqYg= dependencies: "@babel/runtime" "^7.1.2" react-router-dom@5.1.2: version "5.1.2" - resolved "https://registry.npm.alibaba-inc.com/react-router-dom/download/react-router-dom-5.1.2.tgz#06701b834352f44d37fbb6311f870f84c76b9c18" + resolved "https://registry.npm.alibaba-inc.com/react-router-dom/download/react-router-dom-5.1.2.tgz" integrity sha1-BnAbg0NS9E03+7YxH4cPhMdrnBg= dependencies: "@babel/runtime" "^7.1.2" @@ -9374,7 +11494,7 @@ react-router-dom@5.1.2: react-router-dom@5.2.0: version "5.2.0" - resolved "https://registry.npm.alibaba-inc.com/react-router-dom/download/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662" + resolved "https://registry.npm.alibaba-inc.com/react-router-dom/download/react-router-dom-5.2.0.tgz" integrity sha1-nmWk0MReEyieZsexfH4XXQ6hVmI= dependencies: "@babel/runtime" "^7.1.2" @@ -9387,7 +11507,7 @@ react-router-dom@5.2.0: react-router-dom@^5.1.2: version "5.3.4" - resolved "https://registry.npm.alibaba-inc.com/react-router-dom/download/react-router-dom-5.3.4.tgz#2ed62ffd88cae6db134445f4a0c0ae8b91d2e5e6" + resolved "https://registry.npm.alibaba-inc.com/react-router-dom/download/react-router-dom-5.3.4.tgz" integrity sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ== dependencies: "@babel/runtime" "^7.12.13" @@ -9400,7 +11520,7 @@ react-router-dom@^5.1.2: react-router@5.1.2: version "5.1.2" - resolved "https://registry.npm.alibaba-inc.com/react-router/download/react-router-5.1.2.tgz#6ea51d789cb36a6be1ba5f7c0d48dd9e817d3418" + resolved "https://registry.npm.alibaba-inc.com/react-router/download/react-router-5.1.2.tgz" integrity sha1-bqUdeJyzamvhul98DUjdnoF9NBg= dependencies: "@babel/runtime" "^7.1.2" @@ -9416,7 +11536,7 @@ react-router@5.1.2: react-router@5.2.0: version "5.2.0" - resolved "https://registry.npm.alibaba-inc.com/react-router/download/react-router-5.2.0.tgz#424e75641ca8747fbf76e5ecca69781aa37ea293" + resolved "https://registry.npm.alibaba-inc.com/react-router/download/react-router-5.2.0.tgz" integrity sha1-Qk51ZByodH+/duXsyml4GqN+opM= dependencies: "@babel/runtime" "^7.1.2" @@ -9432,7 +11552,7 @@ react-router@5.2.0: react-router@5.3.4: version "5.3.4" - resolved "https://registry.npm.alibaba-inc.com/react-router/download/react-router-5.3.4.tgz#8ca252d70fcc37841e31473c7a151cf777887bb5" + resolved "https://registry.npm.alibaba-inc.com/react-router/download/react-router-5.3.4.tgz" integrity sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA== dependencies: "@babel/runtime" "^7.12.13" @@ -9447,21 +11567,51 @@ react-router@5.3.4: react-side-effect@^2.1.0: version "2.1.2" - resolved "https://registry.npm.alibaba-inc.com/react-side-effect/download/react-side-effect-2.1.2.tgz#dc6345b9e8f9906dc2eeb68700b615e0b4fe752a" + resolved "https://registry.npm.alibaba-inc.com/react-side-effect/download/react-side-effect-2.1.2.tgz" integrity sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw== react-sortable-hoc@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/react-sortable-hoc/download/react-sortable-hoc-2.0.0.tgz#f6780d8aa4b922a21f3e754af542f032677078b7" + resolved "https://registry.npm.alibaba-inc.com/react-sortable-hoc/download/react-sortable-hoc-2.0.0.tgz" integrity sha1-9ngNiqS5IqIfPnVK9ULwMmdweLc= dependencies: "@babel/runtime" "^7.2.0" invariant "^2.2.4" prop-types "^15.5.7" +react-split-pane@^0.1.92: + version "0.1.92" + resolved "https://registry.npmjs.org/react-split-pane/-/react-split-pane-0.1.92.tgz" + integrity sha512-GfXP1xSzLMcLJI5BM36Vh7GgZBpy+U/X0no+VM3fxayv+p1Jly5HpMofZJraeaMl73b3hvlr+N9zJKvLB/uz9w== + dependencies: + prop-types "^15.7.2" + react-lifecycles-compat "^3.0.4" + react-style-proptype "^3.2.2" + +react-sticky-mouse-tooltip@^0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/react-sticky-mouse-tooltip/-/react-sticky-mouse-tooltip-0.0.1.tgz" + integrity sha512-nuKyvolX3Zsu48uoGXkEvEE8oAwl7jaUvJrA/SxCSmBmbzmECNBQp03Z60L6/1ImLUzLFUHh2Wul3GpkEffrPw== + +react-style-proptype@^3.2.2: + version "3.2.2" + resolved "https://registry.npmjs.org/react-style-proptype/-/react-style-proptype-3.2.2.tgz" + integrity sha512-ywYLSjNkxKHiZOqNlso9PZByNEY+FTyh3C+7uuziK0xFXu9xzdyfHwg4S9iyiRRoPCR4k2LqaBBsWVmSBwCWYQ== + dependencies: + prop-types "^15.5.4" + +react-textarea-autosize@^8.3.2: + version "8.5.3" + resolved "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.3.tgz" + integrity sha512-XT1024o2pqCuZSuBt9FwHlaDeNtVrtCXu0Rnz88t1jUGheCLa3PhjE1GH8Ctm2axEtvdCl5SUHYschyQ0L5QHQ== + dependencies: + "@babel/runtime" "^7.20.13" + use-composed-ref "^1.3.0" + use-latest "^1.2.1" + react-tween-state@^0.1.5: version "0.1.5" - resolved "https://registry.npm.alibaba-inc.com/react-tween-state/download/react-tween-state-0.1.5.tgz#e98b066551efb93cb92dd1be14995c2e3deae339" + resolved "https://registry.npm.alibaba-inc.com/react-tween-state/download/react-tween-state-0.1.5.tgz" integrity sha1-6YsGZVHvuTy5LdG+FJlcLj3q4zk= dependencies: raf "^3.1.0" @@ -9469,7 +11619,7 @@ react-tween-state@^0.1.5: react@16.x: version "16.14.0" - resolved "https://registry.npm.alibaba-inc.com/react/download/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d" + resolved "https://registry.npm.alibaba-inc.com/react/download/react-16.14.0.tgz" integrity sha1-lNd23dCqo32j7aj8W2sYpMmjEU0= dependencies: loose-envify "^1.1.0" @@ -9478,7 +11628,7 @@ react@16.x: react@17.0.2: version "17.0.2" - resolved "https://registry.npm.alibaba-inc.com/react/download/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" + resolved "https://registry.npm.alibaba-inc.com/react/download/react-17.0.2.tgz" integrity sha1-0LXMUW0p6z7uOD91tihkz7aAADc= dependencies: loose-envify "^1.1.0" @@ -9486,14 +11636,14 @@ react@17.0.2: reactcss@^1.2.3: version "1.2.3" - resolved "https://registry.npm.alibaba-inc.com/reactcss/download/reactcss-1.2.3.tgz#c00013875e557b1cf0dfd9a368a1c3dab3b548dd" + resolved "https://registry.npm.alibaba-inc.com/reactcss/download/reactcss-1.2.3.tgz" integrity sha1-wAATh15Vexzw39mjaKHD2rO1SN0= dependencies: lodash "^4.0.1" read-pkg-up@^7.0.1: version "7.0.1" - resolved "https://registry.npm.alibaba-inc.com/read-pkg-up/download/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + resolved "https://registry.npm.alibaba-inc.com/read-pkg-up/download/read-pkg-up-7.0.1.tgz" integrity sha1-86YTV1hFlzOuK5VjgFbhhU5+9Qc= dependencies: find-up "^4.1.0" @@ -9502,7 +11652,7 @@ read-pkg-up@^7.0.1: read-pkg@^5.2.0: version "5.2.0" - resolved "https://registry.npm.alibaba-inc.com/read-pkg/download/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + resolved "https://registry.npm.alibaba-inc.com/read-pkg/download/read-pkg-5.2.0.tgz" integrity sha1-e/KVQ4yloz5WzTDgU7NO5yUMk8w= dependencies: "@types/normalize-package-data" "^2.4.0" @@ -9512,7 +11662,7 @@ read-pkg@^5.2.0: readable-stream@^2.0.2, readable-stream@^2.3.3, readable-stream@^2.3.6: version "2.3.7" - resolved "https://registry.npm.alibaba-inc.com/readable-stream/download/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + resolved "https://registry.npm.alibaba-inc.com/readable-stream/download/readable-stream-2.3.7.tgz" integrity sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c= dependencies: core-util-is "~1.0.0" @@ -9525,7 +11675,7 @@ readable-stream@^2.0.2, readable-stream@^2.3.3, readable-stream@^2.3.6: readable-stream@^3.1.1, readable-stream@^3.6.0: version "3.6.0" - resolved "https://registry.npm.alibaba-inc.com/readable-stream/download/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + resolved "https://registry.npm.alibaba-inc.com/readable-stream/download/readable-stream-3.6.0.tgz" integrity sha1-M3u9o63AcGvT4CRCaihtS0sskZg= dependencies: inherits "^2.0.3" @@ -9534,14 +11684,14 @@ readable-stream@^3.1.1, readable-stream@^3.6.0: readdirp@~3.5.0: version "3.5.0" - resolved "https://registry.npm.alibaba-inc.com/readdirp/download/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" + resolved "https://registry.npm.alibaba-inc.com/readdirp/download/readdirp-3.5.0.tgz" integrity sha1-m6dMAZsV02UnjS6Ru4xI17TULJ4= dependencies: picomatch "^2.2.1" redent@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/redent/download/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + resolved "https://registry.npm.alibaba-inc.com/redent/download/redent-3.0.0.tgz" integrity sha1-5Ve3mYMWu1PJ8fVvpiY1LGljBZ8= dependencies: indent-string "^4.0.0" @@ -9549,70 +11699,75 @@ redent@^3.0.0: redux-saga@^0.16.0: version "0.16.2" - resolved "https://registry.npm.alibaba-inc.com/redux-saga/download/redux-saga-0.16.2.tgz#993662e86bc945d8509ac2b8daba3a8c615cc971" + resolved "https://registry.npm.alibaba-inc.com/redux-saga/download/redux-saga-0.16.2.tgz" integrity sha1-mTZi6GvJRdhQmsK42ro6jGFcyXE= redux@^4.0.0, redux@^4.0.1: version "4.2.0" - resolved "https://registry.npm.alibaba-inc.com/redux/download/redux-4.2.0.tgz#46f10d6e29b6666df758780437651eeb2b969f13" + resolved "https://registry.npm.alibaba-inc.com/redux/download/redux-4.2.0.tgz" integrity sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA== dependencies: "@babel/runtime" "^7.9.2" reftools@^1.1.9: version "1.1.9" - resolved "https://registry.npm.alibaba-inc.com/reftools/download/reftools-1.1.9.tgz#e16e19f662ccd4648605312c06d34e5da3a2b77e" + resolved "https://registry.npm.alibaba-inc.com/reftools/download/reftools-1.1.9.tgz" integrity sha1-4W4Z9mLM1GSGBTEsBtNOXaOit34= regenerate-unicode-properties@10.0.1: version "10.0.1" - resolved "https://registry.npm.alibaba-inc.com/regenerate-unicode-properties/download/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56" + resolved "https://registry.npm.alibaba-inc.com/regenerate-unicode-properties/download/regenerate-unicode-properties-10.0.1.tgz" integrity sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw== dependencies: regenerate "^1.4.2" regenerate-unicode-properties@^10.1.0: version "10.1.0" - resolved "https://registry.npm.alibaba-inc.com/regenerate-unicode-properties/download/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" + resolved "https://registry.npm.alibaba-inc.com/regenerate-unicode-properties/download/regenerate-unicode-properties-10.1.0.tgz" integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ== dependencies: regenerate "^1.4.2" regenerate@^1.4.2: version "1.4.2" - resolved "https://registry.npm.alibaba-inc.com/regenerate/download/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + resolved "https://registry.npm.alibaba-inc.com/regenerate/download/regenerate-1.4.2.tgz" integrity sha1-uTRtiCfo9aMve6KWN9OYtpAUhIo= regenerator-runtime@0.13.5: version "0.13.5" - resolved "https://registry.npm.alibaba-inc.com/regenerator-runtime/download/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" + resolved "https://registry.npm.alibaba-inc.com/regenerator-runtime/download/regenerator-runtime-0.13.5.tgz" integrity sha1-2Hih0JS0MG0QuQlkhLM+vVXiZpc= regenerator-runtime@^0.11.0: version "0.11.1" - resolved "https://registry.npm.alibaba-inc.com/regenerator-runtime/download/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + resolved "https://registry.npm.alibaba-inc.com/regenerator-runtime/download/regenerator-runtime-0.11.1.tgz" integrity sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk= regenerator-runtime@^0.13.10, regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: version "0.13.10" - resolved "https://registry.npm.alibaba-inc.com/regenerator-runtime/download/regenerator-runtime-0.13.10.tgz#ed07b19616bcbec5da6274ebc75ae95634bfc2ee" + resolved "https://registry.npm.alibaba-inc.com/regenerator-runtime/download/regenerator-runtime-0.13.10.tgz" integrity sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw== regenerator-runtime@^0.13.11: version "0.13.11" - resolved "https://registry.npm.alibaba-inc.com/regenerator-runtime/download/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + resolved "https://registry.npm.alibaba-inc.com/regenerator-runtime/download/regenerator-runtime-0.13.11.tgz" integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== +regenerator-runtime@^0.14.0: + version "0.14.0" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz" + integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== + regenerator-transform@^0.15.0: version "0.15.1" - resolved "https://registry.npm.alibaba-inc.com/regenerator-transform/download/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56" + resolved "https://registry.npm.alibaba-inc.com/regenerator-transform/download/regenerator-transform-0.15.1.tgz" integrity sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg== dependencies: "@babel/runtime" "^7.8.4" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/regex-not/download/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + resolved "https://registry.npm.alibaba-inc.com/regex-not/download/regex-not-1.0.2.tgz" integrity sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw= dependencies: extend-shallow "^3.0.2" @@ -9620,26 +11775,35 @@ regex-not@^1.0.0, regex-not@^1.0.2: regexp-tree@^0.1.21, regexp-tree@~0.1.1: version "0.1.24" - resolved "https://registry.npm.alibaba-inc.com/regexp-tree/download/regexp-tree-0.1.24.tgz#3d6fa238450a4d66e5bc9c4c14bb720e2196829d" + resolved "https://registry.npm.alibaba-inc.com/regexp-tree/download/regexp-tree-0.1.24.tgz" integrity sha1-PW+iOEUKTWblvJxMFLtyDiGWgp0= regexp.prototype.flags@^1.4.3: version "1.4.3" - resolved "https://registry.npm.alibaba-inc.com/regexp.prototype.flags/download/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" + resolved "https://registry.npm.alibaba-inc.com/regexp.prototype.flags/download/regexp.prototype.flags-1.4.3.tgz" integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" functions-have-names "^1.2.2" +regexp.prototype.flags@^1.5.0: + version "1.5.1" + resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz" + integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + set-function-name "^2.0.0" + regexpp@^3.1.0, regexpp@^3.2.0: version "3.2.0" - resolved "https://registry.npm.alibaba-inc.com/regexpp/download/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + resolved "https://registry.npm.alibaba-inc.com/regexpp/download/regexpp-3.2.0.tgz" integrity sha1-BCWido2PI7rXDKS5BGH6LxIT4bI= regexpu-core@^5.1.0: version "5.2.2" - resolved "https://registry.npm.alibaba-inc.com/regexpu-core/download/regexpu-core-5.2.2.tgz#3e4e5d12103b64748711c3aad69934d7718e75fc" + resolved "https://registry.npm.alibaba-inc.com/regexpu-core/download/regexpu-core-5.2.2.tgz" integrity sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw== dependencies: regenerate "^1.4.2" @@ -9651,33 +11815,38 @@ regexpu-core@^5.1.0: regjsgen@^0.7.1: version "0.7.1" - resolved "https://registry.npm.alibaba-inc.com/regjsgen/download/regjsgen-0.7.1.tgz#ee5ef30e18d3f09b7c369b76e7c2373ed25546f6" + resolved "https://registry.npm.alibaba-inc.com/regjsgen/download/regjsgen-0.7.1.tgz" integrity sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA== regjsparser@^0.9.1: version "0.9.1" - resolved "https://registry.npm.alibaba-inc.com/regjsparser/download/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" + resolved "https://registry.npm.alibaba-inc.com/regjsparser/download/regjsparser-0.9.1.tgz" integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== dependencies: jsesc "~0.5.0" +regl@^1.3.11: + version "1.7.0" + resolved "https://registry.npmjs.org/regl/-/regl-1.7.0.tgz" + integrity sha512-bEAtp/qrtKucxXSJkD4ebopFZYP0q1+3Vb2WECWv/T8yQEgKxDxJ7ztO285tAMaYZVR6mM1GgI6CCn8FROtL1w== + remark-parse@^9.0.0: version "9.0.0" - resolved "https://registry.npm.alibaba-inc.com/remark-parse/download/remark-parse-9.0.0.tgz#4d20a299665880e4f4af5d90b7c7b8a935853640" + resolved "https://registry.npm.alibaba-inc.com/remark-parse/download/remark-parse-9.0.0.tgz" integrity sha1-TSCimWZYgOT0r12Qt8e4qTWFNkA= dependencies: mdast-util-from-markdown "^0.8.0" remark-stringify@^9.0.0: version "9.0.1" - resolved "https://registry.npm.alibaba-inc.com/remark-stringify/download/remark-stringify-9.0.1.tgz#576d06e910548b0a7191a71f27b33f1218862894" + resolved "https://registry.npm.alibaba-inc.com/remark-stringify/download/remark-stringify-9.0.1.tgz" integrity sha1-V20G6RBUiwpxkacfJ7M/EhiGKJQ= dependencies: mdast-util-to-markdown "^0.6.0" remark@^13.0.0: version "13.0.0" - resolved "https://registry.npm.alibaba-inc.com/remark/download/remark-13.0.0.tgz#d15d9bf71a402f40287ebe36067b66d54868e425" + resolved "https://registry.npm.alibaba-inc.com/remark/download/remark-13.0.0.tgz" integrity sha1-0V2b9xpAL0Aofr42Bntm1Uho5CU= dependencies: remark-parse "^9.0.0" @@ -9686,84 +11855,84 @@ remark@^13.0.0: remove-trailing-separator@^1.0.1: version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/remove-trailing-separator/download/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + resolved "https://registry.npm.alibaba-inc.com/remove-trailing-separator/download/remove-trailing-separator-1.1.0.tgz" integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= repeat-element@^1.1.2: version "1.1.4" - resolved "https://registry.npm.alibaba-inc.com/repeat-element/download/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" + resolved "https://registry.npm.alibaba-inc.com/repeat-element/download/repeat-element-1.1.4.tgz" integrity sha1-vmgVIIR6tYx1aKx1+/rSjtQtOek= repeat-string@^1.0.0, repeat-string@^1.6.1: version "1.6.1" - resolved "https://registry.npm.alibaba-inc.com/repeat-string/download/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + resolved "https://registry.npm.alibaba-inc.com/repeat-string/download/repeat-string-1.6.1.tgz" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.npm.alibaba-inc.com/require-directory/download/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + resolved "https://registry.npm.alibaba-inc.com/require-directory/download/require-directory-2.1.1.tgz" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= require-from-string@^2.0.2: version "2.0.2" - resolved "https://registry.npm.alibaba-inc.com/require-from-string/download/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + resolved "https://registry.npm.alibaba-inc.com/require-from-string/download/require-from-string-2.0.2.tgz" integrity sha1-iaf92TgmEmcxjq/hT5wy5ZjDaQk= require-main-filename@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/require-main-filename/download/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + resolved "https://registry.npm.alibaba-inc.com/require-main-filename/download/require-main-filename-2.0.0.tgz" integrity sha1-0LMp7MfMD2Fkn2IhW+aa9UqomJs= requires-port@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/requires-port/download/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + resolved "https://registry.npm.alibaba-inc.com/requires-port/download/requires-port-1.0.0.tgz" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= reserved-words@^0.1.2: version "0.1.2" - resolved "https://registry.npm.alibaba-inc.com/reserved-words/download/reserved-words-0.1.2.tgz#00a0940f98cd501aeaaac316411d9adc52b31ab1" + resolved "https://registry.npm.alibaba-inc.com/reserved-words/download/reserved-words-0.1.2.tgz" integrity sha1-AKCUD5jNUBrqqsMWQR2a3FKzGrE= resize-observer-polyfill@^1.5.1: version "1.5.1" - resolved "https://registry.npm.alibaba-inc.com/resize-observer-polyfill/download/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" + resolved "https://registry.npm.alibaba-inc.com/resize-observer-polyfill/download/resize-observer-polyfill-1.5.1.tgz" integrity sha1-DpAg3T0hAkRY1OvSfiPkAmmBBGQ= resolve-cwd@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/resolve-cwd/download/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + resolved "https://registry.npm.alibaba-inc.com/resolve-cwd/download/resolve-cwd-3.0.0.tgz" integrity sha1-DwB18bslRHZs9zumpuKt/ryxPy0= dependencies: resolve-from "^5.0.0" resolve-from@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/resolve-from/download/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + resolved "https://registry.npm.alibaba-inc.com/resolve-from/download/resolve-from-3.0.0.tgz" integrity sha1-six699nWiBvItuZTM17rywoYh0g= resolve-from@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/resolve-from/download/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + resolved "https://registry.npm.alibaba-inc.com/resolve-from/download/resolve-from-4.0.0.tgz" integrity sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY= resolve-from@^5.0.0: version "5.0.0" - resolved "https://registry.npm.alibaba-inc.com/resolve-from/download/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + resolved "https://registry.npm.alibaba-inc.com/resolve-from/download/resolve-from-5.0.0.tgz" integrity sha1-w1IlhD3493bfIcV1V7wIfp39/Gk= resolve-pathname@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/resolve-pathname/download/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" + resolved "https://registry.npm.alibaba-inc.com/resolve-pathname/download/resolve-pathname-3.0.0.tgz" integrity sha1-mdAiJNPPJjaJvsuzk7xWAxMCXc0= resolve-url@^0.2.1: version "0.2.1" - resolved "https://registry.npm.alibaba-inc.com/resolve-url/download/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + resolved "https://registry.npm.alibaba-inc.com/resolve-url/download/resolve-url-0.2.1.tgz" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= resolve@^1.10.0, resolve@^1.14.2, resolve@^1.18.1: version "1.22.1" - resolved "https://registry.npm.alibaba-inc.com/resolve/download/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + resolved "https://registry.npm.alibaba-inc.com/resolve/download/resolve-1.22.1.tgz" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== dependencies: is-core-module "^2.9.0" @@ -9772,7 +11941,7 @@ resolve@^1.10.0, resolve@^1.14.2, resolve@^1.18.1: resolve@^2.0.0-next.3: version "2.0.0-next.4" - resolved "https://registry.npm.alibaba-inc.com/resolve/download/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660" + resolved "https://registry.npm.alibaba-inc.com/resolve/download/resolve-2.0.0-next.4.tgz" integrity sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ== dependencies: is-core-module "^2.9.0" @@ -9781,7 +11950,7 @@ resolve@^2.0.0-next.3: restore-cursor@^3.1.0: version "3.1.0" - resolved "https://registry.npm.alibaba-inc.com/restore-cursor/download/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + resolved "https://registry.npm.alibaba-inc.com/restore-cursor/download/restore-cursor-3.1.0.tgz" integrity sha1-OfZ8VLOnpYzqUjbZXPADQjljH34= dependencies: onetime "^5.1.0" @@ -9789,34 +11958,34 @@ restore-cursor@^3.1.0: ret@^0.2.0: version "0.2.2" - resolved "https://registry.npm.alibaba-inc.com/ret/download/ret-0.2.2.tgz#b6861782a1f4762dce43402a71eb7a283f44573c" + resolved "https://registry.npm.alibaba-inc.com/ret/download/ret-0.2.2.tgz" integrity sha1-toYXgqH0di3OQ0Aqcet6KD9EVzw= ret@~0.1.10: version "0.1.15" - resolved "https://registry.npm.alibaba-inc.com/ret/download/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + resolved "https://registry.npm.alibaba-inc.com/ret/download/ret-0.1.15.tgz" integrity sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w= reusify@^1.0.4: version "1.0.4" - resolved "https://registry.npm.alibaba-inc.com/reusify/download/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + resolved "https://registry.npm.alibaba-inc.com/reusify/download/reusify-1.0.4.tgz" integrity sha1-kNo4Kx4SbvwCFG6QhFqI2xKSXXY= rfdc@^1.3.0: version "1.3.0" - resolved "https://registry.npm.alibaba-inc.com/rfdc/download/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + resolved "https://registry.npm.alibaba-inc.com/rfdc/download/rfdc-1.3.0.tgz" integrity sha1-0LfEQasnINBdxM8m4ByJYx2doIs= rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" - resolved "https://registry.npm.alibaba-inc.com/rimraf/download/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + resolved "https://registry.npm.alibaba-inc.com/rimraf/download/rimraf-3.0.2.tgz" integrity sha1-8aVAK6YiCtUswSgrrBrjqkn9Bho= dependencies: glob "^7.1.3" ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" - resolved "https://registry.npm.alibaba-inc.com/ripemd160/download/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + resolved "https://registry.npm.alibaba-inc.com/ripemd160/download/ripemd160-2.0.2.tgz" integrity sha1-ocGm9iR1FXe6XQeRTLyShQWFiQw= dependencies: hash-base "^3.0.0" @@ -9824,7 +11993,7 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: rmc-align@~1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/rmc-align/download/rmc-align-1.0.0.tgz#8d64ab484609a041ab424506012a15b7c5b933dd" + resolved "https://registry.npm.alibaba-inc.com/rmc-align/download/rmc-align-1.0.0.tgz" integrity sha1-jWSrSEYJoEGrQkUGASoVt8W5M90= dependencies: babel-runtime "6.x" @@ -9833,7 +12002,7 @@ rmc-align@~1.0.0: rmc-calendar@^1.0.0: version "1.1.4" - resolved "https://registry.npm.alibaba-inc.com/rmc-calendar/download/rmc-calendar-1.1.4.tgz#7db4990087877cd49a7772f4524d33b8016d3bd2" + resolved "https://registry.npm.alibaba-inc.com/rmc-calendar/download/rmc-calendar-1.1.4.tgz" integrity sha1-fbSZAIeHfNSad3L0Uk0zuAFtO9I= dependencies: babel-runtime "^6.26.0" @@ -9842,7 +12011,7 @@ rmc-calendar@^1.0.0: rmc-cascader@~5.0.0: version "5.0.3" - resolved "https://registry.npm.alibaba-inc.com/rmc-cascader/download/rmc-cascader-5.0.3.tgz#c605b1eac6613e4c54aa6aed2cbae7f9c5a8c65f" + resolved "https://registry.npm.alibaba-inc.com/rmc-cascader/download/rmc-cascader-5.0.3.tgz" integrity sha1-xgWx6sZhPkxUqmrtLLrn+cWoxl8= dependencies: array-tree-filter "2.1.x" @@ -9851,7 +12020,7 @@ rmc-cascader@~5.0.0: rmc-date-picker@^6.0.8: version "6.0.10" - resolved "https://registry.npm.alibaba-inc.com/rmc-date-picker/download/rmc-date-picker-6.0.10.tgz#34dc7dfd424248be2d43527421576247c31583f6" + resolved "https://registry.npm.alibaba-inc.com/rmc-date-picker/download/rmc-date-picker-6.0.10.tgz" integrity sha1-NNx9/UJCSL4tQ1J0IVdiR8MVg/Y= dependencies: babel-runtime "6.x" @@ -9859,7 +12028,7 @@ rmc-date-picker@^6.0.8: rmc-dialog@^1.0.1, rmc-dialog@^1.1.1: version "1.1.1" - resolved "https://registry.npm.alibaba-inc.com/rmc-dialog/download/rmc-dialog-1.1.1.tgz#1d7fbc6b2cad5b0b53fbab71fe29636d76f78217" + resolved "https://registry.npm.alibaba-inc.com/rmc-dialog/download/rmc-dialog-1.1.1.tgz" integrity sha1-HX+8ayytWwtT+6tx/iljbXb3ghc= dependencies: babel-runtime "6.x" @@ -9867,7 +12036,7 @@ rmc-dialog@^1.0.1, rmc-dialog@^1.1.1: rmc-drawer@^0.4.11: version "0.4.11" - resolved "https://registry.npm.alibaba-inc.com/rmc-drawer/download/rmc-drawer-0.4.11.tgz#9a8c6125a4ccd37b916f32f7e8b477d11d413ee3" + resolved "https://registry.npm.alibaba-inc.com/rmc-drawer/download/rmc-drawer-0.4.11.tgz" integrity sha1-moxhJaTM03uRbzL36LR30R1BPuM= dependencies: babel-runtime "6.x" @@ -9876,7 +12045,7 @@ rmc-drawer@^0.4.11: rmc-feedback@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/rmc-feedback/download/rmc-feedback-2.0.0.tgz#cbc6cb3ae63c7a635eef0e25e4fbaf5ac366eeaa" + resolved "https://registry.npm.alibaba-inc.com/rmc-feedback/download/rmc-feedback-2.0.0.tgz" integrity sha1-y8bLOuY8emNe7w4l5PuvWsNm7qo= dependencies: babel-runtime "6.x" @@ -9884,7 +12053,7 @@ rmc-feedback@^2.0.0: rmc-input-number@^1.0.0: version "1.0.5" - resolved "https://registry.npm.alibaba-inc.com/rmc-input-number/download/rmc-input-number-1.0.5.tgz#42e02a27b0c3c366be9ff0ce19d818b71e406f8f" + resolved "https://registry.npm.alibaba-inc.com/rmc-input-number/download/rmc-input-number-1.0.5.tgz" integrity sha1-QuAqJ7DDw2a+n/DOGdgYtx5Ab48= dependencies: babel-runtime "6.x" @@ -9893,7 +12062,7 @@ rmc-input-number@^1.0.0: rmc-list-view@^0.11.0: version "0.11.5" - resolved "https://registry.npm.alibaba-inc.com/rmc-list-view/download/rmc-list-view-0.11.5.tgz#8e152a5dbec6aec45a8ccd1f33cb8ef140b93a1e" + resolved "https://registry.npm.alibaba-inc.com/rmc-list-view/download/rmc-list-view-0.11.5.tgz" integrity sha1-jhUqXb7GrsRajM0fM8uO8UC5Oh4= dependencies: babel-runtime "6.x" @@ -9905,7 +12074,7 @@ rmc-list-view@^0.11.0: rmc-notification@~1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/rmc-notification/download/rmc-notification-1.0.0.tgz#1fcee98f99b9733f7ce63a91d7663a578743d075" + resolved "https://registry.npm.alibaba-inc.com/rmc-notification/download/rmc-notification-1.0.0.tgz" integrity sha1-H87pj5m5cz985jqR12Y6V4dD0HU= dependencies: babel-runtime "6.x" @@ -9916,7 +12085,7 @@ rmc-notification@~1.0.0: rmc-nuka-carousel@~3.0.0: version "3.0.1" - resolved "https://registry.npm.alibaba-inc.com/rmc-nuka-carousel/download/rmc-nuka-carousel-3.0.1.tgz#a2a997676b0f986354976dac39ec66d8701b4b71" + resolved "https://registry.npm.alibaba-inc.com/rmc-nuka-carousel/download/rmc-nuka-carousel-3.0.1.tgz" integrity sha1-oqmXZ2sPmGNUl22sOexm2HAbS3E= dependencies: exenv "^1.2.0" @@ -9924,7 +12093,7 @@ rmc-nuka-carousel@~3.0.0: rmc-picker@~5.0.0: version "5.0.10" - resolved "https://registry.npm.alibaba-inc.com/rmc-picker/download/rmc-picker-5.0.10.tgz#9ca0acf45ad2c8afe9015a103a898436d825e18f" + resolved "https://registry.npm.alibaba-inc.com/rmc-picker/download/rmc-picker-5.0.10.tgz" integrity sha1-nKCs9FrSyK/pAVoQOomENtgl4Y8= dependencies: babel-runtime "6.x" @@ -9934,7 +12103,7 @@ rmc-picker@~5.0.0: rmc-pull-to-refresh@~1.0.1: version "1.0.13" - resolved "https://registry.npm.alibaba-inc.com/rmc-pull-to-refresh/download/rmc-pull-to-refresh-1.0.13.tgz#8fc1bd36c9b09fcd50e8d8632f556b6a8462ef1a" + resolved "https://registry.npm.alibaba-inc.com/rmc-pull-to-refresh/download/rmc-pull-to-refresh-1.0.13.tgz" integrity sha1-j8G9Nsmwn81Q6NhjL1VraoRi7xo= dependencies: babel-runtime "6.x" @@ -9942,7 +12111,7 @@ rmc-pull-to-refresh@~1.0.1: rmc-steps@~1.0.0: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/rmc-steps/download/rmc-steps-1.0.1.tgz#b63a0f1ddd2826d03b1bcec85963077255e8f798" + resolved "https://registry.npm.alibaba-inc.com/rmc-steps/download/rmc-steps-1.0.1.tgz" integrity sha1-tjoPHd0oJtA7G87IWWMHclXo95g= dependencies: babel-runtime "^6.23.0" @@ -9950,7 +12119,7 @@ rmc-steps@~1.0.0: rmc-tabs@~1.2.0: version "1.2.29" - resolved "https://registry.npm.alibaba-inc.com/rmc-tabs/download/rmc-tabs-1.2.29.tgz#dd2191525debbf8521e85aeb6d97670f652e4c83" + resolved "https://registry.npm.alibaba-inc.com/rmc-tabs/download/rmc-tabs-1.2.29.tgz" integrity sha1-3SGRUl3rv4Uh6FrrbZdnD2UuTIM= dependencies: babel-runtime "6.x" @@ -9958,7 +12127,7 @@ rmc-tabs@~1.2.0: rmc-tooltip@~1.0.0: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/rmc-tooltip/download/rmc-tooltip-1.0.1.tgz#5af16a3e8f764fa26d2b11932975bd88b1d848d2" + resolved "https://registry.npm.alibaba-inc.com/rmc-tooltip/download/rmc-tooltip-1.0.1.tgz" integrity sha1-WvFqPo92T6JtKxGTKXW9iLHYSNI= dependencies: babel-runtime "6.x" @@ -9966,7 +12135,7 @@ rmc-tooltip@~1.0.0: rmc-trigger@1.x: version "1.0.12" - resolved "https://registry.npm.alibaba-inc.com/rmc-trigger/download/rmc-trigger-1.0.12.tgz#34df10a16f1fc8f9e8b14d13d58cabe294ab7488" + resolved "https://registry.npm.alibaba-inc.com/rmc-trigger/download/rmc-trigger-1.0.12.tgz" integrity sha1-NN8QoW8fyPnosU0T1Yyr4pSrdIg= dependencies: babel-runtime "6.x" @@ -9976,50 +12145,60 @@ rmc-trigger@1.x: rsvp@^4.8.4: version "4.8.5" - resolved "https://registry.npm.alibaba-inc.com/rsvp/download/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" + resolved "https://registry.npm.alibaba-inc.com/rsvp/download/rsvp-4.8.5.tgz" integrity sha1-yPFVMR0Wf2jyHhaN9x7FsIMRNzQ= run-parallel@^1.1.9: version "1.2.0" - resolved "https://registry.npm.alibaba-inc.com/run-parallel/download/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + resolved "https://registry.npm.alibaba-inc.com/run-parallel/download/run-parallel-1.2.0.tgz" integrity sha1-ZtE2jae9+SHrnZW9GpIp5/IaQ+4= dependencies: queue-microtask "^1.2.2" rust-result@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/rust-result/download/rust-result-1.0.0.tgz#34c75b2e6dc39fe5875e5bdec85b5e0f91536f72" + resolved "https://registry.npm.alibaba-inc.com/rust-result/download/rust-result-1.0.0.tgz" integrity sha1-NMdbLm3Dn+WHXlveyFteD5FTb3I= dependencies: individual "^2.0.0" rxjs@^7.5.1: version "7.5.7" - resolved "https://registry.npm.alibaba-inc.com/rxjs/download/rxjs-7.5.7.tgz#2ec0d57fdc89ece220d2e702730ae8f1e49def39" + resolved "https://registry.npm.alibaba-inc.com/rxjs/download/rxjs-7.5.7.tgz" integrity sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA== dependencies: tslib "^2.1.0" +safe-array-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz" + integrity sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + isarray "^2.0.5" + safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.1" - resolved "https://registry.npm.alibaba-inc.com/safe-buffer/download/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + resolved "https://registry.npm.alibaba-inc.com/safe-buffer/download/safe-buffer-5.2.1.tgz" integrity sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY= safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" - resolved "https://registry.npm.alibaba-inc.com/safe-buffer/download/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + resolved "https://registry.npm.alibaba-inc.com/safe-buffer/download/safe-buffer-5.1.2.tgz" integrity sha1-mR7GnSluAxN0fVm9/St0XDX4go0= safe-json-parse@4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/safe-json-parse/download/safe-json-parse-4.0.0.tgz#7c0f578cfccd12d33a71c0e05413e2eca171eaac" + resolved "https://registry.npm.alibaba-inc.com/safe-json-parse/download/safe-json-parse-4.0.0.tgz" integrity sha1-fA9XjPzNEtM6ccDgVBPi7KFx6qw= dependencies: rust-result "^1.0.0" safe-regex-test@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/safe-regex-test/download/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + resolved "https://registry.npm.alibaba-inc.com/safe-regex-test/download/safe-regex-test-1.0.0.tgz" integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== dependencies: call-bind "^1.0.2" @@ -10028,26 +12207,31 @@ safe-regex-test@^1.0.0: safe-regex@^1.1.0: version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/safe-regex/download/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + resolved "https://registry.npm.alibaba-inc.com/safe-regex/download/safe-regex-1.1.0.tgz" integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= dependencies: ret "~0.1.10" safe-regex@^2.1.1: version "2.1.1" - resolved "https://registry.npm.alibaba-inc.com/safe-regex/download/safe-regex-2.1.1.tgz#f7128f00d056e2fe5c11e81a1324dd974aadced2" + resolved "https://registry.npm.alibaba-inc.com/safe-regex/download/safe-regex-2.1.1.tgz" integrity sha1-9xKPANBW4v5cEegaEyTdl0qtztI= dependencies: regexp-tree "~0.1.1" +safe-stable-stringify@^2.4.3: + version "2.4.3" + resolved "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz" + integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== + "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.1.0: version "2.1.2" - resolved "https://registry.npm.alibaba-inc.com/safer-buffer/download/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + resolved "https://registry.npm.alibaba-inc.com/safer-buffer/download/safer-buffer-2.1.2.tgz" integrity sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo= sane@^4.0.3: version "4.1.0" - resolved "https://registry.npm.alibaba-inc.com/sane/download/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" + resolved "https://registry.npm.alibaba-inc.com/sane/download/sane-4.1.0.tgz" integrity sha1-7Ygf2SJzOmxGG8GJ3CtsAG8//e0= dependencies: "@cnakazawa/watch" "^1.0.3" @@ -10060,16 +12244,21 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" +sax@~1.2.4: + version "1.2.4" + resolved "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + saxes@^5.0.1: version "5.0.1" - resolved "https://registry.npm.alibaba-inc.com/saxes/download/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + resolved "https://registry.npm.alibaba-inc.com/saxes/download/saxes-5.0.1.tgz" integrity sha1-7rq5U/o7dgjb6U5drbFciI+maW0= dependencies: xmlchars "^2.2.0" scheduler@^0.19.1: version "0.19.1" - resolved "https://registry.npm.alibaba-inc.com/scheduler/download/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" + resolved "https://registry.npm.alibaba-inc.com/scheduler/download/scheduler-0.19.1.tgz" integrity sha1-Tz4u0sGn1laB9MhU+oxaHMtA8ZY= dependencies: loose-envify "^1.1.0" @@ -10077,7 +12266,7 @@ scheduler@^0.19.1: scheduler@^0.20.2: version "0.20.2" - resolved "https://registry.npm.alibaba-inc.com/scheduler/download/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" + resolved "https://registry.npm.alibaba-inc.com/scheduler/download/scheduler-0.20.2.tgz" integrity sha1-S67jlDbjSqk7SHS93L8P6Li1DpE= dependencies: loose-envify "^1.1.0" @@ -10085,7 +12274,7 @@ scheduler@^0.20.2: schema-utils@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/schema-utils/download/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" + resolved "https://registry.npm.alibaba-inc.com/schema-utils/download/schema-utils-1.0.0.tgz" integrity sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A= dependencies: ajv "^6.1.0" @@ -10094,57 +12283,67 @@ schema-utils@^1.0.0: schema-utils@^3.0.0: version "3.1.1" - resolved "https://registry.npm.alibaba-inc.com/schema-utils/download/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" + resolved "https://registry.npm.alibaba-inc.com/schema-utils/download/schema-utils-3.1.1.tgz" integrity sha1-vHTEtraZXB2I92qLd76nIZ4MgoE= dependencies: "@types/json-schema" "^7.0.8" ajv "^6.12.5" ajv-keywords "^3.5.2" +screenfull@^5.0.0: + version "5.2.0" + resolved "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz" + integrity sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA== + +screenfull@^6.0.2: + version "6.0.2" + resolved "https://registry.npmjs.org/screenfull/-/screenfull-6.0.2.tgz" + integrity sha512-AQdy8s4WhNvUZ6P8F6PB21tSPIYKniic+Ogx0AacBMjKP1GUHN2E9URxQHtCusiwxudnCKkdy4GrHXPPJSkCCw== + scroll-into-view-if-needed@^2.2.25: version "2.2.29" - resolved "https://registry.npm.alibaba-inc.com/scroll-into-view-if-needed/download/scroll-into-view-if-needed-2.2.29.tgz#551791a84b7e2287706511f8c68161e4990ab885" + resolved "https://registry.npm.alibaba-inc.com/scroll-into-view-if-needed/download/scroll-into-view-if-needed-2.2.29.tgz" integrity sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg== dependencies: compute-scroll-into-view "^1.0.17" scroll-into-view-if-needed@^3.0.3: version "3.0.6" - resolved "https://registry.npm.alibaba-inc.com/scroll-into-view-if-needed/download/scroll-into-view-if-needed-3.0.6.tgz#2c803a509c1036bc4a9c009fecc5c145f87e47cf" + resolved "https://registry.npm.alibaba-inc.com/scroll-into-view-if-needed/download/scroll-into-view-if-needed-3.0.6.tgz" integrity sha512-x+CW0kOzlFNOnseF0DBr0AJ5m+TgGmSOdEZwyiZW0gV87XBvxQKw5A8DvFFgabznA68XqLgVX+PwPX8OzsFvRA== dependencies: compute-scroll-into-view "^3.0.0" seamless-immutable@^7.1.3: version "7.1.4" - resolved "https://registry.npm.alibaba-inc.com/seamless-immutable/download/seamless-immutable-7.1.4.tgz#6e9536def083ddc4dea0207d722e0e80d0f372f8" + resolved "https://registry.npm.alibaba-inc.com/seamless-immutable/download/seamless-immutable-7.1.4.tgz" integrity sha1-bpU23vCD3cTeoCB9ci4OgNDzcvg= semver-compare@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/semver-compare/download/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" + resolved "https://registry.npm.alibaba-inc.com/semver-compare/download/semver-compare-1.0.0.tgz" integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= "semver@2 || 3 || 4 || 5", semver@^5.5.0: version "5.7.1" - resolved "https://registry.npm.alibaba-inc.com/semver/download/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + resolved "https://registry.npm.alibaba-inc.com/semver/download/semver-5.7.1.tgz" integrity sha1-qVT5Ma66UI0we78Gnv8MAclhFvc= semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: version "6.3.0" - resolved "https://registry.npm.alibaba-inc.com/semver/download/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + resolved "https://registry.npm.alibaba-inc.com/semver/download/semver-6.3.0.tgz" integrity sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0= semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7: version "7.3.8" - resolved "https://registry.npm.alibaba-inc.com/semver/download/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" + resolved "https://registry.npm.alibaba-inc.com/semver/download/semver-7.3.8.tgz" integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== dependencies: lru-cache "^6.0.0" send@0.18.0: version "0.18.0" - resolved "https://registry.npm.alibaba-inc.com/send/download/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + resolved "https://registry.npm.alibaba-inc.com/send/download/send-0.18.0.tgz" integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== dependencies: debug "2.6.9" @@ -10163,7 +12362,7 @@ send@0.18.0: serve-static@^1.14.1: version "1.15.0" - resolved "https://registry.npm.alibaba-inc.com/serve-static/download/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + resolved "https://registry.npm.alibaba-inc.com/serve-static/download/serve-static-1.15.0.tgz" integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== dependencies: encodeurl "~1.0.2" @@ -10173,12 +12372,20 @@ serve-static@^1.14.1: set-blocking@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/set-blocking/download/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + resolved "https://registry.npm.alibaba-inc.com/set-blocking/download/set-blocking-2.0.0.tgz" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= +set-function-name@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.0.tgz" + integrity sha512-WmS8UHojv5s1eSoRSmzO5zzgDq8PE1/X/ij0k+9fMYmINCc6+j+SF3Om8YyucKn2yjnK4ItNZOoQycNnHsZJTw== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" - resolved "https://registry.npm.alibaba-inc.com/set-value/download/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + resolved "https://registry.npm.alibaba-inc.com/set-value/download/set-value-2.0.1.tgz" integrity sha1-oY1AUw5vB95CKMfe/kInr4ytAFs= dependencies: extend-shallow "^2.0.1" @@ -10188,17 +12395,17 @@ set-value@^2.0.0, set-value@^2.0.1: setimmediate@^1.0.4, setimmediate@^1.0.5: version "1.0.5" - resolved "https://registry.npm.alibaba-inc.com/setimmediate/download/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + resolved "https://registry.npm.alibaba-inc.com/setimmediate/download/setimmediate-1.0.5.tgz" integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= setprototypeof@1.2.0: version "1.2.0" - resolved "https://registry.npm.alibaba-inc.com/setprototypeof/download/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + resolved "https://registry.npm.alibaba-inc.com/setprototypeof/download/setprototypeof-1.2.0.tgz" integrity sha1-ZsmiSnP5/CjL5msJ/tPTPcrxtCQ= sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" - resolved "https://registry.npm.alibaba-inc.com/sha.js/download/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + resolved "https://registry.npm.alibaba-inc.com/sha.js/download/sha.js-2.4.11.tgz" integrity sha1-N6XPC4HsvGlD3hCbopYNGyZYSuc= dependencies: inherits "^2.0.1" @@ -10206,53 +12413,53 @@ sha.js@^2.4.0, sha.js@^2.4.8: shallow-equal@^1.1.0, shallow-equal@^1.2.1: version "1.2.1" - resolved "https://registry.npm.alibaba-inc.com/shallow-equal/download/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da" + resolved "https://registry.npm.alibaba-inc.com/shallow-equal/download/shallow-equal-1.2.1.tgz" integrity sha1-TBar+lYEOqINBQMk76aJQLDaedo= shallowequal@^1.0.1, shallowequal@^1.1.0: version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/shallowequal/download/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" + resolved "https://registry.npm.alibaba-inc.com/shallowequal/download/shallowequal-1.1.0.tgz" integrity sha1-GI1SHelbkIdAT9TctosT3wrk5/g= shebang-command@^1.2.0: version "1.2.0" - resolved "https://registry.npm.alibaba-inc.com/shebang-command/download/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + resolved "https://registry.npm.alibaba-inc.com/shebang-command/download/shebang-command-1.2.0.tgz" integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= dependencies: shebang-regex "^1.0.0" shebang-command@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/shebang-command/download/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + resolved "https://registry.npm.alibaba-inc.com/shebang-command/download/shebang-command-2.0.0.tgz" integrity sha1-zNCvT4g1+9wmW4JGGq8MNmY/NOo= dependencies: shebang-regex "^3.0.0" shebang-regex@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/shebang-regex/download/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + resolved "https://registry.npm.alibaba-inc.com/shebang-regex/download/shebang-regex-1.0.0.tgz" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/shebang-regex/download/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + resolved "https://registry.npm.alibaba-inc.com/shebang-regex/download/shebang-regex-3.0.0.tgz" integrity sha1-rhbxZE2HPsrYQ7AwexQzYtTEIXI= shellwords@^0.1.1: version "0.1.1" - resolved "https://registry.npm.alibaba-inc.com/shellwords/download/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" + resolved "https://registry.npm.alibaba-inc.com/shellwords/download/shellwords-0.1.1.tgz" integrity sha1-1rkYHBpI05cyTISHHvvPxz/AZUs= should-equal@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/should-equal/download/should-equal-2.0.0.tgz#6072cf83047360867e68e98b09d71143d04ee0c3" + resolved "https://registry.npm.alibaba-inc.com/should-equal/download/should-equal-2.0.0.tgz" integrity sha1-YHLPgwRzYIZ+aOmLCdcRQ9BO4MM= dependencies: should-type "^1.4.0" should-format@^3.0.3: version "3.0.3" - resolved "https://registry.npm.alibaba-inc.com/should-format/download/should-format-3.0.3.tgz#9bfc8f74fa39205c53d38c34d717303e277124f1" + resolved "https://registry.npm.alibaba-inc.com/should-format/download/should-format-3.0.3.tgz" integrity sha1-m/yPdPo5IFxT04w01xcwPidxJPE= dependencies: should-type "^1.3.0" @@ -10260,7 +12467,7 @@ should-format@^3.0.3: should-type-adaptors@^1.0.1: version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/should-type-adaptors/download/should-type-adaptors-1.1.0.tgz#401e7f33b5533033944d5cd8bf2b65027792e27a" + resolved "https://registry.npm.alibaba-inc.com/should-type-adaptors/download/should-type-adaptors-1.1.0.tgz" integrity sha1-QB5/M7VTMDOUTVzYvytlAneS4no= dependencies: should-type "^1.3.0" @@ -10268,17 +12475,17 @@ should-type-adaptors@^1.0.1: should-type@^1.3.0, should-type@^1.4.0: version "1.4.0" - resolved "https://registry.npm.alibaba-inc.com/should-type/download/should-type-1.4.0.tgz#0756d8ce846dfd09843a6947719dfa0d4cff5cf3" + resolved "https://registry.npm.alibaba-inc.com/should-type/download/should-type-1.4.0.tgz" integrity sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM= should-util@^1.0.0: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/should-util/download/should-util-1.0.1.tgz#fb0d71338f532a3a149213639e2d32cbea8bcb28" + resolved "https://registry.npm.alibaba-inc.com/should-util/download/should-util-1.0.1.tgz" integrity sha1-+w1xM49TKjoUkhNjni0yy+qLyyg= should@^13.2.1: version "13.2.3" - resolved "https://registry.npm.alibaba-inc.com/should/download/should-13.2.3.tgz#96d8e5acf3e97b49d89b51feaa5ae8d07ef58f10" + resolved "https://registry.npm.alibaba-inc.com/should/download/should-13.2.3.tgz" integrity sha1-ltjlrPPpe0nYm1H+qlro0H71jxA= dependencies: should-equal "^2.0.0" @@ -10289,7 +12496,7 @@ should@^13.2.1: side-channel@^1.0.4: version "1.0.4" - resolved "https://registry.npm.alibaba-inc.com/side-channel/download/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + resolved "https://registry.npm.alibaba-inc.com/side-channel/download/side-channel-1.0.4.tgz" integrity sha1-785cj9wQTudRslxY1CkAEfpeos8= dependencies: call-bind "^1.0.0" @@ -10298,22 +12505,34 @@ side-channel@^1.0.4: signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.7" - resolved "https://registry.npm.alibaba-inc.com/signal-exit/download/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + resolved "https://registry.npm.alibaba-inc.com/signal-exit/download/signal-exit-3.0.7.tgz" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz" + integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== + dependencies: + is-arrayish "^0.3.1" + sisteransi@^1.0.5: version "1.0.5" - resolved "https://registry.npm.alibaba-inc.com/sisteransi/download/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + resolved "https://registry.npm.alibaba-inc.com/sisteransi/download/sisteransi-1.0.5.tgz" integrity sha1-E01oEpd1ZDfMBcoBNw06elcQde0= +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + slash@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/slash/download/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + resolved "https://registry.npm.alibaba-inc.com/slash/download/slash-3.0.0.tgz" integrity sha1-ZTm+hwwWWtvVJAIg2+Nh8bxNRjQ= slice-ansi@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/slice-ansi/download/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" + resolved "https://registry.npm.alibaba-inc.com/slice-ansi/download/slice-ansi-3.0.0.tgz" integrity sha1-Md3BCTCht+C2ewjJbC9Jt3p4l4c= dependencies: ansi-styles "^4.0.0" @@ -10322,7 +12541,7 @@ slice-ansi@^3.0.0: slice-ansi@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/slice-ansi/download/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + resolved "https://registry.npm.alibaba-inc.com/slice-ansi/download/slice-ansi-4.0.0.tgz" integrity sha1-UA6N0P1VsFgVCGJVsxla3ypF/ms= dependencies: ansi-styles "^4.0.0" @@ -10331,7 +12550,7 @@ slice-ansi@^4.0.0: snapdragon-node@^2.0.1: version "2.1.1" - resolved "https://registry.npm.alibaba-inc.com/snapdragon-node/download/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + resolved "https://registry.npm.alibaba-inc.com/snapdragon-node/download/snapdragon-node-2.1.1.tgz" integrity sha1-bBdfhv8UvbByRWPo88GwIaKGhTs= dependencies: define-property "^1.0.0" @@ -10340,14 +12559,14 @@ snapdragon-node@^2.0.1: snapdragon-util@^3.0.1: version "3.0.1" - resolved "https://registry.npm.alibaba-inc.com/snapdragon-util/download/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + resolved "https://registry.npm.alibaba-inc.com/snapdragon-util/download/snapdragon-util-3.0.1.tgz" integrity sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI= dependencies: kind-of "^3.2.0" snapdragon@^0.8.1: version "0.8.2" - resolved "https://registry.npm.alibaba-inc.com/snapdragon/download/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + resolved "https://registry.npm.alibaba-inc.com/snapdragon/download/snapdragon-0.8.2.tgz" integrity sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0= dependencies: base "^0.11.1" @@ -10361,19 +12580,19 @@ snapdragon@^0.8.1: sort-keys@^1.0.0: version "1.1.2" - resolved "https://registry.npm.alibaba-inc.com/sort-keys/download/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" + resolved "https://registry.npm.alibaba-inc.com/sort-keys/download/sort-keys-1.1.2.tgz" integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= dependencies: is-plain-obj "^1.0.0" sort-object-keys@^1.1.3: version "1.1.3" - resolved "https://registry.npm.alibaba-inc.com/sort-object-keys/download/sort-object-keys-1.1.3.tgz#bff833fe85cab147b34742e45863453c1e190b45" + resolved "https://registry.npm.alibaba-inc.com/sort-object-keys/download/sort-object-keys-1.1.3.tgz" integrity sha1-v/gz/oXKsUezR0LkWGNFPB4ZC0U= sort-package-json@1.57.0: version "1.57.0" - resolved "https://registry.npm.alibaba-inc.com/sort-package-json/download/sort-package-json-1.57.0.tgz#e95fb44af8ede0bb6147e3f39258102d4bb23fc4" + resolved "https://registry.npm.alibaba-inc.com/sort-package-json/download/sort-package-json-1.57.0.tgz" integrity sha512-FYsjYn2dHTRb41wqnv+uEqCUvBpK3jZcTp9rbz2qDTmel7Pmdtf+i2rLaaPMRZeSVM60V3Se31GyWFpmKs4Q5Q== dependencies: detect-indent "^6.0.0" @@ -10385,12 +12604,12 @@ sort-package-json@1.57.0: source-map-js@^1.0.2: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/source-map-js/download/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + resolved "https://registry.npm.alibaba-inc.com/source-map-js/download/source-map-js-1.0.2.tgz" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== source-map-resolve@^0.5.0: version "0.5.3" - resolved "https://registry.npm.alibaba-inc.com/source-map-resolve/download/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + resolved "https://registry.npm.alibaba-inc.com/source-map-resolve/download/source-map-resolve-0.5.3.tgz" integrity sha1-GQhmvs51U+H48mei7oLGBrVQmho= dependencies: atob "^2.1.2" @@ -10401,7 +12620,7 @@ source-map-resolve@^0.5.0: source-map-support@^0.5.6, source-map-support@~0.5.20: version "0.5.21" - resolved "https://registry.npm.alibaba-inc.com/source-map-support/download/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + resolved "https://registry.npm.alibaba-inc.com/source-map-support/download/source-map-support-0.5.21.tgz" integrity sha1-BP58f54e0tZiIzwoyys1ufY/bk8= dependencies: buffer-from "^1.0.0" @@ -10409,27 +12628,27 @@ source-map-support@^0.5.6, source-map-support@~0.5.20: source-map-url@^0.4.0: version "0.4.1" - resolved "https://registry.npm.alibaba-inc.com/source-map-url/download/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + resolved "https://registry.npm.alibaba-inc.com/source-map-url/download/source-map-url-0.4.1.tgz" integrity sha1-CvZmBadFpaL5HPG7+KevvCg97FY= source-map@^0.5.6: version "0.5.7" - resolved "https://registry.npm.alibaba-inc.com/source-map/download/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + resolved "https://registry.npm.alibaba-inc.com/source-map/download/source-map-0.5.7.tgz" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" - resolved "https://registry.npm.alibaba-inc.com/source-map/download/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + resolved "https://registry.npm.alibaba-inc.com/source-map/download/source-map-0.6.1.tgz" integrity sha1-dHIq8y6WFOnCh6jQu95IteLxomM= source-map@^0.7.3: version "0.7.4" - resolved "https://registry.npm.alibaba-inc.com/source-map/download/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + resolved "https://registry.npm.alibaba-inc.com/source-map/download/source-map-0.7.4.tgz" integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== spdx-correct@^3.0.0: version "3.1.1" - resolved "https://registry.npm.alibaba-inc.com/spdx-correct/download/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + resolved "https://registry.npm.alibaba-inc.com/spdx-correct/download/spdx-correct-3.1.1.tgz" integrity sha1-3s6BrJweZxPl99G28X1Gj6U9iak= dependencies: spdx-expression-parse "^3.0.0" @@ -10437,12 +12656,12 @@ spdx-correct@^3.0.0: spdx-exceptions@^2.1.0: version "2.3.0" - resolved "https://registry.npm.alibaba-inc.com/spdx-exceptions/download/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + resolved "https://registry.npm.alibaba-inc.com/spdx-exceptions/download/spdx-exceptions-2.3.0.tgz" integrity sha1-PyjOGnegA3JoPq3kpDMYNSeiFj0= spdx-expression-parse@^3.0.0: version "3.0.1" - resolved "https://registry.npm.alibaba-inc.com/spdx-expression-parse/download/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + resolved "https://registry.npm.alibaba-inc.com/spdx-expression-parse/download/spdx-expression-parse-3.0.1.tgz" integrity sha1-z3D1BILu/cmOPOCmgz5KU87rpnk= dependencies: spdx-exceptions "^2.1.0" @@ -10450,46 +12669,56 @@ spdx-expression-parse@^3.0.0: spdx-license-ids@^3.0.0: version "3.0.12" - resolved "https://registry.npm.alibaba-inc.com/spdx-license-ids/download/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779" + resolved "https://registry.npm.alibaba-inc.com/spdx-license-ids/download/spdx-license-ids-3.0.12.tgz" integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA== specificity@^0.4.1: version "0.4.1" - resolved "https://registry.npm.alibaba-inc.com/specificity/download/specificity-0.4.1.tgz#aab5e645012db08ba182e151165738d00887b019" + resolved "https://registry.npm.alibaba-inc.com/specificity/download/specificity-0.4.1.tgz" integrity sha1-qrXmRQEtsIuhguFRFlc40AiHsBk= split-on-first@^1.0.0: version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/split-on-first/download/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" + resolved "https://registry.npm.alibaba-inc.com/split-on-first/download/split-on-first-1.1.0.tgz" integrity sha1-9hCv7uOxK84dDDBCXnY5i3gkml8= +split-on-first@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/split-on-first/-/split-on-first-3.0.0.tgz" + integrity sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA== + split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" - resolved "https://registry.npm.alibaba-inc.com/split-string/download/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + resolved "https://registry.npm.alibaba-inc.com/split-string/download/split-string-3.1.0.tgz" integrity sha1-fLCd2jqGWFcFxks5pkZgOGguj+I= dependencies: extend-shallow "^3.0.0" sprintf-js@~1.0.2: version "1.0.3" - resolved "https://registry.npm.alibaba-inc.com/sprintf-js/download/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + resolved "https://registry.npm.alibaba-inc.com/sprintf-js/download/sprintf-js-1.0.3.tgz" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + stack-utils@^2.0.2: version "2.0.6" - resolved "https://registry.npm.alibaba-inc.com/stack-utils/download/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + resolved "https://registry.npm.alibaba-inc.com/stack-utils/download/stack-utils-2.0.6.tgz" integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== dependencies: escape-string-regexp "^2.0.0" stackframe@^1.3.4: version "1.3.4" - resolved "https://registry.npm.alibaba-inc.com/stackframe/download/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310" + resolved "https://registry.npm.alibaba-inc.com/stackframe/download/stackframe-1.3.4.tgz" integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== static-extend@^0.1.1: version "0.1.2" - resolved "https://registry.npm.alibaba-inc.com/static-extend/download/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + resolved "https://registry.npm.alibaba-inc.com/static-extend/download/static-extend-0.1.2.tgz" integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= dependencies: define-property "^0.2.5" @@ -10497,12 +12726,12 @@ static-extend@^0.1.1: statuses@2.0.1: version "2.0.1" - resolved "https://registry.npm.alibaba-inc.com/statuses/download/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + resolved "https://registry.npm.alibaba-inc.com/statuses/download/statuses-2.0.1.tgz" integrity sha1-VcsADM8dSHKL0jxoWgY5mM8aG2M= stream-browserify@^2.0.1: version "2.0.2" - resolved "https://registry.npm.alibaba-inc.com/stream-browserify/download/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" + resolved "https://registry.npm.alibaba-inc.com/stream-browserify/download/stream-browserify-2.0.2.tgz" integrity sha1-h1IdOKRKp+6RzhzSpH3wy0ndZgs= dependencies: inherits "~2.0.1" @@ -10510,7 +12739,7 @@ stream-browserify@^2.0.1: stream-http@^2.7.2: version "2.8.3" - resolved "https://registry.npm.alibaba-inc.com/stream-http/download/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + resolved "https://registry.npm.alibaba-inc.com/stream-http/download/stream-http-2.8.3.tgz" integrity sha1-stJCRpKIpaJ+xP6JM6z2I95lFPw= dependencies: builtin-status-codes "^3.0.0" @@ -10521,27 +12750,27 @@ stream-http@^2.7.2: strict-uri-encode@^1.0.0: version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/strict-uri-encode/download/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + resolved "https://registry.npm.alibaba-inc.com/strict-uri-encode/download/strict-uri-encode-1.1.0.tgz" integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= strict-uri-encode@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/strict-uri-encode/download/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" + resolved "https://registry.npm.alibaba-inc.com/strict-uri-encode/download/strict-uri-encode-2.0.0.tgz" integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY= string-argv@0.3.1: version "0.3.1" - resolved "https://registry.npm.alibaba-inc.com/string-argv/download/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" + resolved "https://registry.npm.alibaba-inc.com/string-argv/download/string-argv-0.3.1.tgz" integrity sha1-leL77AQnrhkYSTX4FtdKqkxcGdo= string-convert@^0.2.0: version "0.2.1" - resolved "https://registry.npm.alibaba-inc.com/string-convert/download/string-convert-0.2.1.tgz#6982cc3049fbb4cd85f8b24568b9d9bf39eeff97" + resolved "https://registry.npm.alibaba-inc.com/string-convert/download/string-convert-0.2.1.tgz" integrity sha1-aYLMMEn7tM2F+LJFaLnZvznu/5c= string-length@^4.0.1: version "4.0.2" - resolved "https://registry.npm.alibaba-inc.com/string-length/download/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + resolved "https://registry.npm.alibaba-inc.com/string-length/download/string-length-4.0.2.tgz" integrity sha1-qKjce9XBqCubPIuH4SX2aHG25Xo= dependencies: char-regex "^1.0.2" @@ -10549,7 +12778,7 @@ string-length@^4.0.1: string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" - resolved "https://registry.npm.alibaba-inc.com/string-width/download/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + resolved "https://registry.npm.alibaba-inc.com/string-width/download/string-width-4.2.3.tgz" integrity sha1-JpxxF9J7Ba0uU2gwqOyJXvnG0BA= dependencies: emoji-regex "^8.0.0" @@ -10558,7 +12787,7 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2 string.prototype.matchall@^4.0.8: version "4.0.8" - resolved "https://registry.npm.alibaba-inc.com/string.prototype.matchall/download/string.prototype.matchall-4.0.8.tgz#3bf85722021816dcd1bf38bb714915887ca79fd3" + resolved "https://registry.npm.alibaba-inc.com/string.prototype.matchall/download/string.prototype.matchall-4.0.8.tgz" integrity sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg== dependencies: call-bind "^1.0.2" @@ -10570,41 +12799,68 @@ string.prototype.matchall@^4.0.8: regexp.prototype.flags "^1.4.3" side-channel "^1.0.4" +string.prototype.trim@^1.2.7: + version "1.2.8" + resolved "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz" + integrity sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + string.prototype.trimend@^1.0.5: version "1.0.6" - resolved "https://registry.npm.alibaba-inc.com/string.prototype.trimend/download/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + resolved "https://registry.npm.alibaba-inc.com/string.prototype.trimend/download/string.prototype.trimend-1.0.6.tgz" integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== dependencies: call-bind "^1.0.2" define-properties "^1.1.4" es-abstract "^1.20.4" +string.prototype.trimend@^1.0.6: + version "1.0.7" + resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz" + integrity sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + string.prototype.trimstart@^1.0.5: version "1.0.6" - resolved "https://registry.npm.alibaba-inc.com/string.prototype.trimstart/download/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + resolved "https://registry.npm.alibaba-inc.com/string.prototype.trimstart/download/string.prototype.trimstart-1.0.6.tgz" integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== dependencies: call-bind "^1.0.2" define-properties "^1.1.4" es-abstract "^1.20.4" +string.prototype.trimstart@^1.0.6: + version "1.0.7" + resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz" + integrity sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" - resolved "https://registry.npm.alibaba-inc.com/string_decoder/download/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + resolved "https://registry.npm.alibaba-inc.com/string_decoder/download/string_decoder-1.3.0.tgz" integrity sha1-QvEUWUpGzxqOMLCoT1bHjD7awh4= dependencies: safe-buffer "~5.2.0" string_decoder@~1.1.1: version "1.1.1" - resolved "https://registry.npm.alibaba-inc.com/string_decoder/download/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + resolved "https://registry.npm.alibaba-inc.com/string_decoder/download/string_decoder-1.1.1.tgz" integrity sha1-nPFhG6YmhdcDCunkujQUnDrwP8g= dependencies: safe-buffer "~5.1.0" stringify-object@^3.3.0: version "3.3.0" - resolved "https://registry.npm.alibaba-inc.com/stringify-object/download/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" + resolved "https://registry.npm.alibaba-inc.com/stringify-object/download/stringify-object-3.3.0.tgz" integrity sha1-cDBlrvyhkwDTzoivT1s5VtdVZik= dependencies: get-own-enumerable-property-symbols "^3.0.0" @@ -10613,78 +12869,78 @@ stringify-object@^3.3.0: strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" - resolved "https://registry.npm.alibaba-inc.com/strip-ansi/download/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + resolved "https://registry.npm.alibaba-inc.com/strip-ansi/download/strip-ansi-6.0.1.tgz" integrity sha1-nibGPTD1NEPpSJSVshBdN7Z6hdk= dependencies: ansi-regex "^5.0.1" strip-bom@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/strip-bom/download/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + resolved "https://registry.npm.alibaba-inc.com/strip-bom/download/strip-bom-4.0.0.tgz" integrity sha1-nDUFwdtFvO3KPZz3oW9cWqOQGHg= strip-eof@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/strip-eof/download/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + resolved "https://registry.npm.alibaba-inc.com/strip-eof/download/strip-eof-1.0.0.tgz" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= strip-final-newline@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/strip-final-newline/download/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + resolved "https://registry.npm.alibaba-inc.com/strip-final-newline/download/strip-final-newline-2.0.0.tgz" integrity sha1-ibhS+y/L6Tb29LMYevsKEsGrWK0= strip-indent@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/strip-indent/download/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" + resolved "https://registry.npm.alibaba-inc.com/strip-indent/download/strip-indent-2.0.0.tgz" integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= strip-indent@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/strip-indent/download/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + resolved "https://registry.npm.alibaba-inc.com/strip-indent/download/strip-indent-3.0.0.tgz" integrity sha1-wy4c7pQLazQyx3G8LFS8znPNMAE= dependencies: min-indent "^1.0.0" strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" - resolved "https://registry.npm.alibaba-inc.com/strip-json-comments/download/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + resolved "https://registry.npm.alibaba-inc.com/strip-json-comments/download/strip-json-comments-3.1.1.tgz" integrity sha1-MfEoGzgyYwQ0gxwxDAHMzajL4AY= style-search@^0.1.0: version "0.1.0" - resolved "https://registry.npm.alibaba-inc.com/style-search/download/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902" + resolved "https://registry.npm.alibaba-inc.com/style-search/download/style-search-0.1.0.tgz" integrity sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI= stylelint-config-css-modules@^2.2.0: version "2.3.0" - resolved "https://registry.npm.alibaba-inc.com/stylelint-config-css-modules/download/stylelint-config-css-modules-2.3.0.tgz#bf79aaae09ca9fdac37fdd518d1a40a779aa0767" + resolved "https://registry.npm.alibaba-inc.com/stylelint-config-css-modules/download/stylelint-config-css-modules-2.3.0.tgz" integrity sha1-v3mqrgnKn9rDf91RjRpAp3mqB2c= stylelint-config-prettier@^8.0.1: version "8.0.2" - resolved "https://registry.npm.alibaba-inc.com/stylelint-config-prettier/download/stylelint-config-prettier-8.0.2.tgz#da9de33da4c56893cbe7e26df239a7374045e14e" + resolved "https://registry.npm.alibaba-inc.com/stylelint-config-prettier/download/stylelint-config-prettier-8.0.2.tgz" integrity sha1-2p3jPaTFaJPL5+Jt8jmnN0BF4U4= stylelint-config-recommended@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/stylelint-config-recommended/download/stylelint-config-recommended-3.0.0.tgz#e0e547434016c5539fe2650afd58049a2fd1d657" + resolved "https://registry.npm.alibaba-inc.com/stylelint-config-recommended/download/stylelint-config-recommended-3.0.0.tgz" integrity sha1-4OVHQ0AWxVOf4mUK/VgEmi/R1lc= stylelint-config-standard@^20.0.0: version "20.0.0" - resolved "https://registry.npm.alibaba-inc.com/stylelint-config-standard/download/stylelint-config-standard-20.0.0.tgz#06135090c9e064befee3d594289f50e295b5e20d" + resolved "https://registry.npm.alibaba-inc.com/stylelint-config-standard/download/stylelint-config-standard-20.0.0.tgz" integrity sha1-BhNQkMngZL7+49WUKJ9Q4pW14g0= dependencies: stylelint-config-recommended "^3.0.0" stylelint-declaration-block-no-ignored-properties@^2.1.0: version "2.6.0" - resolved "https://registry.npm.alibaba-inc.com/stylelint-declaration-block-no-ignored-properties/download/stylelint-declaration-block-no-ignored-properties-2.6.0.tgz#237028415b5bd543341f7d3c57c5903259a9e09c" + resolved "https://registry.npm.alibaba-inc.com/stylelint-declaration-block-no-ignored-properties/download/stylelint-declaration-block-no-ignored-properties-2.6.0.tgz" integrity sha512-S9EC/tVJL19ppMRC4A4ecxtkENHZ7WNrEAukJVDtFt+iZgNP3SmokOLlYUhe6qZuB2XUvETqUx6r2p3Xfo7Rxw== stylelint@^13.0.0: version "13.13.1" - resolved "https://registry.npm.alibaba-inc.com/stylelint/download/stylelint-13.13.1.tgz#fca9c9f5de7990ab26a00f167b8978f083a18f3c" + resolved "https://registry.npm.alibaba-inc.com/stylelint/download/stylelint-13.13.1.tgz" integrity sha1-/KnJ9d55kKsmoA8We4l48IOhjzw= dependencies: "@stylelint/postcss-css-in-js" "^0.37.2" @@ -10738,40 +12994,40 @@ stylelint@^13.0.0: stylis@^4.0.13: version "4.1.3" - resolved "https://registry.npm.alibaba-inc.com/stylis/download/stylis-4.1.3.tgz#fd2fbe79f5fed17c55269e16ed8da14c84d069f7" + resolved "https://registry.npm.alibaba-inc.com/stylis/download/stylis-4.1.3.tgz" integrity sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA== sugarss@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/sugarss/download/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d" + resolved "https://registry.npm.alibaba-inc.com/sugarss/download/sugarss-2.0.0.tgz" integrity sha1-3dduASSyl9QL88yjHIsi7LQ7xh0= dependencies: postcss "^7.0.2" supports-color@^5.3.0: version "5.5.0" - resolved "https://registry.npm.alibaba-inc.com/supports-color/download/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + resolved "https://registry.npm.alibaba-inc.com/supports-color/download/supports-color-5.5.0.tgz" integrity sha1-4uaaRKyHcveKHsCzW2id9lMO/I8= dependencies: has-flag "^3.0.0" supports-color@^6.1.0: version "6.1.0" - resolved "https://registry.npm.alibaba-inc.com/supports-color/download/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + resolved "https://registry.npm.alibaba-inc.com/supports-color/download/supports-color-6.1.0.tgz" integrity sha1-B2Srxpxj1ayELdSGfo0CXogN+PM= dependencies: has-flag "^3.0.0" supports-color@^7.0.0, supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.npm.alibaba-inc.com/supports-color/download/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + resolved "https://registry.npm.alibaba-inc.com/supports-color/download/supports-color-7.2.0.tgz" integrity sha1-G33NyzK4E4gBs+R4umpRyqiWSNo= dependencies: has-flag "^4.0.0" supports-hyperlinks@^2.0.0: version "2.3.0" - resolved "https://registry.npm.alibaba-inc.com/supports-hyperlinks/download/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" + resolved "https://registry.npm.alibaba-inc.com/supports-hyperlinks/download/supports-hyperlinks-2.3.0.tgz" integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA== dependencies: has-flag "^4.0.0" @@ -10779,22 +13035,41 @@ supports-hyperlinks@^2.0.0: supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/supports-preserve-symlinks-flag/download/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + resolved "https://registry.npm.alibaba-inc.com/supports-preserve-symlinks-flag/download/supports-preserve-symlinks-flag-1.0.0.tgz" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== svg-tags@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/svg-tags/download/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" + resolved "https://registry.npm.alibaba-inc.com/svg-tags/download/svg-tags-1.0.0.tgz" integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= +svgo@^1.3.2: + version "1.3.2" + resolved "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz" + integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== + dependencies: + chalk "^2.4.1" + coa "^2.0.2" + css-select "^2.0.0" + css-select-base-adapter "^0.1.1" + css-tree "1.0.0-alpha.37" + csso "^4.0.2" + js-yaml "^3.13.1" + mkdirp "~0.5.1" + object.values "^1.1.0" + sax "~1.2.4" + stable "^0.1.8" + unquote "~1.1.1" + util.promisify "~1.0.0" + swagger-ui-dist@^4.12.0: version "4.15.5" - resolved "https://registry.npm.alibaba-inc.com/swagger-ui-dist/download/swagger-ui-dist-4.15.5.tgz#cda226a79db2a9192579cc1f37ec839398a62638" + resolved "https://registry.npm.alibaba-inc.com/swagger-ui-dist/download/swagger-ui-dist-4.15.5.tgz" integrity sha512-V3eIa28lwB6gg7/wfNvAbjwJYmDXy1Jo1POjyTzlB6wPcHiGlRxq39TSjYGVjQrUSAzpv+a7nzp7mDxgNy57xA== swagger2openapi@^7.0.4: version "7.0.8" - resolved "https://registry.npm.alibaba-inc.com/swagger2openapi/download/swagger2openapi-7.0.8.tgz#12c88d5de776cb1cbba758994930f40ad0afac59" + resolved "https://registry.npm.alibaba-inc.com/swagger2openapi/download/swagger2openapi-7.0.8.tgz" integrity sha1-EsiNXed2yxy7p1iZSTD0CtCvrFk= dependencies: call-me-maybe "^1.0.1" @@ -10811,17 +13086,25 @@ swagger2openapi@^7.0.4: swr@^1.2.0: version "1.3.0" - resolved "https://registry.npm.alibaba-inc.com/swr/download/swr-1.3.0.tgz#c6531866a35b4db37b38b72c45a63171faf9f4e8" + resolved "https://registry.npm.alibaba-inc.com/swr/download/swr-1.3.0.tgz" integrity sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw== +swr@^2.0.0: + version "2.2.2" + resolved "https://registry.npmjs.org/swr/-/swr-2.2.2.tgz" + integrity sha512-CbR41AoMD4TQBQw9ic3GTXspgfM9Y8Mdhb5Ob4uIKXhWqnRLItwA5fpGvB7SmSw3+zEjb0PdhiEumtUvYoQ+bQ== + dependencies: + client-only "^0.0.1" + use-sync-external-store "^1.2.0" + symbol-tree@^3.2.4: version "3.2.4" - resolved "https://registry.npm.alibaba-inc.com/symbol-tree/download/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + resolved "https://registry.npm.alibaba-inc.com/symbol-tree/download/symbol-tree-3.2.4.tgz" integrity sha1-QwY30ki6d+B4iDlR+5qg7tfGP6I= table@^6.0.9, table@^6.6.0: version "6.8.1" - resolved "https://registry.npm.alibaba-inc.com/table/download/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" + resolved "https://registry.npm.alibaba-inc.com/table/download/table-6.8.1.tgz" integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== dependencies: ajv "^8.0.1" @@ -10832,7 +13115,7 @@ table@^6.0.9, table@^6.6.0: terminal-link@^2.0.0: version "2.1.1" - resolved "https://registry.npm.alibaba-inc.com/terminal-link/download/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" + resolved "https://registry.npm.alibaba-inc.com/terminal-link/download/terminal-link-2.1.1.tgz" integrity sha1-FKZKJ6s8Dfkz6lRvulXy0HjtyZQ= dependencies: ansi-escapes "^4.2.1" @@ -10840,7 +13123,7 @@ terminal-link@^2.0.0: terser@5.14.2: version "5.14.2" - resolved "https://registry.npm.alibaba-inc.com/terser/download/terser-5.14.2.tgz#9ac9f22b06994d736174f4091aa368db896f1c10" + resolved "https://registry.npm.alibaba-inc.com/terser/download/terser-5.14.2.tgz" integrity sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA== dependencies: "@jridgewell/source-map" "^0.3.2" @@ -10850,7 +13133,7 @@ terser@5.14.2: test-exclude@^6.0.0: version "6.0.0" - resolved "https://registry.npm.alibaba-inc.com/test-exclude/download/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + resolved "https://registry.npm.alibaba-inc.com/test-exclude/download/test-exclude-6.0.0.tgz" integrity sha1-BKhphmHYBepvopO2y55jrARO8V4= dependencies: "@istanbuljs/schema" "^0.1.2" @@ -10859,29 +13142,34 @@ test-exclude@^6.0.0: text-table@^0.2.0: version "0.2.0" - resolved "https://registry.npm.alibaba-inc.com/text-table/download/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + resolved "https://registry.npm.alibaba-inc.com/text-table/download/text-table-0.2.0.tgz" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= throat@^5.0.0: version "5.0.0" - resolved "https://registry.npm.alibaba-inc.com/throat/download/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" + resolved "https://registry.npm.alibaba-inc.com/throat/download/throat-5.0.0.tgz" integrity sha1-xRmSNYA6rRh1SmZ9ZZtecs4Wdks= +throttle-debounce@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.0.tgz" + integrity sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg== + through@^2.3.8: version "2.3.8" - resolved "https://registry.npm.alibaba-inc.com/through/download/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + resolved "https://registry.npm.alibaba-inc.com/through/download/through-2.3.8.tgz" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= timers-browserify@^2.0.4: version "2.0.12" - resolved "https://registry.npm.alibaba-inc.com/timers-browserify/download/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" + resolved "https://registry.npm.alibaba-inc.com/timers-browserify/download/timers-browserify-2.0.12.tgz" integrity sha1-RKRcEfv0B/NPl7zNFXfGUjYbAO4= dependencies: setimmediate "^1.0.4" timers-ext@^0.1.7: version "0.1.7" - resolved "https://registry.npm.alibaba-inc.com/timers-ext/download/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" + resolved "https://registry.npm.alibaba-inc.com/timers-ext/download/timers-ext-0.1.7.tgz" integrity sha1-b1ethXjgej+5+R2Th9ZWR1VeJcY= dependencies: es5-ext "~0.10.46" @@ -10889,49 +13177,49 @@ timers-ext@^0.1.7: tiny-invariant@^1.0.2: version "1.3.1" - resolved "https://registry.npm.alibaba-inc.com/tiny-invariant/download/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" + resolved "https://registry.npm.alibaba-inc.com/tiny-invariant/download/tiny-invariant-1.3.1.tgz" integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== tiny-pinyin@^1.3.2: version "1.3.2" - resolved "https://registry.npm.alibaba-inc.com/tiny-pinyin/download/tiny-pinyin-1.3.2.tgz#ce31f0f3afc2a80ee9df708fc7f4e914854d534a" + resolved "https://registry.npm.alibaba-inc.com/tiny-pinyin/download/tiny-pinyin-1.3.2.tgz" integrity sha1-zjHw86/CqA7p33CPx/TpFIVNU0o= tiny-warning@^1.0.0, tiny-warning@^1.0.3: version "1.0.3" - resolved "https://registry.npm.alibaba-inc.com/tiny-warning/download/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + resolved "https://registry.npm.alibaba-inc.com/tiny-warning/download/tiny-warning-1.0.3.tgz" integrity sha1-lKMNtFPfTGQ9D9VmBg1gqHXYR1Q= -tinycolor2@^1.4.2: +tinycolor2@^1.4.1, tinycolor2@^1.4.2: version "1.4.2" - resolved "https://registry.npm.alibaba-inc.com/tinycolor2/download/tinycolor2-1.4.2.tgz#3f6a4d1071ad07676d7fa472e1fac40a719d8803" + resolved "https://registry.npm.alibaba-inc.com/tinycolor2/download/tinycolor2-1.4.2.tgz" integrity sha1-P2pNEHGtB2dtf6Ry4frECnGdiAM= tmpl@1.0.5: version "1.0.5" - resolved "https://registry.npm.alibaba-inc.com/tmpl/download/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + resolved "https://registry.npm.alibaba-inc.com/tmpl/download/tmpl-1.0.5.tgz" integrity sha1-hoPguQK7nCDE9ybjwLafNlGMB8w= to-arraybuffer@^1.0.0: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/to-arraybuffer/download/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + resolved "https://registry.npm.alibaba-inc.com/to-arraybuffer/download/to-arraybuffer-1.0.1.tgz" integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= to-fast-properties@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/to-fast-properties/download/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + resolved "https://registry.npm.alibaba-inc.com/to-fast-properties/download/to-fast-properties-2.0.0.tgz" integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= to-object-path@^0.3.0: version "0.3.0" - resolved "https://registry.npm.alibaba-inc.com/to-object-path/download/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + resolved "https://registry.npm.alibaba-inc.com/to-object-path/download/to-object-path-0.3.0.tgz" integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= dependencies: kind-of "^3.0.2" to-regex-range@^2.1.0: version "2.1.1" - resolved "https://registry.npm.alibaba-inc.com/to-regex-range/download/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + resolved "https://registry.npm.alibaba-inc.com/to-regex-range/download/to-regex-range-2.1.1.tgz" integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= dependencies: is-number "^3.0.0" @@ -10939,14 +13227,14 @@ to-regex-range@^2.1.0: to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.npm.alibaba-inc.com/to-regex-range/download/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + resolved "https://registry.npm.alibaba-inc.com/to-regex-range/download/to-regex-range-5.0.1.tgz" integrity sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ= dependencies: is-number "^7.0.0" to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" - resolved "https://registry.npm.alibaba-inc.com/to-regex/download/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + resolved "https://registry.npm.alibaba-inc.com/to-regex/download/to-regex-3.0.2.tgz" integrity sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4= dependencies: define-property "^2.0.2" @@ -10956,17 +13244,17 @@ to-regex@^3.0.1, to-regex@^3.0.2: toggle-selection@^1.0.6: version "1.0.6" - resolved "https://registry.npm.alibaba-inc.com/toggle-selection/download/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" + resolved "https://registry.npm.alibaba-inc.com/toggle-selection/download/toggle-selection-1.0.6.tgz" integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI= toidentifier@1.0.1: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/toidentifier/download/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + resolved "https://registry.npm.alibaba-inc.com/toidentifier/download/toidentifier-1.0.1.tgz" integrity sha1-O+NDIaiKgg7RvYDfqjPkefu43TU= tough-cookie@^4.0.0: version "4.1.2" - resolved "https://registry.npm.alibaba-inc.com/tough-cookie/download/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874" + resolved "https://registry.npm.alibaba-inc.com/tough-cookie/download/tough-cookie-4.1.2.tgz" integrity sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ== dependencies: psl "^1.1.33" @@ -10976,132 +13264,171 @@ tough-cookie@^4.0.0: tr46@^2.1.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/tr46/download/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" + resolved "https://registry.npm.alibaba-inc.com/tr46/download/tr46-2.1.0.tgz" integrity sha1-+oeqgcpdWUHajL8fm3SdyWmk4kA= dependencies: punycode "^2.1.1" tr46@~0.0.3: version "0.0.3" - resolved "https://registry.npm.alibaba-inc.com/tr46/download/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + resolved "https://registry.npm.alibaba-inc.com/tr46/download/tr46-0.0.3.tgz" integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= trim-newlines@^3.0.0: version "3.0.1" - resolved "https://registry.npm.alibaba-inc.com/trim-newlines/download/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" + resolved "https://registry.npm.alibaba-inc.com/trim-newlines/download/trim-newlines-3.0.1.tgz" integrity sha1-Jgpdli2LdSQlsy86fbDcrNF2wUQ= trough@^1.0.0: version "1.0.5" - resolved "https://registry.npm.alibaba-inc.com/trough/download/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" + resolved "https://registry.npm.alibaba-inc.com/trough/download/trough-1.0.5.tgz" integrity sha1-uLY5zvrX0LsqvTfUM/+Ck++l9AY= tslib@^1.8.1: version "1.14.1" - resolved "https://registry.npm.alibaba-inc.com/tslib/download/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + resolved "https://registry.npm.alibaba-inc.com/tslib/download/tslib-1.14.1.tgz" integrity sha1-zy04vcNKE0vK8QkcQfZhni9nLQA= -tslib@^2.1.0: - version "2.4.1" - resolved "https://registry.npm.alibaba-inc.com/tslib/download/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" - integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== - -tslib@^2.4.0: +tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0: version "2.5.0" - resolved "https://registry.npm.alibaba-inc.com/tslib/download/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" + resolved "https://registry.npm.alibaba-inc.com/tslib/download/tslib-2.5.0.tgz" integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== tsutils@^3.21.0: version "3.21.0" - resolved "https://registry.npm.alibaba-inc.com/tsutils/download/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + resolved "https://registry.npm.alibaba-inc.com/tsutils/download/tsutils-3.21.0.tgz" integrity sha1-tIcX05TOpsHglpg+7Vjp1hcVtiM= dependencies: tslib "^1.8.1" tty-browserify@0.0.0: version "0.0.0" - resolved "https://registry.npm.alibaba-inc.com/tty-browserify/download/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + resolved "https://registry.npm.alibaba-inc.com/tty-browserify/download/tty-browserify-0.0.0.tgz" integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= tween-functions@^1.0.1: version "1.2.0" - resolved "https://registry.npm.alibaba-inc.com/tween-functions/download/tween-functions-1.2.0.tgz#1ae3a50e7c60bb3def774eac707acbca73bbc3ff" + resolved "https://registry.npm.alibaba-inc.com/tween-functions/download/tween-functions-1.2.0.tgz" integrity sha1-GuOlDnxguz3vd06scHrLynO7w/8= type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" - resolved "https://registry.npm.alibaba-inc.com/type-check/download/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + resolved "https://registry.npm.alibaba-inc.com/type-check/download/type-check-0.4.0.tgz" integrity sha1-B7ggO/pwVsBlcFDjzNLDdzC6uPE= dependencies: prelude-ls "^1.2.1" type-check@~0.3.2: version "0.3.2" - resolved "https://registry.npm.alibaba-inc.com/type-check/download/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + resolved "https://registry.npm.alibaba-inc.com/type-check/download/type-check-0.3.2.tgz" integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= dependencies: prelude-ls "~1.1.2" type-detect@4.0.8: version "4.0.8" - resolved "https://registry.npm.alibaba-inc.com/type-detect/download/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + resolved "https://registry.npm.alibaba-inc.com/type-detect/download/type-detect-4.0.8.tgz" integrity sha1-dkb7XxiHHPu3dJ5pvTmmOI63RQw= type-fest@^0.18.0: version "0.18.1" - resolved "https://registry.npm.alibaba-inc.com/type-fest/download/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" + resolved "https://registry.npm.alibaba-inc.com/type-fest/download/type-fest-0.18.1.tgz" integrity sha1-20vBUaSiz07r+a3V23VQjbbMhB8= type-fest@^0.20.2: version "0.20.2" - resolved "https://registry.npm.alibaba-inc.com/type-fest/download/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + resolved "https://registry.npm.alibaba-inc.com/type-fest/download/type-fest-0.20.2.tgz" integrity sha1-G/IH9LKPkVg2ZstfvTJ4hzAc1fQ= type-fest@^0.21.3: version "0.21.3" - resolved "https://registry.npm.alibaba-inc.com/type-fest/download/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + resolved "https://registry.npm.alibaba-inc.com/type-fest/download/type-fest-0.21.3.tgz" integrity sha1-0mCiSwGYQ24TP6JqUkptZfo7Ljc= type-fest@^0.6.0: version "0.6.0" - resolved "https://registry.npm.alibaba-inc.com/type-fest/download/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + resolved "https://registry.npm.alibaba-inc.com/type-fest/download/type-fest-0.6.0.tgz" integrity sha1-jSojcNPfiG61yQraHFv2GIrPg4s= type-fest@^0.8.1: version "0.8.1" - resolved "https://registry.npm.alibaba-inc.com/type-fest/download/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + resolved "https://registry.npm.alibaba-inc.com/type-fest/download/type-fest-0.8.1.tgz" integrity sha1-CeJJ696FHTseSNJ8EFREZn8XuD0= type@^1.0.1: version "1.2.0" - resolved "https://registry.npm.alibaba-inc.com/type/download/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + resolved "https://registry.npm.alibaba-inc.com/type/download/type-1.2.0.tgz" integrity sha1-hI3XaY2vo+VKbEeedZxLw/GIR6A= type@^2.7.2: version "2.7.2" - resolved "https://registry.npm.alibaba-inc.com/type/download/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" + resolved "https://registry.npm.alibaba-inc.com/type/download/type-2.7.2.tgz" integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== +typed-array-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz" + integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + is-typed-array "^1.1.10" + +typed-array-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz" + integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz" + integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + typedarray-to-buffer@^3.1.5: version "3.1.5" - resolved "https://registry.npm.alibaba-inc.com/typedarray-to-buffer/download/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + resolved "https://registry.npm.alibaba-inc.com/typedarray-to-buffer/download/typedarray-to-buffer-3.1.5.tgz" integrity sha1-qX7nqf9CaRufeD/xvFES/j/KkIA= dependencies: is-typedarray "^1.0.0" typescript@4.9.3, typescript@^4.5.4: version "4.9.3" - resolved "https://registry.npm.alibaba-inc.com/typescript/download/typescript-4.9.3.tgz#3aea307c1746b8c384435d8ac36b8a2e580d85db" + resolved "https://registry.npm.alibaba-inc.com/typescript/download/typescript-4.9.3.tgz" integrity sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA== ua-parser-js@^0.7.30: version "0.7.32" - resolved "https://registry.npm.alibaba-inc.com/ua-parser-js/download/ua-parser-js-0.7.32.tgz#cd8c639cdca949e30fa68c44b7813ef13e36d211" + resolved "https://registry.npm.alibaba-inc.com/ua-parser-js/download/ua-parser-js-0.7.32.tgz" integrity sha512-f9BESNVhzlhEFf2CHMSj40NWOjYPl1YKYbrvIr/hFTDEmLq7SRbWvm7FcdcpCYT95zrOhC7gZSxjdnnTpBcwVw== +ua-parser-js@^1.0.35: + version "1.0.36" + resolved "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.36.tgz" + integrity sha512-znuyCIXzl8ciS3+y3fHJI/2OhQIXbXw9MWC/o3qwyR+RGppjZHrM27CGFSKCJXi2Kctiz537iOu2KnXs1lMQhw== + umi-request@^1.2.14: version "1.4.0" - resolved "https://registry.npm.alibaba-inc.com/umi-request/download/umi-request-1.4.0.tgz#ed0e54e47f043d2be06e691477f0890383f9dd8a" + resolved "https://registry.npm.alibaba-inc.com/umi-request/download/umi-request-1.4.0.tgz" integrity sha1-7Q5U5H8EPSvgbmkUd/CJA4P53Yo= dependencies: isomorphic-fetch "^2.2.1" @@ -11109,7 +13436,7 @@ umi-request@^1.2.14: umi@3.5.35: version "3.5.35" - resolved "https://registry.npm.alibaba-inc.com/umi/download/umi-3.5.35.tgz#10a2e69a4b3f24ab7ee36ec5013a4957d1847531" + resolved "https://registry.npm.alibaba-inc.com/umi/download/umi-3.5.35.tgz" integrity sha512-xGEAu3i+3x/VFuSLi3qBLXQavcMJRPf0vtg07359rI4SzTv2V87Vh7gj7GktBc1n9K20C1KtEsPpDodbbalR6w== dependencies: "@umijs/bundler-webpack" "3.5.35" @@ -11125,7 +13452,7 @@ umi@3.5.35: unbox-primitive@^1.0.2: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/unbox-primitive/download/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + resolved "https://registry.npm.alibaba-inc.com/unbox-primitive/download/unbox-primitive-1.0.2.tgz" integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== dependencies: call-bind "^1.0.2" @@ -11135,12 +13462,12 @@ unbox-primitive@^1.0.2: unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/unicode-canonical-property-names-ecmascript/download/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" + resolved "https://registry.npm.alibaba-inc.com/unicode-canonical-property-names-ecmascript/download/unicode-canonical-property-names-ecmascript-2.0.0.tgz" integrity sha1-MBrNxSVjFnDTn2FG4Od/9rvevdw= unicode-match-property-ecmascript@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/unicode-match-property-ecmascript/download/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" + resolved "https://registry.npm.alibaba-inc.com/unicode-match-property-ecmascript/download/unicode-match-property-ecmascript-2.0.0.tgz" integrity sha1-VP0W4OyxZ88Ezx91a9zJLrp5dsM= dependencies: unicode-canonical-property-names-ecmascript "^2.0.0" @@ -11148,17 +13475,17 @@ unicode-match-property-ecmascript@^2.0.0: unicode-match-property-value-ecmascript@^2.1.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/unicode-match-property-value-ecmascript/download/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0" + resolved "https://registry.npm.alibaba-inc.com/unicode-match-property-value-ecmascript/download/unicode-match-property-value-ecmascript-2.1.0.tgz" integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== unicode-property-aliases-ecmascript@^2.0.0: version "2.1.0" - resolved "https://registry.npm.alibaba-inc.com/unicode-property-aliases-ecmascript/download/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" + resolved "https://registry.npm.alibaba-inc.com/unicode-property-aliases-ecmascript/download/unicode-property-aliases-ecmascript-2.1.0.tgz" integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== unified@^9.1.0: version "9.2.2" - resolved "https://registry.npm.alibaba-inc.com/unified/download/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975" + resolved "https://registry.npm.alibaba-inc.com/unified/download/unified-9.2.2.tgz" integrity sha1-Z2SaGr/Dq4XSlpUCkCd16wMUaXU= dependencies: bail "^1.0.0" @@ -11170,7 +13497,7 @@ unified@^9.1.0: union-value@^1.0.0: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/union-value/download/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + resolved "https://registry.npm.alibaba-inc.com/union-value/download/union-value-1.0.1.tgz" integrity sha1-C2/nuDWuzaYcbqTU8CwUIh4QmEc= dependencies: arr-union "^3.1.0" @@ -11180,36 +13507,41 @@ union-value@^1.0.0: uniq@^1.0.1: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/uniq/download/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + resolved "https://registry.npm.alibaba-inc.com/uniq/download/uniq-1.0.1.tgz" integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= unist-util-find-all-after@^3.0.2: version "3.0.2" - resolved "https://registry.npm.alibaba-inc.com/unist-util-find-all-after/download/unist-util-find-all-after-3.0.2.tgz#fdfecd14c5b7aea5e9ef38d5e0d5f774eeb561f6" + resolved "https://registry.npm.alibaba-inc.com/unist-util-find-all-after/download/unist-util-find-all-after-3.0.2.tgz" integrity sha1-/f7NFMW3rqXp7zjV4NX3dO61YfY= dependencies: unist-util-is "^4.0.0" unist-util-is@^4.0.0: version "4.1.0" - resolved "https://registry.npm.alibaba-inc.com/unist-util-is/download/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" + resolved "https://registry.npm.alibaba-inc.com/unist-util-is/download/unist-util-is-4.1.0.tgz" integrity sha1-l25fRip6Xec9lLcGusG5BnG1d5c= unist-util-stringify-position@^2.0.0: version "2.0.3" - resolved "https://registry.npm.alibaba-inc.com/unist-util-stringify-position/download/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" + resolved "https://registry.npm.alibaba-inc.com/unist-util-stringify-position/download/unist-util-stringify-position-2.0.3.tgz" integrity sha1-zOO/oc34W6c3XR1bF73Eytqb2do= dependencies: "@types/unist" "^2.0.2" universalify@^0.2.0: version "0.2.0" - resolved "https://registry.npm.alibaba-inc.com/universalify/download/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" + resolved "https://registry.npm.alibaba-inc.com/universalify/download/universalify-0.2.0.tgz" integrity sha1-ZFF2BWb6hXU0dFqx3elS0bF2G+A= +unquote@~1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz" + integrity sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg== + unset-value@^1.0.0: version "1.0.0" - resolved "https://registry.npm.alibaba-inc.com/unset-value/download/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + resolved "https://registry.npm.alibaba-inc.com/unset-value/download/unset-value-1.0.0.tgz" integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= dependencies: has-value "^0.3.1" @@ -11217,12 +13549,12 @@ unset-value@^1.0.0: unstated-next@^1.1.0: version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/unstated-next/download/unstated-next-1.1.0.tgz#7bb4911a12fdf3cc8ad3eb11a0b315e4a8685ea8" + resolved "https://registry.npm.alibaba-inc.com/unstated-next/download/unstated-next-1.1.0.tgz" integrity sha1-e7SRGhL988yK0+sRoLMV5KhoXqg= update-browserslist-db@^1.0.9: version "1.0.10" - resolved "https://registry.npm.alibaba-inc.com/update-browserslist-db/download/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" + resolved "https://registry.npm.alibaba-inc.com/update-browserslist-db/download/update-browserslist-db-1.0.10.tgz" integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== dependencies: escalade "^3.1.1" @@ -11230,19 +13562,19 @@ update-browserslist-db@^1.0.9: uri-js@^4.2.2: version "4.4.1" - resolved "https://registry.npm.alibaba-inc.com/uri-js/download/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + resolved "https://registry.npm.alibaba-inc.com/uri-js/download/uri-js-4.4.1.tgz" integrity sha1-mxpSWVIlhZ5V9mnZKPiMbFfyp34= dependencies: punycode "^2.1.0" urix@^0.1.0: version "0.1.0" - resolved "https://registry.npm.alibaba-inc.com/urix/download/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + resolved "https://registry.npm.alibaba-inc.com/urix/download/urix-0.1.0.tgz" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= url-parse@^1.5.3: version "1.5.10" - resolved "https://registry.npm.alibaba-inc.com/url-parse/download/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + resolved "https://registry.npm.alibaba-inc.com/url-parse/download/url-parse-1.5.10.tgz" integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== dependencies: querystringify "^2.1.1" @@ -11250,71 +13582,103 @@ url-parse@^1.5.3: url-toolkit@^2.2.1: version "2.2.5" - resolved "https://registry.npm.alibaba-inc.com/url-toolkit/download/url-toolkit-2.2.5.tgz#58406b18e12c58803e14624df5e374f638b0f607" + resolved "https://registry.npm.alibaba-inc.com/url-toolkit/download/url-toolkit-2.2.5.tgz" integrity sha512-mtN6xk+Nac+oyJ/PrI7tzfmomRVNFIWKUbG8jdYFt52hxbiReFAXIjYskvu64/dvuW71IcB7lV8l0HvZMac6Jg== url@^0.11.0: version "0.11.0" - resolved "https://registry.npm.alibaba-inc.com/url/download/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + resolved "https://registry.npm.alibaba-inc.com/url/download/url-0.11.0.tgz" integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= dependencies: punycode "1.3.2" querystring "0.2.0" +use-composed-ref@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.3.0.tgz" + integrity sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ== + +use-isomorphic-layout-effect@^1.1.1: + version "1.1.2" + resolved "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz" + integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA== + use-json-comparison@^1.0.3, use-json-comparison@^1.0.5: version "1.0.6" - resolved "https://registry.npm.alibaba-inc.com/use-json-comparison/download/use-json-comparison-1.0.6.tgz#a012bbc258ce745db1f56745dc653f575226cb21" + resolved "https://registry.npm.alibaba-inc.com/use-json-comparison/download/use-json-comparison-1.0.6.tgz" integrity sha1-oBK7wljOdF2x9WdF3GU/V1ImyyE= +use-latest@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/use-latest/-/use-latest-1.2.1.tgz" + integrity sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw== + dependencies: + use-isomorphic-layout-effect "^1.1.1" + use-media-antd-query@^1.0.3, use-media-antd-query@^1.1.0: version "1.1.0" - resolved "https://registry.npm.alibaba-inc.com/use-media-antd-query/download/use-media-antd-query-1.1.0.tgz#f083ad7e292c1c0261b6bbfaac0edc3e0920d85d" + resolved "https://registry.npm.alibaba-inc.com/use-media-antd-query/download/use-media-antd-query-1.1.0.tgz" integrity sha1-8IOtfiksHAJhtrv6rA7cPgkg2F0= use-subscription@1.5.1: version "1.5.1" - resolved "https://registry.npm.alibaba-inc.com/use-subscription/download/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1" + resolved "https://registry.npm.alibaba-inc.com/use-subscription/download/use-subscription-1.5.1.tgz" integrity sha1-c1ARB/AvrYTG3VeWW+sLdcaMQtE= dependencies: object-assign "^4.1.1" +use-sync-external-store@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== + use@^3.1.0: version "3.1.1" - resolved "https://registry.npm.alibaba-inc.com/use/download/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + resolved "https://registry.npm.alibaba-inc.com/use/download/use-3.1.1.tgz" integrity sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8= util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/util-deprecate/download/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + resolved "https://registry.npm.alibaba-inc.com/util-deprecate/download/util-deprecate-1.0.2.tgz" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= +util.promisify@~1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz" + integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.2" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.0" + util@0.10.3: version "0.10.3" - resolved "https://registry.npm.alibaba-inc.com/util/download/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + resolved "https://registry.npm.alibaba-inc.com/util/download/util-0.10.3.tgz" integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= dependencies: inherits "2.0.1" util@^0.11.0: version "0.11.1" - resolved "https://registry.npm.alibaba-inc.com/util/download/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" + resolved "https://registry.npm.alibaba-inc.com/util/download/util-0.11.1.tgz" integrity sha1-MjZzNyDsZLsn9uJvQhqqLhtYjWE= dependencies: inherits "2.0.3" uuid@^8.3.0: version "8.3.2" - resolved "https://registry.npm.alibaba-inc.com/uuid/download/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + resolved "https://registry.npm.alibaba-inc.com/uuid/download/uuid-8.3.2.tgz" integrity sha1-gNW1ztJxu5r2xEXyGhoExgbO++I= v8-compile-cache@2.3.0, v8-compile-cache@^2.0.3, v8-compile-cache@^2.3.0: version "2.3.0" - resolved "https://registry.npm.alibaba-inc.com/v8-compile-cache/download/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + resolved "https://registry.npm.alibaba-inc.com/v8-compile-cache/download/v8-compile-cache-2.3.0.tgz" integrity sha1-LeGWGMZtwkfc+2+ZM4A12CRaLO4= v8-to-istanbul@^7.0.0: version "7.1.2" - resolved "https://registry.npm.alibaba-inc.com/v8-to-istanbul/download/v8-to-istanbul-7.1.2.tgz#30898d1a7fa0c84d225a2c1434fb958f290883c1" + resolved "https://registry.npm.alibaba-inc.com/v8-to-istanbul/download/v8-to-istanbul-7.1.2.tgz" integrity sha1-MImNGn+gyE0iWiwUNPuVjykIg8E= dependencies: "@types/istanbul-lib-coverage" "^2.0.1" @@ -11323,20 +13687,25 @@ v8-to-istanbul@^7.0.0: validate-npm-package-license@^3.0.1: version "3.0.4" - resolved "https://registry.npm.alibaba-inc.com/validate-npm-package-license/download/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + resolved "https://registry.npm.alibaba-inc.com/validate-npm-package-license/download/validate-npm-package-license-3.0.4.tgz" integrity sha1-/JH2uce6FchX9MssXe/uw51PQQo= dependencies: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" +validator@^12.1.0: + version "12.2.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-12.2.0.tgz#660d47e96267033fd070096c3b1a6f2db4380a0a" + integrity sha512-jJfE/DW6tIK1Ek8nCfNFqt8Wb3nzMoAbocBF6/Icgg1ZFSBpObdnwVY2jQj6qUqzhx5jc71fpvBWyLGO7Xl+nQ== + value-equal@^1.0.1: version "1.0.1" - resolved "https://registry.npm.alibaba-inc.com/value-equal/download/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" + resolved "https://registry.npm.alibaba-inc.com/value-equal/download/value-equal-1.0.1.tgz" integrity sha1-Hgt5THNMXAyt4XnEN9NW2TGjTWw= vfile-message@^2.0.0: version "2.0.4" - resolved "https://registry.npm.alibaba-inc.com/vfile-message/download/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a" + resolved "https://registry.npm.alibaba-inc.com/vfile-message/download/vfile-message-2.0.4.tgz" integrity sha1-W0O4gXHUCerlhHfRPyPdQdUsNxo= dependencies: "@types/unist" "^2.0.0" @@ -11344,7 +13713,7 @@ vfile-message@^2.0.0: vfile@^4.0.0: version "4.2.1" - resolved "https://registry.npm.alibaba-inc.com/vfile/download/vfile-4.2.1.tgz#03f1dce28fc625c625bc6514350fbdb00fa9e624" + resolved "https://registry.npm.alibaba-inc.com/vfile/download/vfile-4.2.1.tgz" integrity sha1-A/Hc4o/GJcYlvGUUNQ+9sA+p5iQ= dependencies: "@types/unist" "^2.0.0" @@ -11354,7 +13723,7 @@ vfile@^4.0.0: video.js@7.20.3: version "7.20.3" - resolved "https://registry.npm.alibaba-inc.com/video.js/download/video.js-7.20.3.tgz#5694741346dc683255993e5069daa15d4bacb646" + resolved "https://registry.npm.alibaba-inc.com/video.js/download/video.js-7.20.3.tgz" integrity sha512-JMspxaK74LdfWcv69XWhX4rILywz/eInOVPdKefpQiZJSMD5O8xXYueqACP2Q5yqKstycgmmEKlJzZ+kVmDciw== dependencies: "@babel/runtime" "^7.12.5" @@ -11373,7 +13742,7 @@ video.js@7.20.3: "video.js@^6 || ^7": version "7.21.3" - resolved "https://registry.npm.alibaba-inc.com/video.js/download/video.js-7.21.3.tgz#1a5f6379e713de3f5dc036ecdef02efb80765bdd" + resolved "https://registry.npm.alibaba-inc.com/video.js/download/video.js-7.21.3.tgz" integrity sha512-fIboXbSDCT3P8eVzIEC3hnLDKC/y+6QftcHdFGUVGn5a7qmH62Mh0Bt/SrBAgdmKDQM1qdZXfXAxPg5+IaiIXQ== dependencies: "@babel/runtime" "^7.12.5" @@ -11392,74 +13761,74 @@ video.js@7.20.3: videojs-font@3.2.0: version "3.2.0" - resolved "https://registry.npm.alibaba-inc.com/videojs-font/download/videojs-font-3.2.0.tgz#212c9d3f4e4ec3fa7345167d64316add35e92232" + resolved "https://registry.npm.alibaba-inc.com/videojs-font/download/videojs-font-3.2.0.tgz" integrity sha1-ISydP05Ow/pzRRZ9ZDFq3TXpIjI= videojs-vtt.js@^0.15.4: version "0.15.4" - resolved "https://registry.npm.alibaba-inc.com/videojs-vtt.js/download/videojs-vtt.js-0.15.4.tgz#5dc5aabcd82ba40c5595469bd855ea8230ca152c" + resolved "https://registry.npm.alibaba-inc.com/videojs-vtt.js/download/videojs-vtt.js-0.15.4.tgz" integrity sha512-r6IhM325fcLb1D6pgsMkTQT1PpFdUdYZa1iqk7wJEu+QlibBwATPfPc9Bg8Jiym0GE5yP1AG2rMLu+QMVWkYtA== dependencies: global "^4.3.1" vm-browserify@^1.0.1: version "1.1.2" - resolved "https://registry.npm.alibaba-inc.com/vm-browserify/download/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + resolved "https://registry.npm.alibaba-inc.com/vm-browserify/download/vm-browserify-1.1.2.tgz" integrity sha1-eGQcSIuObKkadfUR56OzKobl3aA= w3c-hr-time@^1.0.2: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/w3c-hr-time/download/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" + resolved "https://registry.npm.alibaba-inc.com/w3c-hr-time/download/w3c-hr-time-1.0.2.tgz" integrity sha1-ConN9cwVgi35w2BUNnaWPgzDCM0= dependencies: browser-process-hrtime "^1.0.0" w3c-xmlserializer@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/w3c-xmlserializer/download/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" + resolved "https://registry.npm.alibaba-inc.com/w3c-xmlserializer/download/w3c-xmlserializer-2.0.0.tgz" integrity sha1-PnEEoFt1FGzGD1ZDgLf2g6zxAgo= dependencies: xml-name-validator "^3.0.0" walker@^1.0.7, walker@~1.0.5: version "1.0.8" - resolved "https://registry.npm.alibaba-inc.com/walker/download/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + resolved "https://registry.npm.alibaba-inc.com/walker/download/walker-1.0.8.tgz" integrity sha1-vUmNtHev5XPcBBhfAR06uKjXZT8= dependencies: makeerror "1.0.12" warning@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/warning/download/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" + resolved "https://registry.npm.alibaba-inc.com/warning/download/warning-3.0.0.tgz" integrity sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w= dependencies: loose-envify "^1.0.0" warning@^4.0.3: version "4.0.3" - resolved "https://registry.npm.alibaba-inc.com/warning/download/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" + resolved "https://registry.npm.alibaba-inc.com/warning/download/warning-4.0.3.tgz" integrity sha1-Fungd+uKhtavfWSqHgX9hbRnjKM= dependencies: loose-envify "^1.0.0" webidl-conversions@^3.0.0: version "3.0.1" - resolved "https://registry.npm.alibaba-inc.com/webidl-conversions/download/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + resolved "https://registry.npm.alibaba-inc.com/webidl-conversions/download/webidl-conversions-3.0.1.tgz" integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= webidl-conversions@^5.0.0: version "5.0.0" - resolved "https://registry.npm.alibaba-inc.com/webidl-conversions/download/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + resolved "https://registry.npm.alibaba-inc.com/webidl-conversions/download/webidl-conversions-5.0.0.tgz" integrity sha1-rlnIoAsSFUOirMZcBDT1ew/BGv8= webidl-conversions@^6.1.0: version "6.1.0" - resolved "https://registry.npm.alibaba-inc.com/webidl-conversions/download/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" + resolved "https://registry.npm.alibaba-inc.com/webidl-conversions/download/webidl-conversions-6.1.0.tgz" integrity sha1-kRG01+qArNQPUnDWZmIa+ni2lRQ= webpack-chain@6.5.1: version "6.5.1" - resolved "https://registry.npm.alibaba-inc.com/webpack-chain/download/webpack-chain-6.5.1.tgz#4f27284cbbb637e3c8fbdef43eef588d4d861206" + resolved "https://registry.npm.alibaba-inc.com/webpack-chain/download/webpack-chain-6.5.1.tgz" integrity sha1-TycoTLu2N+PI+970Pu9YjU2GEgY= dependencies: deepmerge "^1.5.2" @@ -11467,24 +13836,24 @@ webpack-chain@6.5.1: whatwg-encoding@^1.0.5: version "1.0.5" - resolved "https://registry.npm.alibaba-inc.com/whatwg-encoding/download/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + resolved "https://registry.npm.alibaba-inc.com/whatwg-encoding/download/whatwg-encoding-1.0.5.tgz" integrity sha1-WrrPd3wyFmpR0IXWtPPn0nET3bA= dependencies: iconv-lite "0.4.24" whatwg-fetch@>=0.10.0, whatwg-fetch@^3.5.0: version "3.6.2" - resolved "https://registry.npm.alibaba-inc.com/whatwg-fetch/download/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" + resolved "https://registry.npm.alibaba-inc.com/whatwg-fetch/download/whatwg-fetch-3.6.2.tgz" integrity sha1-3O0k838mJO0CgXJdUdDi4/5nf4w= whatwg-mimetype@^2.3.0: version "2.3.0" - resolved "https://registry.npm.alibaba-inc.com/whatwg-mimetype/download/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + resolved "https://registry.npm.alibaba-inc.com/whatwg-mimetype/download/whatwg-mimetype-2.3.0.tgz" integrity sha1-PUseAxLSB5h5+Cav8Y2+7KWWD78= whatwg-url@^5.0.0: version "5.0.0" - resolved "https://registry.npm.alibaba-inc.com/whatwg-url/download/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + resolved "https://registry.npm.alibaba-inc.com/whatwg-url/download/whatwg-url-5.0.0.tgz" integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= dependencies: tr46 "~0.0.3" @@ -11492,7 +13861,7 @@ whatwg-url@^5.0.0: whatwg-url@^8.0.0, whatwg-url@^8.5.0: version "8.7.0" - resolved "https://registry.npm.alibaba-inc.com/whatwg-url/download/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" + resolved "https://registry.npm.alibaba-inc.com/whatwg-url/download/whatwg-url-8.7.0.tgz" integrity sha1-ZWp45RD/jzk3vAvL6fXArDWUG3c= dependencies: lodash "^4.7.0" @@ -11501,7 +13870,7 @@ whatwg-url@^8.0.0, whatwg-url@^8.5.0: which-boxed-primitive@^1.0.2: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/which-boxed-primitive/download/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + resolved "https://registry.npm.alibaba-inc.com/which-boxed-primitive/download/which-boxed-primitive-1.0.2.tgz" integrity sha1-E3V7yJsgmwSf5dhkMOIc9AqJqOY= dependencies: is-bigint "^1.0.1" @@ -11512,31 +13881,42 @@ which-boxed-primitive@^1.0.2: which-module@^2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/which-module/download/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + resolved "https://registry.npm.alibaba-inc.com/which-module/download/which-module-2.0.0.tgz" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= +which-typed-array@^1.1.10, which-typed-array@^1.1.11: + version "1.1.11" + resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz" + integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + which@^1.2.9, which@^1.3.1: version "1.3.1" - resolved "https://registry.npm.alibaba-inc.com/which/download/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + resolved "https://registry.npm.alibaba-inc.com/which/download/which-1.3.1.tgz" integrity sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo= dependencies: isexe "^2.0.0" which@^2.0.1, which@^2.0.2: version "2.0.2" - resolved "https://registry.npm.alibaba-inc.com/which/download/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + resolved "https://registry.npm.alibaba-inc.com/which/download/which-2.0.2.tgz" integrity sha1-fGqN0KY2oDJ+ELWckobu6T8/UbE= dependencies: isexe "^2.0.0" word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" - resolved "https://registry.npm.alibaba-inc.com/word-wrap/download/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + resolved "https://registry.npm.alibaba-inc.com/word-wrap/download/word-wrap-1.2.3.tgz" integrity sha1-YQY29rH3A4kb00dxzLF/uTtHB5w= wrap-ansi@^6.2.0: version "6.2.0" - resolved "https://registry.npm.alibaba-inc.com/wrap-ansi/download/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + resolved "https://registry.npm.alibaba-inc.com/wrap-ansi/download/wrap-ansi-6.2.0.tgz" integrity sha1-6Tk7oHEC5skaOyIUePAlfNKFblM= dependencies: ansi-styles "^4.0.0" @@ -11545,7 +13925,7 @@ wrap-ansi@^6.2.0: wrap-ansi@^7.0.0: version "7.0.0" - resolved "https://registry.npm.alibaba-inc.com/wrap-ansi/download/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + resolved "https://registry.npm.alibaba-inc.com/wrap-ansi/download/wrap-ansi-7.0.0.tgz" integrity sha1-Z+FFz/UQpqaYS98RUpEdadLrnkM= dependencies: ansi-styles "^4.0.0" @@ -11554,12 +13934,12 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" - resolved "https://registry.npm.alibaba-inc.com/wrappy/download/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.npm.alibaba-inc.com/wrappy/download/wrappy-1.0.2.tgz" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: version "3.0.3" - resolved "https://registry.npm.alibaba-inc.com/write-file-atomic/download/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + resolved "https://registry.npm.alibaba-inc.com/write-file-atomic/download/write-file-atomic-3.0.3.tgz" integrity sha1-Vr1cWlxwSBzRnFcb05q5ZaXeVug= dependencies: imurmurhash "^0.1.4" @@ -11569,52 +13949,52 @@ write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: ws@^7.4.6: version "7.5.9" - resolved "https://registry.npm.alibaba-inc.com/ws/download/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + resolved "https://registry.npm.alibaba-inc.com/ws/download/ws-7.5.9.tgz" integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== xml-name-validator@^3.0.0: version "3.0.0" - resolved "https://registry.npm.alibaba-inc.com/xml-name-validator/download/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + resolved "https://registry.npm.alibaba-inc.com/xml-name-validator/download/xml-name-validator-3.0.0.tgz" integrity sha1-auc+Bt5NjG5H+fsYH3jWSK1FfGo= xmlchars@^2.2.0: version "2.2.0" - resolved "https://registry.npm.alibaba-inc.com/xmlchars/download/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + resolved "https://registry.npm.alibaba-inc.com/xmlchars/download/xmlchars-2.2.0.tgz" integrity sha1-Bg/hvLf5x2/ioX24apvDq4lCEMs= xtend@^4.0.0: version "4.0.2" - resolved "https://registry.npm.alibaba-inc.com/xtend/download/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + resolved "https://registry.npm.alibaba-inc.com/xtend/download/xtend-4.0.2.tgz" integrity sha1-u3J3n1+kZRhrH0OPZ0+jR/2121Q= y18n@^4.0.0: version "4.0.3" - resolved "https://registry.npm.alibaba-inc.com/y18n/download/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + resolved "https://registry.npm.alibaba-inc.com/y18n/download/y18n-4.0.3.tgz" integrity sha1-tfJZyCzW4zaSHv17/Yv1YN6e7t8= y18n@^5.0.5: version "5.0.8" - resolved "https://registry.npm.alibaba-inc.com/y18n/download/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + resolved "https://registry.npm.alibaba-inc.com/y18n/download/y18n-5.0.8.tgz" integrity sha1-f0k00PfKjFb5UxSTndzS3ZHOHVU= yallist@^2.1.2: version "2.1.2" - resolved "https://registry.npm.alibaba-inc.com/yallist/download/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + resolved "https://registry.npm.alibaba-inc.com/yallist/download/yallist-2.1.2.tgz" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= yallist@^4.0.0: version "4.0.0" - resolved "https://registry.npm.alibaba-inc.com/yallist/download/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + resolved "https://registry.npm.alibaba-inc.com/yallist/download/yallist-4.0.0.tgz" integrity sha1-m7knkNnA7/7GO+c1GeEaNQGaOnI= yaml@^1.10.0, yaml@^1.10.2: version "1.10.2" - resolved "https://registry.npm.alibaba-inc.com/yaml/download/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + resolved "https://registry.npm.alibaba-inc.com/yaml/download/yaml-1.10.2.tgz" integrity sha1-IwHF/78StGfejaIzOkWeKeeSDks= yargs-parser@^18.1.2: version "18.1.3" - resolved "https://registry.npm.alibaba-inc.com/yargs-parser/download/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + resolved "https://registry.npm.alibaba-inc.com/yargs-parser/download/yargs-parser-18.1.3.tgz" integrity sha1-vmjEl1xrKr9GkjawyHA2L6sJp7A= dependencies: camelcase "^5.0.0" @@ -11622,17 +14002,17 @@ yargs-parser@^18.1.2: yargs-parser@^20.2.3: version "20.2.9" - resolved "https://registry.npm.alibaba-inc.com/yargs-parser/download/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + resolved "https://registry.npm.alibaba-inc.com/yargs-parser/download/yargs-parser-20.2.9.tgz" integrity sha1-LrfcOwKJcY/ClfNidThFxBoMlO4= yargs-parser@^21.1.1: version "21.1.1" - resolved "https://registry.npm.alibaba-inc.com/yargs-parser/download/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + resolved "https://registry.npm.alibaba-inc.com/yargs-parser/download/yargs-parser-21.1.1.tgz" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== yargs@^15.4.1: version "15.4.1" - resolved "https://registry.npm.alibaba-inc.com/yargs/download/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + resolved "https://registry.npm.alibaba-inc.com/yargs/download/yargs-15.4.1.tgz" integrity sha1-DYehbeAa7p2L7Cv7909nhRcw9Pg= dependencies: cliui "^6.0.0" @@ -11647,9 +14027,22 @@ yargs@^15.4.1: y18n "^4.0.0" yargs-parser "^18.1.2" +yargs@^17.0.0-candidate.0: + version "17.7.2" + resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + yargs@^17.0.1: version "17.6.2" - resolved "https://registry.npm.alibaba-inc.com/yargs/download/yargs-17.6.2.tgz#2e23f2944e976339a1ee00f18c77fedee8332541" + resolved "https://registry.npm.alibaba-inc.com/yargs/download/yargs-17.6.2.tgz" integrity sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw== dependencies: cliui "^8.0.1" @@ -11662,7 +14055,7 @@ yargs@^17.0.1: yorkie@2.0.0: version "2.0.0" - resolved "https://registry.npm.alibaba-inc.com/yorkie/download/yorkie-2.0.0.tgz#92411912d435214e12c51c2ae1093e54b6bb83d9" + resolved "https://registry.npm.alibaba-inc.com/yorkie/download/yorkie-2.0.0.tgz" integrity sha1-kkEZEtQ1IU4SxRwq4Qk+VLa7g9k= dependencies: execa "^0.8.0" @@ -11672,12 +14065,12 @@ yorkie@2.0.0: zscroller@~0.4.0: version "0.4.8" - resolved "https://registry.npm.alibaba-inc.com/zscroller/download/zscroller-0.4.8.tgz#69eed68690808eedf81f9714014356b36cdd20f4" + resolved "https://registry.npm.alibaba-inc.com/zscroller/download/zscroller-0.4.8.tgz" integrity sha1-ae7WhpCAju34H5cUAUNWs2zdIPQ= dependencies: babel-runtime "6.x" zwitch@^1.0.0: version "1.0.5" - resolved "https://registry.npm.alibaba-inc.com/zwitch/download/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" + resolved "https://registry.npm.alibaba-inc.com/zwitch/download/zwitch-1.0.5.tgz" integrity sha1-0R1zgf/tFrdC9q97PyI9XNn+mSA=

    + {intl.formatMessage({ + id: 'OBD.component.CustomPasswordInput.PleaseRememberThePasswordOr', + defaultMessage: '请牢记密码,也可', + })} + + passwordCopy()}> + {intl.formatMessage({ + id: 'OBD.component.CustomPasswordInput.CopyPassword', + defaultMessage: '复制密码', + })} + + {intl.formatMessage({ + id: 'OBD.component.CustomPasswordInput.AndKeepItProperly', + defaultMessage: '并妥善保存', + })} +

    3hd%T1Roou7$o{A-RvVk6Um} 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 literal 0 HcmV?d00001 diff --git a/web/public/assets/update/arrow.svg b/web/public/assets/update/arrow.svg new file mode 100644 index 0000000..eed127b --- /dev/null +++ b/web/public/assets/update/arrow.svg @@ -0,0 +1,9 @@ + + + 形状结合 + + + + + + \ No newline at end of file diff --git a/web/public/assets/welcome/banner.png b/web/public/assets/welcome/banner.png new file mode 100644 index 0000000000000000000000000000000000000000..e7003c1c8665e33e4a0c799a97a74391ede74896 GIT binary patch literal 112413 zcmV)QK(xP!P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR960H6Z^1ONa40RR91djJ3c04W^LGyniV07*naRCodGy;-cK>2;pB_c>Lk z=CP}*yLwrsu%e3~3E-O`Mv}WA$c+Q|BFI$&I6)9!1PBr! z%8ls=u@zg1;6!9JSh6{fO?H#rO;+_#L)UzUywCft_5J@oRZVtNr>*Yl{O8pFf8Sc~ zde^(w_w9e5UHc5nLy!Np#bU9uv$I$%bzLr(HQHG$m$GBVQ3DM*z{~9z8x|GS7ESF< zu)I4Ofq@H92nLM^l{!>9@0ywwN{2$c3lRPh-qM3d1Nc;8P=z;L^G~$9`Kw$~w~7Q8 zMG2^uC>k8cD5~I1)RhclT*RwYw<;>=}KD;@}-!f{HTh z<*f3uNf0run8QnnX|>jBc+%=h|7Y-8$I4+w0g&N+B0-sU6H9(`B#tvMcX$laPa`d4 zP$w&lV!43oBeiCHUplw2G(b4uPF7|Pr@TMAh3lRQ+?)H*BN5>CH+aojqfSYMW zNiR@GQxt&EYt#)5n@H$96X%7q2VnEh(voh%JIcn1Up7K~Sc#ijyL4KwmNT-Mi-I_; z2Bz%EOi@_LdbjLeFUPO6$85Dvn#L)}vispUvRB>$Iw|-x%=;f`uUGAd-SksHZBrWR@TDP!(?TR?+jrwTpoGD-Tz>dtKlkX{-ud0{ zeCyVY>l+(uk34Yfv2(}udG_?-)of0APoF-2?D>EA$mgFte2FTT%lEu|@~1C8^fMRF zJ#^#f8@6t(^}qAs-+OWYO>L_E+w1?u@BYHpjrFy~&e4NwCyp!+Zm`2%e0j0Gy{8o{ z7e@~8dC%;Sr_OKw>u+uH0J+->zz_cHSJ31yGq+zSC^DOiw*^JOkTDVk7BUN|s@X`zZ`O{qRlq4i6W!+{ zU_9jru5eciYtl_IsA5JRGzKs#oA8Wsq>7%+g+=2mUYzakK9oFU7DdvP#z8x(s;}Q% zz`@7x-|9`LNbpq&k(#5$dQ_UdHnug(Dah(k0nY9yxr;WoU2x+`4h&AE?4&hV ziD=)dpcTk$qKcpnKXeXDqhybP!L&5M6B5}LTQi^v&f8Eu)?YjT+(>(%AaAvd62u6SeEQoV5Q>=xnN(0Kzy9;FmBh+?4zzi2g$Tn!!i(~oi9fF{2Jmcvoia2GS2Fhqz zmSpPv)1w4Jy2ska!Mk(0LM8!_4nSp^&r< zqJ7ZT{x=)WU3$5KEw6XlaBb(>W z9C;02+7o^69RKpf_y7L8{^0g=u!UY9{MaZb=*y-da-G1~fErS&vd(Hh=gzcqieTkT}5 z0#@aZr`i>2>v7XG(vgA~xCMC7@29Wfc7KewFh)`6S{v_fC@>5rDK?GQ_nmw%G<|r? zsf-<@=>U0HN*H?{zc7Jm+My(C-Idruqy%qb@E&07E@vEbohv9jr6`Hq2a3dMHd$(H zizbngM8<<20lu3gf&l%iFV-~jVSpWuvn|PeCZcS)BA|35h~>*v?tq7gSwLY1GL$RR zk%X5puy@mB6` zgXvp_Rlv@mT3GZh*SK;AR2>N1n3ki`P2;OtfE<$MTB?Ic$i$nk(dDZcE(3#pcNDzi zbH-kW%b3Q5>YvHXnXIw~NTLqWz_%Hqv2*3@_;3`DJx!rWBL)?L#3Qfir$jjP4=;d> zWby}dWRwSQ?_c?wZXO0iM@&72#`GHaR#b*Nq4QEBdp zr|@+@DSIJpZ1r+Y8O&J=0CCzedkyIoHz)_;NJ;Fo173V>`Hz&g9dzD4L68aiX?X(-_kfEQ}orlAxr)3M|veu%{}JJ=2^6 zZg?n}O$(s0KL}&{R$S9K-%7oX1~>lWBQ>MZ9SA>xOyMH|VeOV{W8eBueBi;~{7X;# zC;#40{r$iDiLJ%P`78S#ePBZ`gNc0W9oo$Q`MW-Qaozk2P)*5t_$-zGOPrxBX{72t!Rs4^NWGF@uB(bjxDhO2BZ=> z28ZXfJFwx72yJUrDhv@}Qd>gr+;+zwF{Wo&8j`EjB~SRA-ie%GN(rcgVM`U$0w9PG z9~yu)zRmEPooH}QsGI6OkogY`H!ELB=!s5Ni2Q|%z}QJE7KowK$F$PelfzzflBK>h z36&CC6&KV%OZxC5N&mucjcD_~AUQL&u=?T{Tn>+1xtLu>$rIiN(}yAja5iHFkUfDV zLxzc8S?06UiyAkkc}&=~nFh%m;HrQch}#IqSV~QWjF;y@y~@Rsd(^dr!MEZh+9e^1E} zJsKr^*k=PW)*+A%%c_7Oi2QOjc8-kANEf1c!-&yQQx_47@}nqaRh6c;^@ zywF}RJOR>A4xg)^9uIzJBQy=uIS~w;-D$hoz)Z-}&`(WQ@y_OjLqo4%uShSb)>eV$ zhaz?8EQ9QGKEPg_R0c2?2%J7B zljXpK9aWMuTi^j?FzKN)6z20_tX7t$WHCQ_7}!L;9;NUp8Wnfy$$D9biG6a1h|Ge? z3$s<)yQ=rnc{ZrLshHtLOx6pqPh5{~qtC&0NLMWV-gQ~q3! zBHf?#zX%1G6ccYd8mm09al{TY@S4I145J%kF99`3=Zp`J<@xa_P`oZrc&^RtDLiD_ zS*)!uKlJYVfBwfG`Q*nQ`RNazJA80@3-6acxcHMN7hn1A;^Xf&{H=HTSH~|rbLeGS zw^*LJb@1aC&wcLr^WQmmr8<$-+Sz&L;LE@D(AR$J+}F{*C=>hYv0f z|4484zEUmMZ@u}N_O=HOe&F#VU;Osf)uQ@-Qg@kl&dnOnZlFTwMs)VRlizvH8&wY_ z-{=g2Mfcdc(e?9=LX4W-4~6D4H&6)uPz45m-!^@HWRZq3eZZ-BJA9|ku6m31> zf_A2^5>ztdi{BlDdD4bH8{7@?SHdL17d&TUGf4NsgdX6_x>d~A*kwXOjkS)UOy9DY z$V)HGo}^BU01i}=#v)KDLbB>3+d>XH;$CKn5tri2!xT~-K06#@Xcbs<(~`(2a~kgO z!15(BatL%BnS~9R@fzA7o2$#LVR!NypR8VLe+_R~VswUSG*M&bHb$-iFqp+rawjZM zkBQJh$-X*Aw=UPIbVES<13E8*0CWCQkry5;O+~33 zefDE5;ni-!+*y%;suedry+VRXc+{k70!mg2fig517#3RST}~x5UGPpwAl13+HE>Kl zDloA_jLVv8Ms_jmORG8xBP>Vo9!)Y#>#b4= zy?ElIHg}w1dS-1*j7Mr3C6fe;zi?IquIj)~Doo+D0(bFh)_N*J$Py`b=MY81DQ)y$z$CC0Jw#fM)4Met5O&;dzcmmY zJ)BM4i6X-EoH$CCk-)6m^n@D0xg&EmP*!Ro0f}4ydJ^PKLU;y#z<^Rj7j9rBfyQW^ z;6x8)K$o1gzEJ3B8{m}dAn;if%dxlciAbQ=*YtBeFzGO!OLh|`_um66^4=l=TSdUA zWTE;9gPX^aI~Kee1x_yu{B5f8gc&*5-?6uGjl?Y2U4{jIC1#R_d@P9mA|&Oc;b=u7q0l8@tPukAo%9(JQjZ-=#A(6P9!_-^W|XHMxqRa_!jHH5@=yjp zJ2;H{p$6PGeLLqyT558?cDR#6s8Bz0i&PM(d~lNwqEI!8BXkGlG_7$a0c&TNt2C_R5A$@ zgvJVw#L8X-DVcN2cHG3@)QRKyh!?==c+@0Vd}*sQv4~c}C0*5pwe7D7WM*7Nj9N%1 zhJtmX(1ky(ttu=Q;@Sba@)bhFYV7PRo#nX1@b^|LBpU5SC8CUn7G)5ccIa{X<_9c< z0t?T~y@n@DnKDKmoQ%P{1sp<{zkj3hdr=b#QpsVa2 z+da_oYCQU>w8keLW1K|8Wm#M(MlP!dF9X)}7JMIK&`_4pT8{BVI~T+WhNSRNS(pox z+c8q%FynnwamU~{Ubq^_u3?NO@9_#hs*=cSGi7%uWb$$uRFaWGq69X)bi-vD&!|#| zKl;*y6`1%Pr~p%0Dx4&Q*8J5UR78;ABnZp{6yQgN%3!@nT6uwdcA;=ZU9r?X*#urJA!CMAQomyRq28G89I^EE~IWSCA zjqiR63!eN1W8VBSHb0#~ZNaVHF!NKW*IjlGcuMT*6zH(X(6FRp7bSZ+<(r=c0Ppoo zMg=g4EPT;Ot{O4$VTFU=^eC|}BB9At=kN~!)laXR%YnA^z)~I1sP&|Cl_0f;zlx}i z5$M7k*ZDCz0W4ODn~d;Bl?N5x-t-foaF7)qvf!~xf%%o!7$Hl4^UE$s5`og#$xQ=m zEZ7XI^|C$#qZW1@o!vv{m#G5hdV)-dGmd(xtM!!8X|lRh3Z6VJoVv0FSTNh@XBr8r z@hyYUD#ZF2Lnby-;N?1lwf-rp@w!%oM*%3(0}-LZ{BFM+C1CS+Tez|@EQblCrK7LK zzj*sYC-jQe(^ZN&`{r;(EKXdY#uN}QeuXT7Cv;Z$|-2CmcPyY4;-#UJKp19!KCwe~g{FzOC^X_7)S8@B-7dJNf#aHZ-JvxpZx;MY`c~^V% zy~>9+7W&rlJv_8$wzd~~TmH>;96qrA3m-Z8JAe3M%g&uoGv9aGy89ZGYR+S%&u31b zc=^f=-*REl{jDEKe!i>wp_%JRB#G*=R(CvR;N|l`JDdsL+&+EdOmYh|VFX(kksVw2 zf7@Zh6JaLkL>L+4))6xq(+EG$=;Vrc)t4s`J47??}TvDd)l!FT!Og%=SY`}D_ zbP-8vePVWb=J(tSM716`3+)mo_(?t`I}t8VNDN<1?Mwo~99ay4r4tYiTGE5c#Q+mR zOI@Y6{6gt7M-9L@4Ga+Xk+y_6WbP9Mqzavr89Uh$%?K`JLaCDQdzuKHZH!qk2hu!p zmkwy)bZX<_*9^N4q}s+6LMFu=eu{VY1b{QY!sH-t2ITj81>Z8D@0`U?A>{Q`XFh#6 zA#$JqV1E01N*4P@JoFP`qFo`hslE9-kp+=)IGBXCinAdnN)$3#6v{IfP3ZE?f(Zh< zyk5-RfBI=|m&3@@^ozR8?@Iz^s+=1p{$(}EtnpkAZuDSGE=x>*f#VtsLiN;f)-P{Z zgoeyiNhwB8`wWmo#`k`M-U50xM1x@K!Kowl?_MuCOy#7E;pMP=qwOlfF2_@sS;VDB z*dT`*4*$_;!3bTIu-2_bu2CsjDMv%2RXwp;VlgwlZ(U~T|-+*a3lGNGZ z9uXuXk)!jyhO z@t(zJzPfnn<;AJj932^N*7MD^t#9%kFWrCm`jJz2{Cw{NHxK`f@4ZW(FKpb<%V51H z{G}r=ZtFc(Em2l!XK{Jot=~EGls=DaZ~W9tXMgtMLm$0-c4PbXeI@)y$1kvB*akcA zzi|KdHd|CL;nvrd*KhMsw`&j9ML)%Q`0n35um|LCG>Scc0jvUVZ@u|m086&M3;Ijn zy84|9`Tv02oU*H4d2bDW-RSE6v~PXw%$eiopTFq)ZQbFOLifYm(ELc^M&~J8S0BFX zn}PeSx3lk?eS5~r1K0OPB8=)Aqv&&s^jY!Fr+~T%%d2q3aOH#4&a5+>IUAq5Eg}^G zDjYBa62$#DiNd(aSNojssNgtB9R1xPw2EFl$Cb9cya^zL+ zF(_we1DSQ|` zqz@-T67NA~Sp4Auw$X&v+8H}G^zu@agIz|cl0l!{2=QfgS-l8Uc$PU)E~pwodJ6#S z078QAvmwgm)e?IxUby4bnBX)wSx5F7AiXl7*DO&5z6i|L0i&NYH@3bu-)q=`RrqCOf@LtP{;&JRZ!V_byQ@0F201#lZLP# zeJfNg$dHkMnUYQWA)X=70#pPa6kq4s54BYgi?Tip!e%_R^m>8NeBc?SBBAq$cFcrl zYJ8PRCKFUWCaAF?MOR~5VcEf%oFZ&Z7W>lyw3G~VjiUn`M)nxwPbp<$?te)NnyC*S zYbD%4z2^xiIrS(oM^&Wp6lSDPcjy_eRXrh>+WWdwX*tt9sKg*L#cMRtSz_R(-lfOT zI>qmE5;D}kDf_6d)pF${8`bWhOM?|E(rk`TaR+3(sW>^r=+$V zucU+f@xJ)wPdxU&{Fi_2@BZe;KK$OZ$B%66O7kkG=T7kg`1vb~N9!HXR~h%FhkfDL z^S^uFQ(m(j{i^4mx^(W9N;Q#qaeKM- z?Za38#p!4M@dHnO>+ogmptCm*y&mrgZ!LHJ!Q)@#*H-IWOt<#^tuH*Wxw+7*@Di;9PG6uiiq}H!bsS`raM-Ux_#4@6FcIpSy44b5CC7 zd5=RktZ~f8!?-%g4URLR2R1gYUcb4iUrL^P8P`#MAvS z5i`7Ro}ik&o*Gu=_j66|&(_odNhO+2Wo>z`Nh|OiQKb@!| zn++;|n##E>7GB8B-x+JOR`!I|%77&hqXT`WIt*Aq_*(qI+l&S99zpmlx zfLQ{YBB+=PL@FOvrLjOdqR|1d>Fhy?=aPaI;RRFB7(l>BZMzW0#<*!2SEdZ+>qP?n zvz#O|8e?sd!Ea3n6wU{iF*e>>tp|GrXxP;fkf4z0jMp1o1M|kSyUI9oc3}ZK3AtP? z&8PvkG|Yn%4bUk?Kee+TZ}RA9r|Ld$S z3nNE$!6S+Fl1PXIznx z)HZM;V8&Wz1leFCBPX?2C$1RDpleZJbdX&(1{8-31hk$B9eDRMiOkd+&n7d6U>;Bz zl3AS5)9SdEtF~tzFtU5S@Me7{BqP-{^o$!j>!<~(#a6o4&wT9V;A(4{eLzdzY zg~_bjeAP}z=mh=5KN2yhgG9y@IPfeAkzI*(!8ev3r1c16kpo^zV9b%L^-v52&& zvXHtADtU>BsoOL3m;i?8feI6cC6b|Bgp*9Mfyi3kR-k@mh3jo#p1*&eI34{Ql|ZK7IDd zuOGRzwYGEi)}f7^J^M!3FCBa7pPYF*8|fo2-2dV4KDf2bPygyydEdIdTwiAk@5yoW z;G6Qr+n=R&y-Y@eKGs3bAJ|T|E6OP9az_m_Pg~aaI$A-z4HE=duki{Mz>rX zJh1=L75#E)A-GxkliOzouzTVGL++`zaKFt%v@ql-W8FS0bPxax5d#mIlA^Ei``mZp zxCdUoCghqMdkUb&LdvX3emJGD1_sF=o(qdu(z9 zfC-whO#=@l8nMz(t{mp5bpm3e3UhzFzJy@*jtX)X&Cu3FFs5g?MTZel#Wd?75pE|D~=|2hdukBg5nIb!s*G!Vyg4{UEnHj}3h~Q@l zk~w{LgD|wHVIJkuZuA5)^`H4nC#^Hhq{xZdn5;rfdKmL?5v2Kz4sik|xL^vU2=MfZ zip^o4;0EN8K_Fbpz-~9Y@Tc} zkf1nuAUTS0dps(0>h=0shkR*}=)t)`3^*DAW9u(?^zcw>J=tc+bbg12#ho&J^pyYP zv4g+;5B}Es-*MWgJvjZs2NwVD*A`!Uc5&wT9V@m6^lwlKy#rh;wOIUE{{Zl-)OvJl z|1ZDrs6KD3ZT{iO?|L1z2Q=yVg0pE804=zdhd zG%YxG>-X~!8Txs-8yp$dlDq=B-hRFseTxifo&O!+q$h_QWU{c7Nj7??OMd`hEFM&Pqtha{)Dmmq54s9Mby9s+8D*H@!ZLpS47b|bmMh_K7 zmp85^%&WVOu7@9XoCzpExXKzLJ;WR@aP;GK-5$VUyO+rY1_o*n)#JjEPS}MSF>v#N z`)LXii~=e;OyJ#!7KEDm1i0%!*w_Z}w^Gvx96ktq$ZfcBbR0j&0C=RNwQXkjv0jPD z*#z{niwhBE?;rcST<3uqJn=$J`6pqPLopxT}}E;}AwwiUkyn$pG|`3@|mE2FZ(H5*IMSbT+BI4IBL=!ZeN} zvZI6dwDcPaPXDO4^>n%r4L^f~6tcrIb$hE^H=NuR(ac1MVk8*-alL?Xf=X;79Uynp zr#;cbIm;Kl;fDq~4(#=~u|=np3m_xI3^u;(MbM}awhYOXgTt0dG1J;_@fsvp<8`g9 zB#^o1;p?n&2&SX?8F-p*l|4r6@Dt&{+4G%DIYy!}ZO7=i4dF3yJuV_M`Z|q;ak5VN z(COR8yC1vnAN^N<^SzIsEc(5;=({v;++KY9yuMCd=zYJp!f|VD>%V*3zs}F)Xo<2d>{<*Q-)*L$B)ga_6}NSO4(j z`G54_lV3RY!j1JU{mG?6+dtx;75eWV{qp4ve!sBx#&3M#{d%3fwp{Xkw)*DhwS^|H zN&hQ>kG%EX{#7gVH*57>(0h339bo-v@tgFx+n)sm*#{^1-bP~({^SD*M;~368{Cxy5a@JPh#jNOFcydJ$pd@Hqp^uYq`+7GcSKl_#BGQdGX(9FDE zQDt~s&XgTOc&0FfXRx_AagB9M_{2ZQhlMPK*J!q0IIOPH8IBQt?_1D4Kz-?%vZpe5 zx}wonYF2&W%2&WeFFsqS{-^AOzTy7yPwc^V?|D2 z!uu>YSz&b_7$C=XPFa`v**@jny z3oJcCwWNnxFG%`2^DID_roo!XEsdCD@= z6J<(6yUdQWHp*DvO566Kg@MrS^Rx=)TWtj`)alMO&35|N-P;d z1b-z^4U-=2e5rE0R6hRjssH*v{nZb@d(YncEn$m=eiB%30_!iqJbM4I-OGb79ev@S zoq381m&;GQbnd4vKD52f)=sNaxf=fJkM*6kM{gX}A4dA?-+$*5S5Iwh?|c5h^_xq- zCk%_Yw7@&xKXCnzPoDqu15f_R@e5b?ZQi$e;KzLlD9;ZC=$Ai>?X7m`?ex8U0jysEt^ZVd^ByOT?z?n# z>%ztHzXEJyZ|1wzl*h~bQKN^@bX!~Q+rR$u)$81DeKfGI*}Q|E0WNK6U2LwW13iw~ z*P}88KeYL-?uTA!PHLS+pno;(`>n2dR%(J|_T3n~rb#?KFPOvH90OqX^^A3!q}w(@ z!E^t21rF|$0;+9#_Hk3V03T@NSGWNaK3}D9He|FvY0B7XD{O$!lL`r*w9fQ|-`t?< z`4M!tPB~V736`Z$lUYo!I4j|t3b{*_@eug#!9Ek2N z!okNdOk?aKG2S#ufFbK`pHa=y0kefGEu+_F3T?QFks@dr_}@5nxpoAigsfj#5}`8% z1mFy1*Tu%_bH+Ifu0batT2q}|P&X))C8s9g_rx*Got=1%r+;*{k3dHNW>U>)+DE*V zKm|thCK7;IK6=|FUx-ptPsxp)eSuifcb+eY6B-^D$r@s8={A02)^Oowq}|X zsy2}3rkQpN79Y-3><&h5JBe~$d7QwCG!CTC!5f$pXhySV;_%2=o48UKZ*5afXO$xy zBuk$`%=DPcwxK6IY{~A`EC%f8Kxv;@aO)sL)t7lHFQJ9^!q^Sg2Q$oFJ5097OVLJ` zQxlvk3uZs3;PLukYDJo}f0$zc$=MaP9$SSl2)y$EGfOk#sKXriJ(oEY?bcOX1ML|Y zXP7;{!0`bA0-+gXSZu65#NVjkN5X&ucSDn_d8cb4id&bB{rmpjfAGsc`{4%;ZtU3) zlnzxJ`}mEuPkw)KaNk?vP2m6Y%+sIeTcA1q^7r2P(4`YMH+ODr@*|*pQ!%fEYby#+ zi)HW+J?Ta0LpP6p{L+KJ{{46U*vt1F+}x*MB7J?|7F%XU^!$Mve|qBie|+{^e|YM= zewFme%>&0@#dk;l-hI#h@yQElSS~;L%p;F||K#@0a{oU4s$uQ6rGEZ*mf?pgeMNxY zN!APCx8R`-pwB%#^sss}{t~Qt2OhqE;|ot-UH#E$Zf&o4#Ho#_&)kQzDfw+!`>$QU zxuy5nXGgXyX9a@K5Ee$WuK=->)j@N58!BVcIYscqG3q0^V)UbY_w%n4DI(7c;x?tv zeOEwQ6h;*ZxM@_zB#e?ePfr-u0e&*gkV=!hz~Iq`+#pJi%*Gp8&-lfq3r;RM0>sGN zsF@d&rXzrooX^1w1DFXi96Gof58Naemi{GJ$)ZWVNHt-zLFcFLoXj2#qAk4QMc<@E zR=0d>W*Q|Ta=iT*jkAs-2%#MI$yoU!!G#0~5dutE=xRFut6{Gbm?B6xGbJ(cMIW`Y zSx`z5aA?SY5Fx7>)L=XcEUX+%i@(!35OC}(6xAt1MmtK7X~~J!mBUl9r2xEOpx0H0 z2bxa}j5GKI4tUe2OO952$Yyl#i_rW&dCD9n7iaH`j)w;yL2~XX30iCzozehY3>+mV zg9uv9?z~=6BaH`Mc!vHr%0(r{?2xP)7|7-5c4=&5N;2MskB(Rk0Zy(s*1;NO%$Pxr zqGAGZPiNNxBA^MKy5MCe0f|eTC0Z#=8rU_t85u8k9}#K?CPz0N)53?aUj5ec?S_~9 zTCZ@4z{#qyBOAGVh(9~TgO&9qd%7c}g$Xk!bV7=bUl4m^h|v+=VdkeR*)TX1AbFnK z>rH~O)=M6PfEbPsvQDIQCUN7_H77tAjw*m@?_N1xi64}Y+-DpGk%^r%C-U1~;xhG_ zv}rh8kueH%=23oXG)0g@VYkb2rhcW!q!~YSrols z=$V>fI~l9q_{>i<#md*|n71B@ac>C(<`spBfH7rIERz~rhMw81gqfuqApX%GZ!OCj z9-#I%J&Xj_4+M- z^8ucNKXI@UUph>?&JrY#X&5vm*o74+9@Oa7jN2%#`q5aIC(~3c!Ff4?vAH za6aEH31pBhFR=M|W(+E~>nLbJNoAVc;+;Tq^E)v)q4LSuEXeSBCW6`Xcy*5;bA&ANNG3C%?lRME zw;KzYf3K9=B1(3cN2E+kVuLjmi@Os_D zF@lUY0#itO+6w`(Z1y)l>@nzEAGNQ9)JNmd8e}KHkE!Y>9(F8Xv-kzE#b7+%<&MqC zVWWbu$YU}m851a+X0TXe(Fa!jOtjCt+=h)))H1aUPL21q%CQrWyxwX0IZOrS z)%+OPx!fz*Wku}^km8bc4tyckt%EmQ= zB0Gb1VV@l-A9i~^H6AUljzKtV%KFXmZUq=CY{JZ_Uyg7v7$X9h=g^{S5KFiFyREtPsB zQSbBUOHY;I|) zH-vZeN|=>kHOI{%i~6e03cLT-p&!3|_Seq8<0mgacx-dy;=Y?#_WRpPYge#OF73bd zh2t;&ll!06+q^ICzj0MefY)}!gh&0E~?`sONB-EVD6+_)>k;@hJigM?vm1XmsA3Pl?* z_Lo;vM7$AZelyw1lmOEikuYxZ2=a-GeV&i6x5E+@Dav}oD`;3JK_g4)83IUN39JW) zlfw}j^fcZB{GeJsI83qxXtxa=iUpQx=oDZ_d}N&C2O9%(hu(U?VkLy5{tQwkBXUgB zIHgwvU-Rg2AV`eeDK8*8rqr)v&F>82!d}lh$kAb=M?Fn{R#e6n z(u9o&GZ)t|PJ`}eTT+klWL6d(#R2nFnq^=bmF&*a_q{#?0|i3G)yz@kTeyMyAPIzU>%*Vdo`e7*cbq7 z47~9e2bMuPX~OEN-GBmgQrqJ2dKI3rtVJ4iP8vUF`15#a+u$1fDJgb^&)3WRD4|J~ z9>7Eryp_m5ljGEu&|AeEp_&n5H66^((stNtDcQGDD6A1;v!%aH6mF_GI%; zj)YlhC>s4t|0u0&C72n_)f9YLZ8Q+u{GfqmDWemVu~lb3_-uMZ&8}%Zic3!~d)fui zgi}OBC28@47)JsSNT2dPB~_rtiOWhM)rSNU3-HjK-`;lRxX}ZJ?J;q*C<}m*zNVL zCg?ybi&H=G&a=Pz^Y4EA+)=$7Q$(-B<)PF3B=GZ>7jHZJIrQbdClonOH z>q8gLJ@L#rzQdCjkSwW|Pv2LpH-YsUn0JHyr*ZWC;ajqA$(ds;{%fmBuW3JW<;-8b z@b;g1>A{n?4_w)I>ymz>Row;HRN6l;uiw_+I{KY6Pyh2X&s^BJp})PPUz(-O@W&@E z{NCwjvY&tQ{DV(Cdq3a*%&%F}o7KDp?D*HF=dNhIZ>j$cd8-{-+ADkeJD?Z*G=aXK z{LOx7V?8weS>W3FuUOQsUC8Zs_N1UcUVU)m@|ElQiTm6YbJrbgxxHtT*H}Jp?GWcy z+<2m)?_04SzJi1GiEEq{k^mbWY;#i^y@Ds*B$ZrXl$0~M0j%WUu991Ka7LCsYfUoe zHQA6CLOZ}jzl}~%j#)b2!9Y^Zq>6@A*Rf|>(W|!_M;U529EwOiO*`gr1@rSlV3x5iZFpK!hQxpt5?ZwaPTwK}u(Q1q^;I52-p`uU3@; zY#buBR2kwXU3J!=6h%9G3O-_NNu>&N(l}NG1rV0VxEN&HKWJZ zj3LD9fKgG|r%NG}LfT?xpo}?{Ep2e=U9c)oIu^wWA(<(%AH@}ni*(TQg_M)b0)~dJ z*OCwxIg}!J4$6vVp_y=`y)b7^mXQDyfR;0+;djLRksx{mn7#NKnO#xmN<~uARk5(U zTFZhYO_~)@0!lv7PDcO*yFVeH6^O@bI8{2yDw`h#ZZCmUBRw;ssg>qP6i^?s0RYcX zHsdGBEA5fn3&eGX$0!SgRg#&4lAeGyo%1Ihcv9ApDeMFj5LdbsCJ1xT7VANb)0ceW zMvsf55vB^51mf~#Wf3c@b$}-ig4|u-UTTw+5MKtu>Ro~CC~=0S@OpJzryd=WAmh7d zkh)w3I%LyrLGsf6yi4AsxFhTIVm+~v|xkLxl4 z4c5v0SsciiMo*|2yI@DkhF{}OKst|Os8yz%#6vj8Lq^L>kD_E42`FC)#15T4HG@AU zBw!!#LMY03{J{eu>kOZ%ZLt?o>a8rSb+K0gl+V!NgrxjYb)`ukTXYNu=NTSBvjHzj)-n=(-2bUpex^n%*+i*Wk9b$-7M)te zR-9%T#l|^%wfzFxrH9hlGbf(?{)?IWt_z0enz|dp>1ghKBS8`CQJbV83_Yg0-%j|t z(I(DHHLNwpH{EZ!)$7AXfZX}5$3}YE-Eo>q(eNfO5?V6gt2yj`0nGEXe=prS=49CD4 zAaqK@9SD2|8`8XY3vU%>i~QizXVXyuhqIN%Lad=2cm7F+3Gp(2RU@avay+6BLv$)03^^x*mH*Tsn{K)kK z6&4&rJHMosXcz}5viiqlA(ZD8Mr+ya3z0j%dKcx{`3k2^$X^`Js z-b>ETDq(8aG??uNFH=I52sA_kP<@36vra4g5>xmB0P?VxQW3pddVOK?(wTDLL&UU> zN?P{5Kgem$WX`Zu64wRH^vIOb!b{WqXsdc{b*>^4hXJrvGTgP_SQhfd+t-RmYqn>L z)V2FRh0()moCs>2cJ+invv(rq*0Z|*2W&QIea?~n6ZxhnjRT)7OikaxV-E}&EeD)C zq6l{d$JC!eFyAV~fVp$OnXURaGGqXL>Y8)PaHpO|ujq+JCG7q?E{UeCXxS;IHc9B~ ze!L=xb{dbBfzI$}2|ci_T`t!2OQoVc=9mBg zKmbWZK~&scUI}mOZ{+a8_|_J`D@*ST>lO0W)VN!>}VqVfQykY64?3m4A=>hjhX)0jU@vj z?3ZCxm^}7{zc8RWBTqdh@^jXB$c^G6GIo&+fD_HW{18W=K2NY&%JE!|=#>O1*D|Ir z3{YtKDT)Zu&cA3;0D#q%AT>>Jf(+(rNVRgvsUu$xjH0jz)z5bt=VySYNFg*Kl!1X} z&OA7~N*-g+%ZPLiO*3FT6_YW(_=O1$d`D8c6`;__$lOx^EhpJ^Zi5i0C`3&P1wa0ZpD;FZN&z!~@Mg0!(H`m)(#$kA zHwf^ZXO=>yR7Bo$+cinlMp$I&JPuE{h>i&gzyN$Nl2_ALt3fP z#p9mJZbs*soSIId%9K6e3d(~!L(qkM_PomP?5;pkN2Q1)6It07?D90OkZcUlZW!Cu-mZ8b1_4+Mym> zPsu3iq9dC%cwUl0`T%RZvl!ZV`NP_&nHn#TuHo-2Olv#|1IVXyG_vzXSh!~Li&+;h zxBY!WK#z6h7`o-KJG7N75P~X0WRpXI)6=yznj1q2fAK5t(+y6qA&(qf9zLM=fq4O}Un{k-UxTIIabI88Z&#)p+G&0ztnZH2E8*p> zEq{-6-YyoY9*q7`VKx;@%gRp6`6`;HzlWs1pY*909{rUIZ##GE@U8W&3;S>E=)XG# ziwFC6*8k3zKXl^KVZHobTVEXBSRUM1-r5|XSCQ$5LG*ttZ}#6^{KHDz?bm;8yu8=n z|E#~Ie9ycCtbXa8+cPKjf9c!T+&k`IyPLRct}U5e$pByNQQz?n9nx>Zx;CCt?e+cB zH^h!}r0;_A)!mT9_5<(d-(;})Zm%z_mQ!nP0t-XX@c3a{&_(9R{?kh8P#fRQ|p=HZ4Z|toeg%=8P_kzEILG{hcPWePf~KBI@4Ig%DBvtL5w~P zU)2ZeNW>W0z`+wYKA_yGp8<{vVj~Q8zc_)A0S!@T5i|#jS}CWmCYy!K5GKw#rvC=8 z`0kstSzL7J+(#B-04xV&$w@_2LMEjH;IRQICiZ-BJTHLYflwml)RaI5`Dy|krZnv| zG>n|p7!%Q;0{hw%7(-}yrdBCLf!wNDKoLThQbOE_N~Gzm;(2xlm3WE>zh#JN=vk#V zC~h(5GkH08?wQ3ILl0^8$(-Kmu-A(dI0vuo#T>m|%pLf<%h$Ff!g<-HK8i4zb`eh7 zwO=e%QM2~9lDs(g`qD0?LAon;5sVdGJ7($^G#m3oh97J37m#TlPe~vg3kMvI!aEiD z?MWMHZl+G2eBcS_!8U9}-$H*y6}75O*y z)AfM{8KH%;Ae~wr!`%m}IdVlj!6u3$&hQE~)l1L}uIyL<&=!rOJZ5Nd62p~gM;Otk z*zK1o$eEsUJ4^h@Vj+Xv@{67g5V|3ZT$3JV2y1-ZKW*;QjGjRBv#(r7`d`sgf1rfd zi4f2T_hrhL6j2z$#5JA`-QJSvu83h!4?Q&q-olb-5G2Uw-FmWMRxN+z!{BB$u!ADLU-GA)xYxuLV zPWPHmdK35$^Cs|plzNXHPaV4Sf8F=AUaP9BPdtD2ea}6pKU}1rdetjQz3A0<6zgYc z^_!*ix>s)tAK161-w5UJdDe>={hTeYgtdYS*LNW6m9Ty`Sf9KY-dgHshWR;R{Rt&K z{Irn)R`Xs{8xL*od-v6ozx=`@fBC{=kK8!2x!8XG;0Vglp9R+D zo^ErmxSZPh)BV(s2tO#+{j|umLZS$uu2uAuE`&N;7TJU*Zq^R>#cU9HKtO*Q->1Zd0NcP5mrp0qRE_L( zyS^Sn4T1z>F&NRwoRa`<#{MD(;;4c~N0nq6>jFl_ zP3uH9Ff!cg0<(BZ5?;4_M_PWU(djT(jBUz3WZZ!VW=;Z>VQCsA!RX3ibx90#Xq*Et z-D5TaBGu6os!EB00yu=M1l>YS&4(vPuh(d3GL|lLL5{Ff5sI_o#*9Uw z`QQNLY#0iP%|zhMU10fwFIbWf4EG2pC%EO?+a41PjIHJ;k;H_yzc#gjj3OhDQLYSJ zE>qWlmw`U5p&es=DR#DPs&K%jbY@7#z}W>0ZITp2BpcmX0cz|^&S{0t^Mff=oI|NG znFK0V;u0h=X^WY?P{tDg9E#m|_lkbGU}zaQu`{Q2;-`UWBjYK+3s*vs6%AlAE@{wO zhE)tX#)OaDc}NkGf>WesBeepcHo{ruu`Dd9gHdF-4zNVQpMRA-i|ul8q`*`Hsll=i zel=IN?h~zcZkd7>GU5#lOOy#JA0tw z)ZVJxZ|gUq`#`gKZQ&A?*6;dnIaN!WG{J3LF|kn)w!44(CQV1_s(iSc&(S>1utQ4mFch`oHqDK zE~BxgJe+P&mgbvJzaYcKE4Lpy^Sb|qR=xZ8iyvJ4_8%{vdVcZtSNGen+~ZX9Mn8Y! z@Wpku>bky#`5iCbr`1?n+u66arkB3z{@7D`BV2EJE%Xks_TDys7DzuTys6&~tzV9% zSG=3NUebH8I{UX|@$0g9*?e16^`pXi16gmS`e$_6J+(7(d38>^P9D{7!@9l69|q$d=o@10 zB=wwVe4bb8?mY6rY0^9$Gqfp@)6)lYlEU zfo`Y0e$K~a^vd&{pV?xG8jsCqap_4BOQcy$Y90KPj;$`c-6cp81PTqU=97YSNxvA_ zoxk|rYQBQEU#L(`c*B%JggGZ8Y{{Vj>lqekS#ECySJm<@ z0@eMQYGKJ(bVZh# zv933)?ge>P){B(ntsJHWsW!!EO9@)xcbL2Z*`#A>Kq zc;T(}LSwZ@9@5JRcUAxsw6J?)fCz@G1Du)&3(|RBW;DVXyv`wm2%G*vPl8IV5f*2n z%mj`>2y9Fu4I@wte9&WYR3PKcW489qo#%~$qCw0n6 z`Z{+%qbs>*`)6Ri-Pp912>hM>Pdu5b``u5OD7*^rxRh1OYD(j!v?~%>ic)YD02y?p z2MX&iE`n38zZVucLdZmtrp+LPDk^x8W}{5dt9UuT`@PHGc>2ZjFWt~z<+1Tc z{3WFCzQC_Oex>8)?Va-%x4!nw<{y3i_IIBjeK9T z{j9IPRn;#e)BBRjO6x_YUuWt~V7<|*Z<9WDaCzd;^5o&Q6NlIIW5fQgXWj{-ToB(x0!X9TIZ-_Q9jKHxz!GZ@Okn zt}S_`t@ouRa?f9^s*tzHq5s0TJpRV*-qoxZ!1v^F=)l@9eB?xzrn|$+Lk9cYpsiWk z-S?3h+?$r)hNZntl<$bX`HkCc?ydqtf-4xzzHKU%jD*@@Hx?r`h&34BV10k?T)J|A zPonUK(`tD(;b?k>Vl#cEjwJw}OAlQB5V-k6=8Q!zLK!7f^UgS-7|H5<9wMKo9w!PO zuZ;}Mqk$Vys?DE9h=Y8xU<9W#3F>N_CKZX#8G|4XKoUX3!SfgDbyq_Uy5v=g_5G*b zn~8B)<;>X-D2hkJhzT`e#(OGq&x|*h;Xp{AFC~R!FwVt{5=fBPV`P{(F184InGv2r zsA8c9<#$S8Mw&Wth;*dRmhS*FH@~ ze?^-%;t`ZJ3}FX|FCwin^kByUz=o=TaQrrwoB@{4p*oNC0@%6b#NUO*MRXI|9nc_6 zb7~5e{EhGHtQ^X&EV&f`C+j%Ep=smdg-e!6ly!K@LkYZjeC9Okr^{7vsjG)xAxTUm zRE)_BT@C8?LUi%lwZiWW35!LtOIbCJ@c6RIFWRZVmHnekjsh=&Jit*mO;g%nuYm(f zTz9;pOh`h{Yfxj~5Q?$tWMFD|GZEGOcZS(XafCV82}+O4Z?SUYlWX+fa)ut3TVQz&WvGDC(0u`* zW^Tg#`OENea&&Px?JNPABE=|=tF*+Mo-`9bHRl7VYsip>ToS~T5y2W!4D+PYkWXUA zVYmIVIw~$A3@?189kJD>;#X)g4l$`Z?4~DmVaQ;7kCMp0R8;hcjr$ z(k9W)1We;L&Xb^J!rN1@sX=8eO)dZo0u*Y3h$+ObOK_aijdsUw265S6Z0;&}f22K? z&-)Eaxoa5B;E^Nmq|fS2Zvn|#cnfkZF+>d9fl*wq7ginKh)Mw>m?aQ*XtEQ z3WylMNnm6)_mHGPIZFuI7V~uAbbKxP$D3dH}!hqvR(vLpqv~n zD4nc+T5OF;64clvRKv>VY?|sY<UTH4_abj;&XeoS&u3nE6TAuh?7^$I*0*{4cW0^Ze^w28?>674%wGYnWt>;GG8RCe zdL^vSdQW&`dF;^I@k7fKN0uiJFL_URW2s-MrEi25QtvL_;`Qpb-V@eu{JD5-`_eVu z7QT9Ohxdf@ebm`ZEA3oKIwtz{yL`K~{#uWJ5ic*rm;5y*ZInI#rOomzuiGa0_ z9v2>So_&J1+b64xI$^|24K)MKV`d(}XTMy*`EH^@UOo1pBG-RV%Y5T_5H zjqWd$%N$MKK!#*(zUp;cO%U?gO&mZFR>$g#xc&6GufxkbOZETPUNjOx9~U%nH=u zL1}>7spT^*39GsW*A8H`y`A6zB85ZZH@T4z%OBr0IEM7UitVA#% zU;WbuYG}yGj~l3NM6Z*SXMkZ8EfK zZ0AaU%x=%D9Px`l*4RAokcxCT5h7f0(}x9rwtKLRk7go#fN>$N1WJ8GeU;IA5+ZWE zpm}08nzcg!;pBdKF-^&cZTPS-kJEt@C6_V}6jm;f>i?tR)FMIVZ*@qAEtE$s-y$QUx zhvePczY0sg_WAnm-@&v8E!3;ud;WK5A3CtEuQa}ULG8=^?QVUm?aaN7EzSd`;dXK2 z=L>k8T)TdAJo*^;p4V{%`q3s1?y-(Dt#6D844d;PuDu?{=s1TuJ5vq(z%vaq|0|nq@mNoLm);w)VF zDYWy_Pf_K5VzDH4qEZ98(qX3&W2-R6S@=}sG6z3++Eb~GXHx1@Mp&FTg3>7`HZme- z{ANu+G1mpSkEuVJI*qO_Kpt*jWJ+5ysIa}5^ zss4C@htkj{!{`rF&}6oJKa{+)j7)S3h(69HNR3`FgUuqIPzGhWaZoSvb1U#zj$TmL z2CzV_$EI|niOu7T5mXCce)Q)F#Au`lo&q~W7>2HQ=)t1U*oALB9&|uJQ~%3OsQ60F zj0YnEOv~61&nYuug-5l>x3PuM24wM{+XU_3kV`^QYhW+rN5w zV`J^%`w#8;OHI8t(~t5#b$;vV3tP{=sF!AFTU#E!y|uofcTGoinD27rP2k7Q))zl_ zLA(J>-#ThA5$?Tc5}jvUxtZt#P=ul2}s>8u~gRg3uUXnm{m z&QdRTxA+!leq{I7)^d}VyZqv4{TQ%ZTGX}MJ2%$!2ZtAW<;;0KpZua}y{VgK_g*Mb ziq+edqSZ!PTlWtD>$QWO`qNE&erQ3j-dN~w`P`F-{_5|wn|oiG*6!Z^UxU%IkH7Eu zm!G<({~EJJH;dT~LPHsR1HqhIiEzHFf;T*V%}yUbdinCT{zmA!-|EIn9IR}3KbJ7@ z^MwhTcDn!fEp-;heb^x*o3o2GA~oP3B7C`_D^tjZe9@4;$_yUP!q@Yo?ZAWs&qF<7 z*!X8b8d3>U4%=%`G8|Mzjs1Db z6tGdh#-5TTiF6*YECYnp;VKP8hCfMaG}D<-T9*LqrZK;itnz0HKjBT4K~EEJ{xVTu z_~%Ht+@Q3-GXb>41C1+>Ld{%xb(tKUXVn7I1-RXlV4I-}ht6L10uaT4IRhnf2Rmcp z6C6#!XJbG+)(g!c@^vQ1*_rb(*2`&od(=8uMASwP`^1eSmQSm59?Fd&gCVROh^}g! z+4@9a9-WN$hP1BYFFVYpMRoB9=Iw?FQu&4;F+0le;ulH$GKSe_D0|RX;dF>$3~EX_ zWe-2m4(B9168Wf4Xm%Z|jUs_92>}aV3yrr`gg^P50XUh)*@Ll;(|Q?Fr_#H!TX0E+ z_fN?YOw~{f>z*@0?DiFz_7IH>!-=TJoz38hQ=kdWK($qk3CH8w>5Mj^`)w?=$>2ez zn8X9Q6GT8v1Mf@)Girt>Z=y-u6#$ryB+y&~cceOysU|JJRSM<#fHRN<9J_-&0P1WQ zQ=7QIRb@6+Lrpknjco=Hp@P~80%Rr-G!6&X76))Lf8zxsV&Dl#1OuCmFMGo5s6^}& z5KXvi|5(j%S77Qzq4lIeMq)bD`4vF}}f^!T$c?!0(;TQ7w4{miG1{(tPf z*|KKYb)A=e^*sQJ4M56jAc|@zF>INXBB)R(LZK`9%6bLgIYPIN@B_&YV7-9DvK?Us zMT#~hlK|0>Kotm7-)E-B_l>#M-sfayH9%$&DAdYx)?RDQF~=Np?fvin?A(8IekJCo zE`Xzf!+--LFHXLG{cbLX`6gk$ONstw-Y1+dQUa8n%BNxFlbmyxHP^KK46yg!+jfYl15c-X8K}RG<-f<9$xv4IvbBcJ!~Z#8bbT%TkSyp%0 z;vXJm1=$~i6%d$vXaAv2qO8yLo6moJFVf~B=hlU41%e}uM+J0X*a!y&d*K?ZVwQCl zcOPX5^`r^@R1^&5S^a2%p6qFR5U}gm#ho5Jj3^OK$_@g~zl;3i0)K%&5wlnq@QW&2 zX@RYQ>=*#iH7k;tXwea8eaIjDs5G_#N1fx-+-|6M0v2Ksodz++;Yto0VlfI|GImlI z=(MMT8s9~JINHM0^*OSvWoVV;Tl@hh!|eB}+B~zKVAD2C`8}@I(N)0OU+044KMFNg zE-Br=RHPghz|~h>_t&A6C0gqc0EZU%bSx+9ck~j)G3!8rIdX`Zb{s7l;M=rodFq)2 zM;S4bSm85328}+y5-4a_P`{vam%Q+^9}?BREZ7&>FlQ>_!tv9jiCOre9~o|jzl&DC zOb}8R{0+xk;TPo(f83xIpgQ#^;Vf3ZbzH%|_SZ@X&)RDR16sRj4`9D|d}beE%0Jd? zXq#F)2^x+UwZTlp&`KdQMMI{PiCP-sm=z#AO`2vV-=$^JQ9IyKlo%^jNf%8|CG9c? zO%5w_esTScxFBfsEFtJgE<_{N$~>T)!`mzyf7IKgJYII(ENrP}A)0;DCF+76uuVL` zvJDCGrF--ok){Zf^;sSk+SG2{YxzS2*E$k{@#w)wz_I>|sd`Gsa;chW zC3OWe)2AJ(ja>NBlPs2aqrZbg&pxUvh79-76Qll}xH(0WczkkITA|L|1R#?3HkC^SWDe8Juqw&P$`Y66ST$UJU1Ro^u(@9b@+i57J!R z`VrG$!vFZK+_mPjxc1d)kdNYBySWDbJbfBg-j)5MxA?DwN73@)=g;wHU){T6el75a zue|!;)yy$|ZaHu{lWAqJPi%Sn!1WJ4yuEG$?--Fjp!#$(&v(nePRPLgBY^?*>pZ-k zA17xV8+PPw%zow_k>ud1WS^fg(2#@Krvp#koH>CiqdX_}@rY>^a6$zB;0K_kOg`_7 zci~L{ig*FClGtdge4187>RZ{0Pi=+k)t16+tphK&V7FLU3$C61GW3Cq6bt^6$QJz(vs)pq#=?OP!Oa zY|Xj&SXW3SvJ)S!$lPmGbU>E7z$QHQ$Dw2hWj&3jg6`)@d`gXI^7^dIIH7T)WQ}`J zNT~=N2t6Sh)L_PGE=_C5%!+5ZCX0Zs1Wf)LM32|d9Z7_EM9N-zgzg4k=c{K`S2LUR z3EBH=(k9OwAc5mw>X|r)M*7Sc&?gNE7FeWMT#MTwgqKEInR^UaM&|Kq z?L0#sMW=Y;zyR86#;-MQp6t&wKnJ@MD?a;1^1&KH!=IQN0WY6O64YfHdi`bxgW6C@|1x{j-B- zJT4(3S643kV}EV>WIXdvR?rOL-vCV{#Kq&(SpA9tzir5&4SyfkH4@H@r<{zU40 zv{j6JWU_Tbz}YJgW7+rq66AX^W*AcKn$jok>rWCtFPh85n_;}X}a~dhq)Y%kT z6h`Wu04!woH50{L>HTqh_Cf>e}yr z^MQZG=1T3I4{l_K@xe|b>VccS6WFV}2Vy=mM{aKa@Xfn_{=?hfeEIe_zkmA=p8SjN zKL6_NJZkS;`RX_R%5y(>CLi6Lo3yzuWuIKl=UqSKOLz9{)wvSB!N*7YKH*#m=bkW^ z#QCf&ysYY63Fn?LSHJn}=v>Xd&o>_Nn&-TxIv1k(-l<%u=M~hsw|wvWmP4Mm2S4Ra4ke-thM!SU>qkAnE8n)8>x{Ma9Saiq}ZT zLw5e*<_RqSjAA|zx6X)|n4o<=J%Rbl4fk3eT%w0kw>+dlnB{N0aPmWvCXW+k6+gQ0 zm)`&;JiU-G<`PJ94}K!!tj^{NOiLo~xqd9o3@h2SCDZ78(3}GDj0y?>ut;mHBp=DU3lSxF)LxP3GOl5=$ zIgnI|UJ%V0e}JG2a4@Tq5NPBqvE#`A-Tt#c+d>-N$UqnjQ6EJ}G?;$K0@~INaGqLm z+Yp&58~();|1eF#JNv{hiAl$5x}L^3fxbZL170oj?jRf?g}!d_F>pAtBDz4_!_NZa zHpc)?`8K}^!0vWVNuc{n06R{~WIkt483>E9m3Dbq|0)1W10)6(6=zU>r=kN2P<^{P zL$QJH#C#Q_q1lIjGMRKICNKe(w+dEKjlq>#9FrL!=rkP~jjOBB%n)RXSx{qH1qX}2 zRTC^ezIc!XPYK+iBH{>vYDz7NfTL}~4(#Lgfp$rbNhBmA$l;%<1*m7yD}U`TlpF%0 zm%`kMY{S8fM*4N+IGg%#91n*ncK`j1m>2Jb9&)35a$oudc+y3!NcX`Bwzl^qO-rDw7v zP4^_gi!A|*a0}e!2fE8|2IXA+&i7vX?SJsKYuB#-%2%HJiC(t5v^@9JwS0#2t8bC{ z-gfiaowq;DP2ey*^ef4GRXxa(%f+iZJoU7lf zxdx8--1W`%@Vg)Iy-LxazPRJgoMSc#$mTo>#Iu`!wwd^uPs>mrLX! za6O-f#dmz^BC==QOj%n_xIP<#Cml8h1nAN{&o-Pa;bA&FD@ZHR@-$t18kSmR!|wAD zP?~y>mqFn9J&7G-yy|Hml=6Tlpn4`1@ofzlL^dE&oQ~^}ygtL#B$a-Y zhbe94Z7q#h3TC#Z6JU%s{gclG9m|>_cxmbKi>b%%s*&xm&r-n97|C1hvH>*&i2D~# zesp9c|8PiytKo5(>afIK+dyDyBebbw!Wu(~VrF#wD`$FAgDn3EZ?K+{4`7wH1@7#^ zIIy$pVuZxJ;9cv6Y&k{j-lT>R1s4-H zT_8;xpo%@aB!|#>kfH)LnxxA_xYju0GF2bcAPs0(1q>dj{^EU5H&z2`jhgeL%q2+J zG)Cp$7LL!@WNv)vw2pldbn5w}0V{5?u~p?ZpzuNg`gJR$6)2!a&sWmSQWP;Ky((So zqsQ|h+MOQ>jx6wX*5VjvBz3y@j&ea_*#S#_fen&OijHPp+D%rbNoj^f>y`{AC%Pzd zINInb>yT6SMzVxMFNdhDy|kHH0l4BF^hu$~a2P7|CcAMk-_QBdAsr z-YcD&q%mgr5Dgh0C_zTslQ$X|t_Qsp<D7Te@x3efq&tJYoFy!;M~)D?X5fCd-YB( zdjI%)w_kbnPTt0R@9Tko|F3=f!|Qpa_tk5+uYdjbel2D6qnq<8=oFQ8%^rEwm+tIC zf3l=`vvjT>a_2S|wEgVpyiYiHcjL-W)Z{`vuY%4!;oO7Gr7st^*#$T9*57=gE-{@~8fEu3D3?c%EKL!p0$p z48rdq#u3DP)dXc38s>$4qMUWhgeDB|!fWf_s|<_4U;2$N*L`0C4X-V{T#pkAKSM@# z@{u^!;m%fkbF3nb!9^&pvdqjK@1Kw4lKG<0B>)+dEjdv^R7Pf7{65o%)Y~o?mTUL19tBjT{Z6ouCyw*5+73&Z zXQ?IGK1G2?z_`{F--zyV5LIKL(|1$KE=b3q!#w?o!fZ_^e*YQP|4o>O>p`;W?y`$c zboWvDS)SeCbbq<19(!sq9Ij)f6$KUe?louwiZPp(rfZF{itk>A%bg?CnN`c&y_$gX zLu^}ib6_FY(UuY{Rj_@o=M*qTm6mZTT8oZc?e`6VRf7Nu1VIKK0ZUHj7PnBh^gjS#ICY|(>y8GCnJSy3DSf{3J zMgW7hYACXqPfD7p#~$OfVTOMMGpLJQX@MS52mn40ceyBS2PWy7Yz~Ny300pAOaD57 zsK(<>DLtxJ_@8-5vxRigV#0Kj7tJX9b3=Z%V6qaJ9-$^E*_GZZ^w!oVkw$# zE$E~s5Kw_9Jvv(j92EE*7j>2|NhxIB#f!$2m^y;w^b zJoHVf%e2J{Ii)r%bI#|ZN^S6mw2^uyZJB%iH>q~g&GQj5ARL;ds#FC}QW1-`T!%9B z9BrzR*j#8$15+FV#)yq-x_(_i1X<(4tLIR_w2L^wAz7>4MQHBHriK&VVLk-wg|A;$ zUAom1MP|eYA>9j2w-r1_9#X zJ?&r9406|VaXsVh@}fy{3osH3?YzIh??;Z*ARwoj66`}U^R(0QGhgr-5C1YJq~#JR z@!;14LIu>xl-zCEDnWxrG(i|YPQA09u4*kpjTKf#5)*S4B+Z~F=iUTgwyj8lbhO=P zt{~C6R>2E$fj=6uo{2}gf;xp#Al5Zz>;7_!Bfnj)p%9^*M#aDOuY9q#diyfaC$3TD zub9~6HXu1PA>s?R>2^+UHY|uv@_qwC%#i#lWeCr znAU98IEIBY8U?fdrcRbw&mKPDm!JTQ?gC<#fAnB=-k#N|xNP*5XlB^TP**%-ir4!{9i6Y8^Bb;>;pkOF-)g2%F3+ z!Wl-``E3DNz-ozubU6~}onSJ+5JrnW!zNwqM}W*a16cuvHX{9^)6ZNoa;*bEe&W~i z9vE1HYuM7G8~hx8fM^0MmcDYZj$>BeD&VYr6?f(J+ywr6zmjXG7ar10;1{31`g`BF z|2u(`JvX@CdH+UUO8NFtcs+}lOZ;E_ z_LrXh;WN2hOl+<;^V-Yqte06EW$t$hi_mmG2YI^>AM-om;!HKbE)t z^4-7J^7`l82lkM-Tyg?)!!w0Eik7{fi^*J;-?-=6`%$F(NjP)qo7X(&^Sz__5jL-W zv*thNEnf?qb^gvPd5QVyA%7aOJ~?1}Tyo^vvTN25zqT7UuICQ$yYGFF$0Xko!`V9e=v0^py#-84=G29G?_jFgR68Bu*gB$JQU3x5w(0j#AXs7#s5 zK=_Or-`*+;SgBX$x<G|BCB-u2f2ZhY#HbL0EROvwx^57EPB6f-H{DE5wrJB?Jot-K@^%~g1r+m}T z{vwbf{5|imBasP|5nC5y(S~Fd63^^=jCzxGGJeCyqL18}Y_xd2|cxA`Wg&-C@%D>Fw;e%6&RuZ8BzlWttg zC3?O{DK+NjaesK3^g7CRcn4v~Rdg=@9$gE0KBFtzawYuJ)^gzG68*Jzcq#ZJ`mn2A za+dn}C%Gm5Mav50Ch#A9`<-{+zu&`fKf1DHZ5ePTTc^2;EBN^1kL4?o@+s(ZB8@k3 zgHPmfHr~d#Hy;C^Bg|&T_2d)KG6q#%x6}E|&|Gz{r23EN(**(FT)_LpL{TI))HpgK z#$)hFWZ{GM<8W^$dOEn0d|LfeguLgMH_2}C-!v}Isy23b0pA!!!O z?IM^0b|_>3tOM&tGr3dJ&S5^kGFkO)VHqkN;WZR2r z$)Z2_|oJp1;Z^s=Is3fW!UgZSxKX0>40})2nxnnx=fhbGHX)o z)zWesAzT-@LdOrfl-qz`Zn@xxQ{w__h;eH!xq4ufHS51mxRbLBRK|udc1~w`7xlD6 zJR9F|;4ZKBbA^a)B3z8kF#OI(-$a#Ao@$}TIPzt%s?qPblEfhyUiHgO&Jx<6#^z54 zKd6~!vO#gKdO5(bvtg&K8K(S9!WGICIC?UYUnB;nrzOL?p>Y>pq&)@`WVZCcgB>|5 z0GgF<1nH`MoQ*r}Fyb%l@xn0sRmQS0|+#%bMC4%b64hj$M3>u#h&RW?RD`5E7+KCTJDUG%O2)lDTVS<>QTu)M`;HNjdXw#V_Z)|23- zT{75C^gI%p=9G-%N_cF5^GmRfZVtbtM6hX690H;qJv-gvA7ZJ61>E&;cQuZ{ ziDx9PYVgA!#5(>tV2dhH_Y5uKP;@b&KXdy>A zvkJiEpN^>2x_@WZ$f9>Ze1l)^HFddICS?#7kNw)Adw=nO3~Y{vs#(0HHO&Bg_`<~Q z%g@L+mD9yP`|GXDoE`uGKmbWZK~&P|Wt32qiqtFB@W)Xliys)Rm5|dtw2ub`0V)d# zK=VWO3$In8c1Hkn;Q6(u07)*dfBnEDHU=3-0Hi=$zg+D1tk3W^|4GhzfF;_5u*ghy z2A%J6_wkRViFSnzte{JJf{w*?DBo0iqiyR8LV&*T*B(yHFMpBtOKu zu>&%RPVvo$%eE968;eMc)?>ZkN}j%HGLW75=vmohT`D?}b%tf8*HB?$iDe8O)KPwm z82(9D8HqrWKN$xCahKf(0JK%Y^FgZ}ap z`2%$E{`lLcAHVv_Yj^(Q_4{An=Ecvs0RHgKwHr6?ev+GixlH;jZvubs!8d{5dF=h% z0nWOluxEet^q0T;QWh&0in((3)w~y$E+69cmvs~P(w@tK(4XvEe>gNQXuTA$rnyvp zq;Gs}o?K=pOM2g{jMUG#<>6KhufNUJZ$2vQvuXK1h!>yX`1zupS73cD@W;LUfCFV6 z#}3aV9Y1#K=G*VQmv089xE{LK?VY!^CBmB7df zl&x(7mKU5bor=l`taw-^&|N4zopmn<5NK?`bztoBkbRniDB6M?Z=#J0{1{Jh+Elaf zp$|$jm&lA1C}2a)fq>D?D8rEv^~F=*R67Q6$Vi_SWBR0H03D53vJF`a2JN0AY6OZd zeul^?zyY{Mk$ojV+^Poj(o+uQG`DFiN;t-_4Gdz2otF_<=1e96ax9TGPzG@-s4@&F z-qkQcQ01C53yK-+WB>-E*bD+|KX_?L2ZY`L#zZwReb7aSI)()bLt2k`rqI{SnCSkC z(e*?Iypw3LvpYoARr(=X^cdkReXL#EnyVrdu~$yh3|{3bX$?HgDaB#84SsE5W)If=$%uGp;Ex!w@~o@gHT2TD4?(on8>`h&{jeBuW6{-z+{-i zM^yBLwyLVfp7>SIp+`juAPR&@=@^~n&=w874Eoo?fj62?Cj>VaL^6Ex|&2x=ZZPt#g4ENm@Wuht#!7{TCI>IQfMV)VYQB)Aql)@d%DU) zv#Sd(lM0%0i*1|{k6I zRqgkNCHHer@>R3%zJGleb1!ULzW?f-k9}+I2LFVEr=Pg`;xjDHecP)~zjZY)+`e=5 z%AKpv|L_@hbS^39mCu)>a^3#zAADBVQumen6B~1d_RJGMG0P_-$Q{=oy?NyaZ(Mof z9WF;dgO)qbd7pDGdXw~rZ}R0vkMwr;rHb;O3%UBu3V+e=U4h^I&F3G#b&VD)HrETXP|H7A^*EnZfHb-0@zVr8w_&H<2x=!fO6X1mmaI;LB*_gKHZ@k6Z zCr%4}pA^ObNaZG4e-Cg@7C%9A{*TS#=t#2yK_x)njCXvo_(bET@q{wr=GyY)4WP1` zF}+VfCSVO_dF6n)cz8R>W(26J~P zvl!;%Wa%>;1!V}yrdk8yXzq`SaGtLGXBn}SFny@XziJfkpIN{pQA3wGDlt((H?0UH zg%l*euyiH>F4vNQb<3EQpDIZ(XgLC7+eF!fXADxZR)NQQBxusTxrF_aKI9TGe!q3k^O~nYk|Kxhadczf6ATk@|Rf{Y#Gb~ zp7t*elFPsLFBTQ<{KUpaGeED#3;Rnim?>)D&>dwWgQgzYoKPp$dDXvMUUPEJ1@6rQ*q78wcV?+Fy7JS!T3?bE4e8s0P zzplz4(X7s{oec1&SIwf*27cr~Q`oYoR`0-MP>YJJ1#$zjg$68rs0>J0D;EaK3BwjK_;cs{bX)=H)e=rOtIeIcY;W^rC zEIw`$NqvzYiU=TITkD8fezcwTS0K$P|JDO>sR9SnXG7^gBuQaC{N zGPEFO8k01klOd>sTH-ttCQ zZ81=36)!!VCDEdH*(+Srj*ZQFN0I#MUoaD*{;X#$&y|1wd*8{Mfxq?g+aG**|J$~W z{N(+YpS$+!Uwz;!JD<35`__%TJ1-@7!9I#OBES90XL3oTim!e7fw$ydd;0BbcdliL za}E6L51;Nqk&ozNjqg`SZYJlecR#AOpL*XDxAI}ppPkD5uR-p?{>2+tUU_{!csUot zJxYIa5jnJTnVk#WyuvyBKS+wVxcQu$9;K2zbJS+aa5@IU>{=Psw~ zBWa!Tc+~aGI2O*v4A(iO=3BRJJpbI&oDV${wvUU!I{k5?G`b=6;uofoGd3sKz}Dfo z2c}$)f3pNs{sz=1ep2?F5w_|<^LnBWqT}GFp#2xcp=SlQhSmbSV!?IweBQ&j3?0w& z9TldTu}JlZ!CdF$QjZq#p$tT+7!4*@8fzSd(^cr+(G=76X4)Z3&l|cJGqX(2Q z4A9Ci!|=zvr;Pfu;EP|S$gZPB*_RfxG+hc6GT&`r)e`FpJ1XAr3}mj>L4sGQ1wboo z$(7Lc6ko3PTf!df$Swx3`^bqY{_$Nd*ciQskkS(1Z+G7!#x{)|1Yh_`u&2yeUtoA! zZjps`Z}`U^wra@%WZ0wH3y!hel7!?CJ@G*{8Wm2ul>bPX9j4R5>&Sb0wZ@d#%t)A{kc z=uJd7^d*X6F{)z9C=)8z@|fTZP2f~v;9@@ZZN9nLNU-&Y zM>>&3GR99X=(Q5$B8R`G_A(7*CAts*ne4+lxt$fb$`3zC$;e@zE^>fN4+Ex`)_6uRrpcQn{ke`&XyrN4d#Y=|1S4z~A`gS3bOPJ4<@^_O-A5mtW2b^9Eqv zSbOFC2H>qOyEr@HFZZ3mTg;C=$U9VXYxJ|ZE4xKz>5?(mtGPgZ`+aWJ=9S5}eNS?) zSF;z|dKkOZd}La@xzLSZzx0^Ee2~?f?{Z@~gG}?q&JXdTda3xN+q}&CxhJnY`Pe7L z|J>s8wZPwb<-OP6y61ns&gXzRg{{+JU1tF2!mE!zaqG3$-{Sw<=I^Ebbm5Z@#{T`l zVtZ~Ts!yGsMfaZrP(w1$kKH*t>pIs~mC%HHLPtkW%VD0;+Ng@dc{4A5(_v;H`&d@N z2*BCQ88tPiwvIMJV=yKtEfGced=Z4TgIr;2eI`Ko;wTLCY8F_r@|JwKPL_q=c?_i5 zcnZJ9s-(JZ96M!h6_FgTQ%oW`=Uxb?TgL3>!Ivy9e-@t9ZHQr&HeOxHMYd*CXvYdZ z@Y3NHJ{iirGLfZY8L4OGx+EXu#3rEi8kvZR-6Fy6244aef9&i?+?SR}Td5;Md=tPs zDu;Cy(e1DS9>c)a=4{Q_b*r9(AQ`lW0^^A3n90KH)Vt)LcYv#B+9A`~T84jVY=+7S z>hL;7&Pj%p)5UI-1gK>_mwXPb1ILJ!EdOM5Z7VNj6HCzrhF8H zB0G*Kj1)kj%xWND_AdauIMVCy8E=WNX+keZTl`c!k&B?LmO?VjT~F8$L@d?@fVr5V zb91Y9fEpw?LdlNUt~n0`xHMH^Ev+Z93)!g5svj})PX_U8UqBg7(#vK}vk=v0MgZFF z$Hl&A0U8#)Y{Yg?t^Fn2M9vaxI(I4=J(hGTx1mikF@aal@^!5a?UQq|uENN&O{E%w zVRyEUw9&t-vt$rhI3^FWDqqF9{`d=_?<#AMPur@ubOnQ@ff~LHsrNX>I+ko0Jpzd^ zuIu0P8?1QUU1p6z8@sI+_g6!opY?3=*v-TdJF8z1uZM|Z9~^Xd~>?Cblq@BQfZ&-zW^RF!MCTMyim_o@2fnzHwE$@=d5T*u}W%dfu0E#ln2 zedV<)FTZx>`>$U4zJp9-j4Lmt&QI>{@}Ayzxr+WQU)%f4Sl`0F>eVc6m2HT$8V+MqC^m`fQdcCw3LoS$hUTR=j|JI_ZH z+wm+<{&Zha!%(EXjQoMpS^~USLj73bm>K+7#)wrDkTje^hf1yUBKVA}roR5IoUszv z8%i0B;6jjLrl`uU02dW634>0XZ8qSYbv-LYNZ3Xi03G7H z2(!Q7T1Ra46s#r`FOlLiH}@zYZw<$`>zQzJ=ePK#XG#b?5}i!J+UugnWxdr+fW}ZP zQZuYDwn~*#_JgFM+g};3C+u)fRVyjB&f#X9A22X=XzJ0NSxQ9p_Hca*2gs zynQT88%nkOglUXxt>DLnViFwz)(~`$nL6U1%GfMnD@d38u&5el6x)YtMlGTotAGUN zpEk2h0uy4*K+{qQ+iK(pwfvKf2&t>jO|cp2Urw&IZGp#2~@c z?xUc367s+NyFbV!>7V}DTkt-N_K*Me&5wAU=W|bRfB4-GKhZmZUwQRT?gKvzQ6JBd zcLKlk?B%y0zVXyM*Rp>3bNcqRXI^{C1FRpU?5=qLYi>w>mapG_fQpA;&R6yP^nP5^ zXLMZr_{*4w^0QA~dH$&{-t_w^*6_t=Z~miSfA&5BJs*0qT_@?D)W9AqGDkP!YrwnOAWjw-E5ehkGH`Q#UMF-<#ZZ97fvb8J z@jQR&Z9%dUQ#=8sU}LUqa5AMcpmU7H7ho=*X-vRWd~1y@1o_ce!g+oH;PXp$EQtIo zt9tOGA#LFuYqc9aLd-Sz@+VDB!BSnOoM$tkqd-HNczf|sr)dxtn%XruQl7jV~w2_3i)GNO>=1Kjg^6| z1D6MLjb<3XWh__x`AJGv8Wh=G^$8@qippO+5b?twz$$nw6HQ^Xz`-ny9l1363knWI zet^%BVmP+^qT>=CPwe6|)@vr>f6KL*6plk ztX+&2!(`z=XN(~B*LkfES1~8~jfnt7uG|D%Y%2?k13&vK=`<7CNQv=c*H?V(Cp^pz zP2_N_Y{ADOUYNY@3+Py6Eab7&RqnVj=67f-0L$R(?i{M&AVOM|_o$97EmCN*PwF~q zAA-mO%ghKfUMdYH?D~oWP8bQIru>qi7xeHeUm4i^F+j4Ztz=d@I!XaYe&irv28(4_(yTeAg@Gm`vY7dLT$S`#3ss0KWs*y9W zF;bR4!_Qoo`}eeGYbU4eQoWQidKfGY`6&Ps^R+AV#iVPfT+IQo5mRxqwy}`;SkZz; zjtPP{Q;!_*rAptQ5F{xSI7&amt>=ILy>I88z~6r5o%cWZ_?IQa@^LM%{{1_@_P|?* zkMmC8+js6<&3)jHW5WMg-UR;YJ?{j5^T~IwX1`@&?p}T7HQxZ7FY3tMrR;`}l%Egr z`W)N@PL;WP`ImSf_>&wVKb@GzZ(aG)GgtC%>ONq9Iz|3;s`^L2{>%%{T>L13Jk~se z?G0z$Imu!h=W_R4|Dupwk?r%MT}p z@pOk`g#m@tLx2#V>CWB?GzxI@tX=4n`cqWIbm&$~e|7w5})c z#O(cL_#&Zzs5IXi7?7A)xA5R43(ZPz{*mK)29SRsv2M17hYe41na->i&L_%fJi3Y} zA~6bJJz-vZ8J?vlW9`}|4HXzY`yH9$5mB83Cq?4RPt?d5enoQtcQAsiU{W120-+ET zyAq9|Z~a9|1nT_2JOZ_|T+omg{92z3CCwZ&zWiEGP4rDb#lS&kP=*>>ZYy76F?KfRAWM3}^wwpYW5t z?4&Q;t$HBb`r~Z^H^M81D5fGuPuWHgFzngVMiG*B0_)sxR1Z-@!i}H`2u%8=M@YOT zfCD{5Xh3$fS=~-h1A_Q%UruMN64qn=t7p)0QEv2foe?y6J&e(F<;uVPU;p6lox9)s z^M`g5_;-H&fgcB*bkBPe_?`E86Ya;gAH4n<-UNR9@=f43pLj19z}NCA&>voX^7VW$ zRPF`y5zy)9pnpICpPQS&Icjnr_>1?iK43rJ$D9v&&e#0r1?2a6DeryYUzjeh!1e1_ z|M_pda9BApI@<$gc?5Do!*iS+>)7zCPvn0fI71fC`8EGMVXo)L6>X#^1m<*Fr5 zYCwsED+@Ad@Y|rv3|Yd;ci-C*J}PL43m#bqWAxbx;`)8EN1be}<}$f&CSfo)(xX2H^v1 zBq(yFO#%lToEr4TjdR7zi)jW1BMU?9!#30MX+z-*a3%tw6ilB+jx`v*RxUO4ytz7A7-;gQ207vh+-vwxgHWmphUqbg3xtd5p(89M;qkg6tPPwE@5N!r*v~>Arq1?YY z_Q0i+Copsz2Ivt10GZPhWLyW$ym(|d6>NQz0K9Tal^GdYSL`VVG)`O@aQNb9eK6U9 zU}ahljCB|(jywWz!09@jV4X`#xl?!0)f43GzIr8f86@6`stSj3)0-XT4E72;L&DZG zMQyg~Oi=Y?Yx&@Z%v#SnVh0|8BL(cjYpmA_G+0qaRYzDXsOmuoTe$#mfEnO|bs0e# zPER9yn>sVg&+H)ejksV&?!u!NeeNKFJfP*T9{Llz1mY`ERUtE=)uK30f9( zDvc2}fF?r*tOgBX08G%Ez~6m%H-Vpj>gwPBs}H;h{Me1#kKN42N?rZ%!wOX8gSxv{ z{`BR0J{0Fc;GfveP2eT!gB!Q=2HKWHg_PV6~0vPv&Klg~)|IjQ(jmHD+_cbzFH&ayLGzrY?zQ?_I!wqLmL4?BLq{C>sz#YFhji6xr&JKBxoty+lDVD@~^$lP)7O# z-(zAtXZ*lLGtLoD>;5W7HOXM)i8)JE=JrI!lz=&En^3c)qlkmHM|a`qB=0c0SrdX; z3>OF~o4+3C3`aR5|4IYLxI{8&AdMN+V5HfLo|wr9b`n%GaH9|T0P-7!#M+vA&AL6j z60ksnx2Q^@pB>Omu?jv8=nxv(V{B&UNr_#tiy{;TbN81xZO9oSmu}VAeh;qc^NgG|tK?>TPqBCE9f>!b%3cOjVLckd;<4NY!HSRV*& zS{NOslUuc}=b*FMI_5}Q+08-4>%0VZeh>CACcAct(q*z&pdlnX>FLg!81U7fk-@Uf zG1f?9@kLAPU2KxTj$uvM3uTIpph++gHy8M00cFo-AJ68)d@xXn>u-)mt@S6DG%a_A zPS)7%iC=P3qPTVL^SQnd&hr9@MH6JkU;Cvm{fpoI%@40V^VMJa^6T$>f_t)I`~)pG zf%C`bgMiOH&O3qM$vc4`2suLk;*C4`h~{Jdut#^+(uerz+ys7R7U8WY-p$o-KKSa& zooi3O{$vzz@0Zs(R254J}@nc;}%xq`^$^RYk)SIB#Dq>5CTUBtyxTYdm z^LdivoA!*KhYHO)%qo-soyZx%BS7Ua4qjy%0b5#o6IBvdO8b3{MLlx*pB^G0m%$yNTm~H5`~!>CD0;=fpE#fEQ>j&!qCMA zY4HOmf%4gCBdEy1uPJJ1;-|N)#Bba1cRgGdTtv~Gk}@W7<RDgEm4n6#(*#M|EKZE8h(DJ?+2%0Biql!mg*~ z#{$-3WfqdOz>xOz>QLl(M5JajEJi# zs=o&%BF742R~0#>hG~x8)8oZmEnrna#9E2LS3lgQ9i*yAGk6kAwpLv{^$8V+nx#jL zx(82MhdBV?&Ajea?&!&jY{O!`;?RXl*hM`gOa89Qz%Y@(&U_}KHqq&YxSo|3-!FdU z#ozty-}s&1`diO&YY%9?LgtNk`OKb&^0`OPKAD@qH~#Mjd?iwD0zZE1_Pg(2zkT~^ zz8eVvAJOu0&@X@Zx4-tlTgo31`XE={p!?ce`MLAzTX*vby?^)grsaGma4xyCAa6hR zUUo`u_vUMMo_ynpu5zw_^D{^0gV>inH-UfUOW~jWwah=O+uYcE=~=#8C|@k(G4-=r z$V1efOW(XcJU=|%zGx3`1^8OvzyI97`#*nlQ0_BY);cFLrk*;O=FzF)bYRB+p&teA z>9nWEkTs_G%K1Zsb%4>v;;`*qZ8>P?Z(5Rte=X zyPgp;$gPm$^9Z2a^%!Vr4bYB=P=&CClKj+`YfK&(v9V$tIn*=B;RqF?wiT3-LC$bl zW{yLI{n7<<405j>P=I3HUurPaN^vj9Slz%Ro6ce~Z=+@=V{pp4ZmKBAY~)ZH%MK!J z?c84}W@22#0Q7Hsv$aRJqltme{biOB1R-;B2hZ%tkum$r|DM`PyZpFfYJz5w0(=$o zu&Q!pkfYS6IQ1kcG}D8kDU#}p-iaDa64q-skGgf7EUtKgQ$U9Nx@n-*wqniWE=1f2 ziDPAw4TObfHjb%TkKT@2T{Vow^^Dj|4XT+5U>C3bI8=FB=9N%94`5rD4n3~$DtEH5 zr@$lkLO^0;j1H|^53`sOK+O1>sK-bbG+9V+G@b62?oZ@&fy+UUw5sl*rH6DgSP7L? z`mKxbttZw@nlcV)hoh1WPAZMd6MRy2wo(pd^^_{TD?kDVV3n-^k0)1Wc*(LBEKrsW zOE(Dwc0mvHE?*a@0m6(-*VM<1I!IYPE@L^h7f)>($wvVA*dDue>tFw?fBesW=kKiy zxZ{8M^($X}>B^7Zy7J}weF&?dPuKnSuiyH;Z+!5eZ=-qcvG?D7|A~AY^i#J!{*}-_ zeB73rTsq&ilPlrpo*MF}yb1gluits+@%OLY z$py}xt9P&E0yyiPN#5a^bz^6`tRI~}H-W$NgWG@Y7e7C*h|LP*-K|f2$hQqWXwQE1 zntX1&`G2BZ_db4;6>qV`{nm~y1VoQGiT!_b{BY3Wu95a{CF-E z;xN0ar$r$>$@hd@OatQteL8`1LQnI2d)nP3)Pb*03BVQt633h{`sYaCJ`or|Y$zZ< z=t%;_J;kVL;Oc$JgZTB49RJtK=BoP{l@cO-(ib?46F*v1KzRrMjH-({GgD1>;pWzHQRmo z5$?)`$pGo6(j}lYX7f3&gl~-}ff$mmgvUU7T&Fgi;9abH4L`ibs)v$7# zHNFNeLCd-wN>=c}!-z2U!cp;s8IxHB3+QT|hpU3z;8g=A;Bz^{OMiRwC@@FdKX z#%W@@WB=pjVI!a|LnMle%)0DSWm3julD1TGx*y_|1(;`|mP;c=tB)t1~^)=eN`!4BU^)5Xms4zDE((fj} zp6W^2Of;z-<%vE@V&?In5vij`9QeKOu%rd^r5B$0pa0Fj{<~lQ z)#0ndK3|=hYnxoN<;9#2<@0-T=kwk7@BY~j@BiV_*RS1u|Mv9{Z(qB9-48xFDY@_P z{SWSb<@xLPb$x^}7iq7)dFRi6bmyDjzx|Ex-~PdCciw#GZmxtcwf8=_`wJ)XT-bc~ zjSpXb{PH!qvW!{k#P2|srW^)L$l#g}gV{-3<%iSr^|A5Wb0@)&he%ca@f zE3d!#wvo6mozFc#_ZevZECDlTShfHT3-R;!z{;|=0mI*pL0jd~H}!tN6*UHFat&$6%mUBZI+9B=I^>WUG>a*S!{If_q?*5GkYBFfABeXuUC64#?Gru`N^o zuqYP}cZ|*=8oT>_WRGR(OXL}kvYOV8r1VQo#F!@-6o=0$E#~7uj*)gSIh*}u1PO{S zg#lYxoaJM%8sVB{#;!LV=0lF|7+l^y+JS;T^#J&D%1}ePp5#E`^bNzZ)^qYkzW-4I z=itdg>vRclhI#L=QBookNUvb>Oni^eguyGKSi-?ffkSgFrwWQmZ*(;wc*L0^rMAgd z&XZ*^nh*QhU$BWDu(H+|kCK9!{Z$F06SfkJUo?b$DB`5x27xVo6mtMrKsu&N&``SR z*l_WX!IvMyvoRP;e#@<8?=KwKkK@6q=7})+!v2yUo-;pUFp(>*2aJZ;cDW}`%;Hs4 z0h?qmf2c|c7&rVGocOWM@uOR$(1HnC%U6;(=kW!iic3BzX8r5Kw)XDA5+rX4_Ik#q zL%fJ|{8W4`_ERBiC1TH+Sz|L07(@%~gsCxR6I~h=8MfA+P};_i?wY5Ep$W2eays6y zsOQu#c2!6jqtW}EVH_Q%+-y!hPz z^gsUhUwZL@cX&U%&0qF+?p}H7v8n1O+~le1&_l<;1z@%^ltE=c4!J+u!)!?N?sA^F}UuKRlCN9_Ql!*{7~Pers0y){Uz# z-+AYio4oTlaZkPa6e!Q`@uSw89rj3|5JEzy|4HqU_V=~98g&bKVAk8 z8MPq2g~e=Hu%s>ThPg8U>1C-HvVs^O-OB-m{Mzxkr{V7*HF#k}($>)yxWOQmfx&>L zD!QOatf|?T29l<&iX3*j`1MmA(C{ac?JTU8`UK*1x&mhXT8YkfN(yBI#<6tv%1mP+ z=!R8aBK>+wUP+}dH!aLvC4kX*h!$tf(a;$$yEkR+ZS;xaFtQyi+kc)Tv z|1%B@@+Z{C*bJtwl9;{w3zp`i5<=xKJ3L*@Q7`Sl&Xw~%aeFln~HO9MS)>r&dA)C5PSqNHEz zxg|)$Y-h?~9@@J~+*2doOj+Hxn}|hOAS}S})fQ(O z?7-I|8?opLq$egWIrL7w(xPz&gB^lINN;>?P2NWw;83#TpDW2+TYmR1?th~&H-SI6bM3?1 z`QDRHbQAd9i}z{I`tw)v>u=wA`PDo5$ml=$-t7!tfBWwHA9>Mx4$t_~P2e}5dFMOt zzL(F(%H{MkuRML@y<7P_o!tJtl`n7NO~9X`z4hMb@FsBU&wmQ!cIXqn12+GA^0{nz zHAJrSpUExX$GPTD$zQb3as__rrCWdW?RVaN|DOM4$)k`H+?-xL>GeE0>Yje`i8tPQ z_q8|X+ub;~&hz6sTYAFv^f^}?iR?L(oh<**uk$|?`9g<4pJ@(=nS05@iilStw8x2cR(|VPsj5S30x_w9ab5X!;;Gr z&g0p0tx1eDm325hWTnNu`3FygEiZxoo9Ez~6HGj9w#%T{cq+4Q;!pTS?F^>@bS9P! z76T_>63V&g<<)_XS%|VI4>|lBybCrdGy?vAw50$r`rby213g3OpxXT zr!j}WlRD<0(R<)KN-uO`kAh2~Aboo-=gQ#Z=wK^dX)W>KKlT@}`L~aWWSC%&Mg65F z8!WPC;9S~7te7JjBv!g{lZ%!qL(A0V$o0fIfq*aI8{5ap;whFG!A%5zO}c$llVY3W zMEwM1uv2whX&#U(Z1CkxJPgA*BluNs9-L}u7n=1bC2N|5t3CvzDWrW3+H{pq>!jHa zfaY1dbq7`e)5HN=(JpCT7tEpSO(scvRQyJXk_^tz-Ep1@^+hGZR+uXkLM%r(we{ zl`JK91T>Lzi zXGsb?9$%V|9Ttw&uuYdT#JMZ&O*B8I{d`@gPu3f!#{c3Ik=Uu>i zsXt+^T%UjbZUXPxbBJ*__%U8NpGx!dIcTXR@9)j)oO9iqi~KKc`QE!vbGFRQ|MU;# z9TWHR*OLEldg81bU92fz3}WG{+Dmvxs$&kkLLN%ljXvD z@`Yl;!q_XcoT(h{!1d3p%od&##a(h z8!Y)PK7H{V^H@Qt#4%HlqC;3Jm^}{TfU@{TTHp?V3?U(?1ANGKa{|3>!A75n3&+E# zd<#DN%gU!H@-$>rWpar>(O6Wq_3VZ1ajOE#1Y7wBJ`j@Zf{_zT;hWjGIcx?G9p@IB z?k+}{Gf3}Xsdt;@B0Dj0Qa-aeQDAjFfi^6fu+jo2`+>&*9_0k8#&Qjr>}=f8>4ljA z!i9&KR{kbps&&{i-pU4!Y_dW>3!A7IltTdjn4?odjW9c}RW!p@@PMm8W8q;DH3=Xl z9p`OQC>S~NCv&q7I%buj2`q5Azc`GGtwpFuFD4PnM@j@PU*;$+Z7+03%6h;C!AsM)PByUxTd z`WBMDI!mh_l~5KufvbSfW7Y)HqJe=K%WuHaT}gN;)9j5~{8m|Zd+880^j(?IWv+q> z65BcU3(ZL3t|n`iAoQ~iLi19hbJ`@z)@zw+#j2)p&p%`10! z?=heMoUcJzhsdW&my7eBlJ{ z9|f0JJLkfFokAW}&YwBnJmT^(;5kLS_V$&x-o29lBzn}1uLb^9KdipzSx#_{<~->m zi_@S&m|guVUw-~ufA-34U!5BWF8>tGn1IGo{QR-PAU>ux`Je?qYS6&HDanC-|(mbiL(AOro{*?gKTpoFv#>Ie~Z&5j=;1s7>+N^eyVpCxJjTDF`L#4JT$v_ zL=F&oBSDAcz30h7Aw;y>;Bj9bt40`6~NAYia})G4Mz3H+sq zURHMS=YR;RayG0ys)}=y3Ay?&7KCU6C%(L;H+nCQ@bYsQBmfm`9K=0JVBg@<3dh`J zi!&%s7se(mVD++L;PS9KQ!lI;Gj%X%b>gdF;z+erKoA!u{{dT225ImwJnR#S1`(>t zXpVpI1PyEtiruN2GQ9wu`mo?jYq`kED6njV4>MU-o(#}$V?zLe7y>^$M2Nz;LPA^w zJ$js_1H15nAX`FH-S7oK~1lziOgmDfQ0 z=*^GAePaKA^EYqZx_I069Qtg&6Zqk}u@o_EJy7?IAGwPRK%tuU}4L|<)^|$W+ z=uODqzWzZz`}v7$*Pgv~{nk5=XEnJmkuOB*6XU1P5QcBBtLsl6{WBJkkA})!(|jrJ z3r}-f_^18esTaL@TW`JqEEl~mKFw<%Qo+#EM9OK?T0Waj_13om6j9woS)GHWrN8A`@{oM=#i-OU{24E zCw!kEHeUL;!METo-f4i^-2y8A=}(au^OGjU;E4)yo{p+Hm5N*VOaPV9;i$Oq1S~oF z8VoNNz+GcfY}Of9fihiOmm)B74}P4Gk{<;pJisI0EIod96;K02L7Sf#mkcqM6jWW{ zrB4rj$(fFG1xuxpS%CRQC-<~tDCm29BH7?cBxi3VS1CyaL_ z8IJ-?3PrQqkD!|9gSQ#R$V5Zgr0T3VWf)P|;K#XR-D&Z;!jNuS4*F_{Z5{w!hjLW@ zfp?*{TEv$7lo2`9;clKpx)W<;u|cIJdwyaW{RYnNVUa03dL~|2kTJ-Q*(p>3b}K?IN5Ght>~PLR959*7uN)U0_@(0k4$-ibfAEkle&U#rN!cQc z$I(Rfhb~VMF@eDw&fwl< z=^g<+EYPlmSanTbL7y_Eetm;uVZlrE}{K6+t&b9u;UdG3A2|o;y{;j|M z%dmg4cH9L1H1DDP2=2Uv^1uG*o4|Py^xZ4(fB1=R0_R=6=Un-K{E|_>$@-S_g(b-zs~TSJw01e z3+LN0aQ+MjtmX2IS~tDEjbChVEj*`e2{1AqeiLxo*N%tLk;pZTQFzSaC4hsoKF=D9 zGX6DTG~jGtCBIJuwVM%y(MF25Lk2P8$dbTZ|gP&mjeA!9@iyqj+%D+`3dWb7w`OjHEmL+}l1aDN=3fTRkoHFG#uOMc(0N!c3dbqeptqZH*zBZuvVet;C2dii6_e}NdTQdV!s)R zN5J4iZ}ui#sr%?U3y3GvS?Ljk0kg+|{G~kv%#Ivx$?E*9sL}M)+R3Jm+M_A-^W0oI^fejzR*ZSZko!ePzOqbf3jBxQBRp&|)vl7ixk2f0&?m<}Cad0eE zMkmn{GdZhl2~d|=-0fXQAsL>|x0JFI6`x*sGOVyeP_r1(IC_wF=~cBJSr8CA_5OGN z;=g_Ig=Y--MBVM%d>Yp6yIdqZl*T)O|78C~dYSUp4c-ZyS3%#p@$v5je*c4fBGJ_+ z)+aWH>**)1eeXxNAIe)#OaAtg@4cT7=elz>ub_P5<)`0$kE>tb0PHLD_O7^G$H&Y+ zmmdfHF*WPXg=Oxk<}J0k(VG7a$%S!l+UE$(&xO1BpM>kvV*Kjnys)_+)|I=vxz7!TYf-QCZ1HeXIW~FWma}EAPGjmjC~? zAA=dJ6YaB4J@E@)dLeH@&-;FV|Ns5de1hFRhi^FNNzbo1Jpy}@%yA$SeEZ)S6Zloki6r~=G)M~Y-dj{PD z*nm9`hUdv|{=@ue1M@HshW*wUj13RqF?!rEV5oIzse76fNr^1pimYOhb;(SBzwcXX z?-P+(RawO(#ct%ztaJ8W`&-}o*4igd#Ho`Jk&R&nn-~&3^&|@T1e(s^i(6d>wH|vh zW!m6@T3+qSYDhbm6#Sx<*f&fcLQcCjS4 zNMW)8+p3O+ERS1?A$E-%l@itvlacZ9&?Zsj$xpLfRR(W9*!|l9V$Bw|1wKnAE`CeE z60W|?;Wr&(g>-*Nuo&D(F;NTR+}wAJ#;`XndpVfXp2Z)UgaN#-5nGLb9Btt9Q^pWz z(&g)V+Qk-o7m2JMhRp+Ge7Wuzna10VsO96*put)dt!Auf zHb0XoODrZBHsWhGNjoWm3#m-IJVozNc&md~N|5z3I8i{C2Vk@HQ5u75JH)K9dk|)8 z2m$L=;S$su%q{*@vg)aD`my{-90yIP?1a$ZlT-W3qmo=EAQ!A9csbLWpk6ky2xiH^ z>1XyU{UlU*RH z1ES|-DW@VeVfs=Z@|s@T>3a+}_^Z z-aDbcfWH+j?*C*UtC*rg~j1e-7=x{L!QJfm?nU>Cvb+=ASup`iaLce)ZWW z^_S0AKf3;x|L?DU^ZMJjcXoX2aDtYw@u=gV>T@Y`en9)&8pwFP!I1MckNG~E8jnS8 zKJmJrymNkb%oyA26~%*7Wy;VgW`Hqxp}uL;DgA^4yROqB8JqVO^eZPNsDjOdis zQHw-a1Q@~8K~LQMg4Ngg;V5faAn5#}>4(4w7XioDV3r{_zlm3ne_{+L%lunx{ga&~jBR z0DB6D3?VAGr_ClR2@S*nnk2IwDgvAu4&dP`N!ziK~==-BaC5qq!GYrQBZd<=qHJ~4ETV90yYml@AOb*0Cu|gyCV!5j8D(? zi-mBOiGvxGWM_vO*VFneAo6;>P^fSN-#y|X!Bh4l85FP*vi49BDia5Hh0|MXn^lg^ zDnta}!7M7r@|dZhNC(Gg>xiLR$R`0u(dmSV& z&`PhR21%C*DAkOY&8urW*5D0bD4MLJa)O0mv~&W;0!%V6=fIFHaN}b)Jpk9!qD!T) z!$FSvg%FDBWM~>}V3<;$4ulq9ORbleAAoQWXi?H*BSvG?xkV$I{J$S|O7OCo_ zk4I!+w7;Bt?KuKTjh#`TM?smTo-7D#+2Q~?WN|Rbh+Yv1me_Gvx>>(Ts0Mr~f@w)V zF`;nz5Lx^QAL3*b{6c@^RCJ3)I*xXbWi%N?Tn>1!tceB83ACQEVqUMf*}sWH??7~0 zQGz*3r!({pJ9|v`*`oYtGmn3Rn|L!^<_)reTn<%@5Au^ja%E- zcF&$)?cH9Ty~(?mFP-21_~x!|V|sb+gK7h+g?jCsoo_wM74>mT1$6xC+Eu@IYI*qZ z;8-B?SjYpS9~X=10c@RW5iuIpm`ag)zv^{q5)K6Y|9(+s8_k7isd)zPOq>vu|VPQs83<;{ z#p1XQ3Z*O^mxo_4$xB=Cj>|y;P!^vNEJ)y`Lj*zSA}|y~9bG1Jtn?gWMsO(G3h12- z2wEm!MN6X-0G+@DwF$EH(*d&CByr$12dyE^QTV1Yd|i(aR@Z(+9dTWrSQb{|@c05p z^u(@R$RnDGrHrvm>43Kk$1)LgGp>&x_=TKt zg|;@Z=4bgkkfsW6huAT8!Uo_Fq`=)ef+oN_q~_9}dla@JTn(pmczKALbn3}$l5Oa* zgUReLMB+c111v{QH-%N0=waIr7f)qoP0yeQnd+HV-I0;a){n7^HWM(d6eX72gK}pU zL3r$geXX3(rVdS;X^N5NN&;cnLk9}dRCw&5thhXkef5zCEz-(!rx3wK02(0ADQSH(*FMs#>ho5}xkpdrX zSKkS|$NjV;`Qyfryt4id-l0V|cJwF5H+N1b1ARa6u-~bp3+bmX&C4czKC>#OkI1?c z{_ysjr*2(a?OwWY;*;CEXFfW6;^xWoXSc3?q%Q&1r$8@@et61>ynbWvsYmsxU0J7T zKknVB0z5|it1F%HJB&Oaj@zLtkPocVLtFQIb-k)f-y?bBK;nx^_x6vn_0oq^??!&> zgVoiWXHK3zcmAQXXV09<7jo;p3U9pm?qC1StJ>~4A5Q)`NAh^Bo=7y%`EXd&7ZAJ8 zx0>e1&(1lI5Z}*V*zMc+1D-D+f?)F75_3-Ikd&N?E3}P4)oGik<9SarCC>t^r+gC0 z0P7*T=@%1rMpyYb(8i!_#m`euz{wqcKT!^$9+H3n(MHl9j_2#!j6tj(?162SENJP(<*#cx} z8O4G{CL_H8pjxI+Ks&5O2GJAHP=U&@%u<>%3YXcQFq#6TZZhMlAHq1nklBKb)iNZ7 zWnkQbzf1{K;ml7ICM`FeUa#;QAc$mwEE#mF4H=kn*sy%^Bf(Jx4VhL;UiP+;>cXCb zqj@tGRIOJ9HDZ)M2-7+`ASEb1&$NK77lAB;X#k8;@ATqho1;17mYx0NH&bDWP2ggb zwFncyWJHYaS{WC_0Ha-tdx(BMS-e{Lr!3F)c>X-*vEssJ@B^J>;bGgtwwtu z!C12mo^+;+QlBgd*6A9AA=$xC9pq~7rXBn};q?aM{7isi;qjj5Hxp2eI2urO#$+1s z>eZH>Q(>p(k_eC=4p1c>1Q-wHQcl&a;)D0kC=hT@;%HKP)I9W~ z&Xd;xtjvHBuk=7unVS_wVP`8pB4(k1VbGqk_3AesSQ4~9NeWz*seGXhy?eqBJvglg zz@Km($od(ZxzG?ONT~`QH;17f4m2~&f?NOKH{LE&f7zT-CEWO^ggCR&<1Gbpx!8un zdMBHQU=8pARg=9-Ju|X?GZz~bbNY@#fd)So5_YrI-usScGqIs=nN5{sihIQxOl74E zP!h-wfE*6G{rle4d94_)!)!16Ch&XLR!<+%P2eAW^YmZ->ek0MqIXk*J`P&%1irCz z;?yDD39OsI?|iuX#3S=hru9)+M{*Nbe}#SH`qqcncK7tfzc)^*hWaKaU9~DAMO~}? zW(xNlYkl-_(8o7{?^&p0z)@8|mxQ^^d$gCk`{fKGuc0{wn*mcUK?Z zm;oO-fAakgZ(Y0o$@^EXzIWx?yYFA!(T5f+J%#lN)K7$TbH-uoXEe^MepUk5kLWr- zdmI~Q|9Zag^C10lD1don>z3z>X0(++=@6VV$j13uXsj)gX9hd4kEdLG>M^_Z8822M z8ShTgwK=D%@G>_W(LEacE(OoHRu{f(0SZ5yTTUqawC?y4jBIv=k5A&ad*uZm6O~?a zb0GBRL$LC)W6j+G3T8%!kkvdDJ=8{_B+IO!h(VyTqB{jsn9NhDuao3?H{qM#+0KIo z*E)>og`TY)?OxI0!wjmP&PQTc;q>9?7o7uR`E}TVw^nZ(A1`l3qt;ovytX*5Jkd9q zJ!Ok!F&%|Y1Gqc2Eg~R8_YhPBVO-m~(y}-@GfqI;l2cLP^du8Afl<)F?KXq9$GRXB zQ7F?8rdOK)lx}9UjJS=vz1ON+4WREsS!7JXXJ211-V!$P60AOS#p-0 ztXEd5w;;h2(H%L`vCaE+{+bYEy`14lWH?7L+7y0`G_%H^co-Xsf9J)l{$(zJK<5@X zltWM$W6n19LOXP@LuJ}Bct&Z@xS6fchPMntn}+>3^7H7cx#AzVh7bN!brfSwPV);q z_-hr4CvjnK`Bh#yG%`mK4v>?V)7CVj*x03PV+*yNO5u>`WHn=VZ>wgY;m;#NyY9eF z0M9ylqQs&3OE4TJ!oj+{H5P)!`a;TQan{2`i2E zjvg2Rw5LXMy;KCW(E!ckD)q2E?lvrPvIjn{Ls2-8m(561LR@}f(pFmVXE{)}Uyq5b zr2y-inQ+ANcww#cPZeWKj1{pG3${uV_gTwTGNA=mMlx7tv?i0%!+_}| z9N3}=B)&W!MvWcT^u+E0#XG8O25sVs6)an^S9!FvhP}P>k3M_;(sSQ`{=PrYDmQ@@ zSD#&Ump@W<^h0fQ6Ii8r<*kGN=2G|fcK5gmEZrv$eG|CK%=h%7;mW7J34G)9ZI$(- zo4Xg!oH%{`tR5t1PHsQ`@b`>gS_@UB07<7CS_~5!6TaT^+dd%w2n{|&@-&dsH ze3q4t>d(48*iB$Ps`TL1=gZ~cCE5B5uawX9xYRz48IzGbK0yQWrn2efpH4o*D5BSR?@V zUys<$;rjeMJr+6$n5dRRSg46E4VF`ZDq`@OFGy!cvYdu!?z#ioEE+X)o@FLT6V{0X zEgXd(PaEJhl^=&v*7^}3-c7GzT?Gj5*!}uV6s@si5Dq*+TSSt`c4VSAL}(r~yP=Aw zOjtXV`f_C3uV9$83K<+GD$J#rE}5CJsF9NzX_aUAow{PM!Vv8En;L%}{tNsz;6my|NhHWBUPr3;dP zsIa(nZ6TtCIR*!V8f8i^7?+bOkdG56m-t$9d3uMt*Gr?q6PxuiePu!<{kSkfCTLdB zIOg!80vsyf6CIY+sVv}K4Dh(wk96Um=!zIP%+*MZuK5vEhnxJd8($i7#FwA&(NSs~ zJrVJuiW6UB?3uBeWaP?Zy(Xt{RUQ|@F`1LeC@(C?4nH#N>2z=M@yEWYK3?7*=^__qJ>XQqR4uDEP^M2 z*j*Di6Wcw_drvg1L2I z4xRwndQ{0eGKg*}&1(PmZ{Ggk+Rcj>_(q@mYWkbQulk+9PhYw(zdM3|_|4P*=~uTt z`h)`PZ@vk9Qs0Mk`b0j%W;_T;6%{xzG6Rk_QJrw*I57fF4o056aEn zT|T+BtKX3IZT)TSz!s^ZUSMPkdsabEqc;Ttlx1L#j^BF!bE$#XL z;miO2uikzC+U=YwIX{l)i$O5X|4gfKD&)NAC*e9jV;-l^I-zRUrzbpOH9lwOO!G=R zDbz_j=UWG2!vZXxUo?wCGdp4?`{|Jc63Fsko)K~F=c5YgjEIuJwX{2V8a#eDRb08TYD&w3C>4L$6c#myFWG%`rf^3pfn0fMi^?q()^AeJ7XO6KlxM3BKuxH9b=LSX z!=eUF2;8&cVTv;2Ha8J$s~zFjXf8nU$IlBu*QshtUSml7s;9Hmgyszx;`(S#ZJ4bC z0#?I|&{NCoU5v>O5$sM9*UHuctR!NapZSuX$FY?R0Z>^}@aiW;xrn^dH7%og{G>c{ zy&y3~N->ABi^(dpP_;zPAcXQ88q%RAYthAE3e4^hj-SFW_zfXrI+Z{#YZMrvIdTXq zEXJ1!#9AYq(4#pl1~X@qc{5Rj;N!S}Ck_A$@QgqnKtBa70}2*G@cLK94jv}}Lynhe z@QX2|1aWvQj_ENHO;QUE22X8@#X*t7tI#hiY*Z? z5RTh|2kuL9480>6 z%e56k)F(ry=^=LIo0=IPXPY7DGoGWEuL=a0dCYGX_i6(k2=e^n;;nQC`0RxzbyfGm zGxvP~th+J#J|wXo;Z0z@llJf5yvI#o9fF6t34CMk>Br_9YV)4JPjeG^XIp>yysN*b z+}YW?b@jyKXHRXP;7_3StxFg6WlL9%-~w1H^pV~PeDV05z{_Lzxc`6^sJHdr>bLdo z9_8D5A3&3C0_&r&IKk~}GU~Cfo4xu=5It!1Eo&cMU%mRy>gTVme)IN9Z@AFAeADz^ zVqNb3@r$ef=7+0)^@po}^7Yl1ALkS_n!XnJiHoQH;y=C5>5)?&TcVB=V3{&^kQ$$c z*U!)M`9cn%9T7SE+XQi){@Hmr`IqPCeH3EQ=UB& z)rl5f>BkY-R$1~aD>0cWWla$Fes-=|M>QXrLyM|%ww%_}YORurfbW+v9@@=8qqbHh zbwo}TR9#;HBgjZQYGi5#>3Ew>+bj(~veXn#5#7$248Xi}Y2e*0{BRfm@;A~rv*TJx z5(^47HekGR?)0Sb1~dkInlQ;0=J>)9?Y9a%#F$3wuoubi>77 zcwT5EnCaFWtN`B%l}<9Sc}#W3tdR~l$^&WR9u_jVxuZ=T;tu6aBFL)` zT}L#NY4M4M#KS4GJ|6HxkhgXqfrci64I=4M7;g`A7k#nVWYRgAc;!|sK*|!JhKt&n z-g=f9H>LKGXoF#B4j$JzuYS+NyfGP;18kEqd?jFz&|$r_r=Z?|T%?;A z%;cv|dydyK7c~&jxv?1JdVRE$68rQZGE|wBxtnv6| z(kuzYHa+7tsQNofP1Z@3Q87dS+~Bdcs`cpRUQQZ`x0@VkNeWo-SUh5=QV>*K+n7tk z(YCg*m#u0yVea|bulT|F*Wrv0$B2^UGM@uFRJ@x$!lNLu%mI9=LSrqBxoZx5KxRiZ zinMX5Eem6FiGw0zu+d$+_R`qbtRaGoh5+wu_9%KF+q&Qj;J4o2`N22zna1;eDK3X- z`uj;;1MAL`zNqF%n!XeGr?2eXc4em=YGG$ zW$4h?AMI}GlXUiO=}z#~lltT5htF+4bb9N|DSkh>wRfj`*Ms4Z9bLCPzIX%kA-#@a z#}!ZobdjkeUtd;q{U+Pb`pv!fRdby=xxVd3q|QKG^ltMW3iUO6?UU8(@2-COo7F3q zS8rZfUHiD6O6BskCs%*?jn#kkgVlfgwOz z=(I+DretK6+E(twOAAT&4cDMjMfG|;J(RH=01QEG&0K9Mf+cvp*7<=@CCzv9FhQw5 z=8;%Ltw%|DBRKG8LaADjv{l1AuoaZZ2|bV)H7LP&cZN{q_!(4I0^t&$)d+=aYYj<) zFiQb2c76^Ssxl|F1dXP0M~Oo^fjG{or2t!%Z|CG_m7{YL0J3GPLb$6ziT-6`e{Fsf)h3RrE{!hDw1bK2uxD%D*yjTk4FVMkuzUcJ;anB)k6j9g|h zH2o-hcZ$-!Q=|DSfT@ZICFmh{p+^he+mdQ|Ru0|?4s?b>cuHP%LRn;`LxK z19Mh2meS*~UJeqi7UIfR=;pV)smIAWk~hUa!N6VrRE0hPN=cPkUWwwZj1~e3`I>C# z@gg?f5dX)4JzVO64|3d-Hw~1=dutgM)ppba+d99Yi?keEfHJHY2IJgFDWdWY>d zo_&y;!1`8IHGRYCk-QUFpV+KFD*n5>-vqvWLdhKFCa|snp1E{l9CW;yaBFqtT1v5~ z&*8dzx&U6SbZx$Kd$n~#U(2Kq0Nd6@^%-tzZRro8-+cf0Ch*}(d5k*J3h3md3tjz1 zhCUZ+ysh_0BODo-9wBE>>%qIym#^v4S54n2u0L=7`Rl8{du#Q(_xW5apKE!jK6`2P zPhVL5%kQuL^-oqmd2#iPr}@(6yr2J`f`0Vk!~gTYyFCB5i*s^4-$A`N9p;3%{(QtE zI;U6#iYpO)KKHZ0cu`S8g5P(3ws%J^XnV}3gUtZU5Je*M48nds9TRJjfPe`@-PC7` zt%NSm!k@2=QTYBEkweTXuY+%dQP+^Lo7WJT2GB!L0tf! zx|9pxDh%0_vH&xxl~YW`t27N&zwq!g2!xe3S|JE-(s#t=7 zr#WCROmoW2FK9Yb01h_fb&sb3hA19^WTkC~AmN(N91KRMUO1Wy``~AwR$6K=x8#d| z>GK0=B5k*;eYzqgR1>vc1tBT5-fEabN%-RTWSo*OSmV)9{DH&N^wF0sb{dpEIw8j; z(Q2+u%(Q7uj@_NEgD^DzP(x>-RDhJ%TeCW5%eSEAdTDm7SCCLxOVmT?E1xzOKeHuy zfrr1=OC2UiXI{x@SoZQ|8~}E=$V)${Y&{KQ9Wc#L{%H;;LPle&PA6QjUN6Lfi`$@3 zrw~I@Il?KM@!F`x+i*{iPKC?$n;puX|i%$?=fD#GqV`0+RTG z#uE%i13c@Qls73E3w8M8ntGZG2Jol~Tk*t!fCsFX*LQNFC?l(@^+Ka3s<`F{S8(R& zZ}5+DdfE`P2v-&hZWaN?^3jFQ_}*&2UjKS{h76A)hDZJ2wT)e{h5o?9@8oPCz|uiJ z3st7K!68MP1;xW|S&q4032ZlYwcnu6`Vu4!BwV#s$7^XKCuCe*HT>%j*4)cyn@^-pcz2U(;t;`Dh>&OXJ~8JrWSPl$^Xx*<7T^eJ-f`2v^C^Yb_n z6NCYLgfh9GUkXy{7yNkS{A`DK3_UOe;hx>s;KZwJc)m!;5zO4$_zB&5%pZA>$+><_ zjm7^;z#ytw#`?$BKx5TaLBekOdVSJ*;t=LUs{+E~HqteS5Eak-41?Ix_W)ni1#p;c zpFnzM8@yjAuQQ2_Mj_mF2aARl@6L$K zNdJmIfkxhjD`(?&|0##f)D-{CPOC_TBDXrLoC1Oj}eCuj!rLq7RzF1&~>~g3AtF` zK3Y;j!U%s$ z939wksP&Db&{3U;_8S{d?mvENz8vAt%0X4#WS1h=`9xERgbYgVaYVz>QDtuV6*_or zlYoy0@C9>7deby7RMN%=MwnH0pkXuhAE{F_=%^Zv}S(aKKYzxF1 zIzhqrBPa~oc5p-bQJKXiN(xEJww{~1*vZ|nW!)=IznPa<76=A8K%g?n(?#YHdIy<4lB zJKWuU^)eT|Z}QSnm{^j9X);b^V&(x=T@ZG61t9Ck_^eJ`GF)gfpwuwWX9UQ=?_r*DQBdR?6 z37|M4(xj8My>v3`ryk1?jOe`Z(>C}JOb;sutzYBi5Ih#OHHVnsRP)OpA>t`R;oXDF zdQ1bn@Ixf{di@ZFP*EgvPUA>wD9lklKLjh0MUAVQE%e)>y*0^_JV9EcJuns;-MGa> zr<#pHo3=3jUNY>n zv0m^6rI6{BUyVXrOf4=Uho>>?_;Smx6~pgyOzfp8AF2g$#TNrNpOX^YgbhhP|k zlRFGkTuOP?5_iiblkBKG;gPdp&u$APVT<_Sk}=0$)edwxE; z&A_Hk2{1((GBPW|b@@yrNeJBoK$Ew39-9o)qO}7iPibQ}{IId51A~7+s`(HcSwb+Iq%_dgb|Th_}N>%dby^xMH9>+ zB#wQ&m4_1n*%UFLpdu#+;QnW9lR+6G6Re#Nu`szjKF!f(!P(>lgT6hmR`g|nflsV) z2Ux?)yc78B=~GbLSF4-AyGQm;;HNI0`0H11>C*bZrklVY>7Bqk+ouoloxr*YtWV9k zaIW8XxLWBZu-*wQ&G*}MKZLKbz*B$13z!o=wZyetQzTdJQ zwe1{WbT6%MwlV;E6>{(|`8F_$b zJ3MU4%g>(n`5D|i-!kY^z9_)^{M>{D^7+}3u`U(jX>Z##S3wCx^SB(;H#GJVVPn6X zu!AN7GZkPB7j%-lc>Y7p6a+fWHloKfs+~3)82Ooc62W*+29UtK-c~EBD#r}4VF**b z2e_s6-r@!kP$y#x8`OH+A#0u(epOMcBM?CEyiF!fiE0`KQ4A@tRC>#ovk0tZ}YFd6I?wNY*xAa?-6TEk45 zrg7#k7^wR7k_)5Z;I+OU2iJs~`?yX2s25wL7A^C&pw4~{tr}7hEp{>F=$D!dy(^sf zx|iuiJ*8Z;uCie+3L8`{*30!D?8)BP0O8kgZGCYs8S{7mHyd$hem*$-s2u#(UE~Ru zschxD7@F3~YeN~~*DwM!1mESQv#89XYcIJKzdDXH5JOf0JHX6`p!EyJ+U;eJCLH?O z>b(`FS6kyN`YaIo)kq@zmVu@9sGkCXiwO2c+b{*x*>lZmev!jZkZ}r|^$guuU&pXp z@R}xWsp!?nuxVS6R287*cRB0fk3+cQBG?*#yZbn#D*P6L1kz{Afoduu&~XAdFj>Di zx1c)z2QMO?@YI`a;gL@ zV~l3L;x#iHbqCt=iDLQcc-n%R9LH`BRM~kx{!oHiAmahPt3g?ke$v%k+_0k`irQ7D z>KW;#A5N`^ef&&-KY_4CQ=5(R@i5Y_@_@(14cF@8!SQ3ROrk4@hBLWv2uW`>mjYq1 zpT&`{Etz%{02XFGGvZ*Yw$+NThuKFwVBGS%;!~jY9^fE!6ZrPd-Z!7S?{@+p`AuLc zJbQZk*S|gZ&!BZTNskZT1U}TqL4R~(rSCvmTf1$&7Eg88i*)yq|LFAAE&Ua=E~j~~ z^68V?8ZPfJ>z%;AJ)(C4>pOw^{HZ2r}oyr)-R+pC+^X}T5s++%!O@1MN1`tSdA^-rJYd(db3z-T2un*L|+Eqk8oO=F=dyJj6C0Xd3zy(Rdj8T&r`a+F{SnKIe|}PpfbKiY{^s zfY^QFPQkX0fEH~$r}Od~uP^Ee6m-8(H)R16&`y)TqRVG7kwM%Hop_>J4tsmG?jjJ4 z=QZ^6<0#iCzZ@3SGb{uP9X%2_7r@L7^cscDwhSjq0DhqoSuCV%Y)sXnI?MKF-Y+`> zmAM=uF);W9>sLidTowYDUYn|s<-}I6azsqSrhojX6LwEjB`m{y;xY^eyV-&0qvKxq z&C#&hGhMWc*Dm!UhRJRg8mA#+Gn2x^Wynu}aCIm{QjkJVejx|Uoi-RR3)P|TF_Kbl z*&E)Sc$R~UiuZz_L1@xpY0{Hx@f(hD@bjSZtRMDE^(2 z*nZV(G9wq+j&%K4GELSCUd!~(BZqWVm>J7j$3r0T5wZnUa!S{y49$0e9RPN#bm&P- zdHmXUpv0Jhs*_(FC*8hvX0F)54WiD#bHm>CEH&7NM+IuKq~r`y5{dy|r?(kX^BZsG z5SVms1gqnLha=6oLX)4QslH(tQ&>?Jeg-2#8*{cnMXzrK2tQCnrpD>iwNuuM=t7`~ zpzh#W%S52MRv}wJ+Q?FH+-)7p3aux@U-+0%Vpma&!=|FkP6X4#4lzRPP?NTME(TC3 ztUHF+bVctn$~yHg&WEM7gX7$|)}uMM(t|EV9fy1HGIjkME@f^SufcOxm~mz*7DM9v z4jIm*MN~aZS$zeWA?0Vs4LyYb%8%MuuR8@I1k95jHyPk(Vj0LYSmE}z<=0^>^H`CF zz@xsm#oPRbtS4@u>8&a{23|4y@nTM^kRY_|*JIN{kHk7+xq4KaO=0;I=z+NW!OkDN za8{pbJS>Oo)J@={`#5NQ70}Oqb6fAKJy3w|{eF~p0-xHwr&hgdSASEjPi!7k=g(}t z^}*i#-2~PVwkMY@E`arIz*~E#Pi&n!$)AqvqF28mKY6t81m4jbAgAo1|G4vyvI2St z>z1kRk?Mo2#%Ec{_yuhGPbhtgm5%?@r~K)6d;0pW)teuze)U`ay!oB04AXRZ{M1GM zs`)41TK)OUtCzmQo!;~M%)IR*zTbPND*f@xkNlf||Mn+0cJFb19?t|##OapPxwiWC zGr-)B^K+pA0UhUOzo^Lbs#*FKf`FspGzN=KPVs(bC3?LCvDKOuPnd$y-QS*X6UWX=caKAe)SfLv6W6Ig+X3MJC@Ux#Z09`eK29}?a*0k z)8nyJ;v~v^?dZG;My%u+8So3=+m=siRr8UW1z1mRq^!L}E?TnCZ>AE*sZ$>1($Tf| zKx}j(U62}vW7A<$IKkur<7npWQOijDOu3%L<8%m}W*O*lW8VdmL4Lh$e5V5Sa0q{Pq8bG1duZlyJb<(Mic>GjbJ%Fc z^C3lphH7QEV%ebe*8Hd(LFwQyWi%eU^MJ5bq~i#6*f1+vc53O2t=Q9KaY#l}vGEKk zuYDy`9f9<(dJIB1It;xEgU<0W+pqAf$J%-s?uDesto`Ivdv|hiIQWemcmtc?1e?c0 zn33=4s(cNz5LTHrGBE;N0O@JG5;Q>yli5W%YrULb4j7^NO_{w#s~pve)@c@%O9kF_ z$X0MVIJ686TrdL=6o=;5d5fSp^%0wJ+G1p`5%Ki|_A(dFN=IF7H(>%qZj#d8L@bwKUKH|;p44B9 z(yI@QU~Zz-z)1VgK+B^=(BMRiq|yUeErF^Cs040Q^b|hnkBP<$yikN5Tt#adGwiK4 zE`a5$FS-3RH-Ys>jCxu8>6>KgO~t=@qu(aD&Zt@CrklXJ7Cp(^f$!0L6L|SfU_Q3$ zes2Ox3ZJ#R!$q&|%j&bQ_&d+-t&i8gaQFys0)Kq-_$Kf@R`wtIv<_qa2Mrg!dRy;J zI{JT^Jk-Bvsp&zdTe!LC&Aa_|cUqrirT6sy=AG5sANpI1a*|rD9($O-aQ^W(SAX_0 zA8PfL$N8jyoO_a&GUa=W?)lLD)K$>ml05O~{953g2HA2t)IR6;IuH94-Y3a~Mj{sP z3-6(ydGqSU+k*Ggv>0yXNoc|(sBv94l|5}&7jf>QFLm{uUhb&+$-D&8hi)} z96Zk#@nhV2>X@stXdd#zoa-@ZnGtU|F=EE6&p<_@jd`oU2JLI@0u7Hznx(~InB z@OjMFaIP0X6BU~|(wCj}bv+%fkB8txRW-m(KtK5Kh+jYCG~0p}O3W|dm?E6G`Gq{X z#_Iwz zAE%~y(~_<|8P*&f$bw+sEfF-z?1;w@FPlAG1qmW<3;N)pVX7aw8g+sMEIr<5Z2m<8 zSkoMs01T}^dTjTD0=sL~9f!sU5?pQ9^mK-r#=V9G$Jn+I*wWSx7v84loReo$S)w=0 zY%6`pqG!g8#R8aPI2w8?O7v&|m30cGX*0{{(@W`x1P!D9UD~kQ-82bQY$i*;d0`2c zkrtikVH)$~&V&=ME%MxLxkI^e5gz&(&tnJ6#sb&~uD19T=*(+-`O59@KYvyqo;)mv z?C9c99|x@uwt3`;z7zO~izj~Z+AY2B@xXTa#GY;f@9u4%KBdLFN7F@xUa~*@(7c=K z?*!gG{7qoR&{wM5x~&AYHrx70TisRG{a#%OE9HmItlb2@adh7atXqP|H-Yc5y8i&D zb>Qh((t8JVcF5A;Q4t5@FUZM`3U%oTf@ zE@;2`3}0NN&v5>szp7W?S~R}(cOyF4ksGJEtPI1(|cH>RlPv7#cPc1Z5~uPz)UBo@%&h?ADY-hQ4c)u=Ab)( z=AZHseIbE6z^%!WGZ(k43OEkJeUB{k_jF({KSx#Ch7N~Vt*W17ehl~zxa-B){Y1=S&sHC zBawntU(*9)d}azCODHO;!`tF4Ymx2Mp_;-1V$_y|wHeWZveD)Ma$M)&!$h(?N ziH~4!qs9r;YPLS{M;!ynv2P9=YbbmPcL~MlMn*+k>l^hBIgd{gYkrqW^IYNRCyo8$_|KG# zy{weN)oDR?$Vx2_l@Z;Y$xoDJfe_<19D*oo4Z_?x;?su@(kwC#-ZHHy79|1=Z13H{8?6dXe=*!b*Ss1{od8p-(Tjltlqq` zx^kUF()3wYUwdlxPrknTv+wd%y)S%e^~A%6{Qzf?d_FgUCH0S9dia0(3%(Y(&WTD= zzx{+dtmB-y@p$X=r@b@h^QV}{$j=u!t8>1UeV%{E8F-p%KF>16QbqMHA%l0UJQLMZ zRiZBOeU2xv!_C(ZrdsN$G?pZ(#@L3r)CLzp6;cCUnFOEEGXO6|26{M8J)W#k)@r7u z8my^b*N54<0G1~|-DV_BxaJXOI~)I^Np1RK=Q%ZEMi^1>+w|;vU_7B^NbW@_L(zMV zICQY4BUyO`Q@U%amLd2KW4)b*+?&fB<|h`f|DbQ$R1i!4d2W<7rFWbT!vGKw@&j4D zEbeu8@Br5mPVA8to(OF|50acCBnn$v%937r%5hO3Xcm5`!>t_?CAUZ1XL{fb1dp0n z0imWbRKNR>R-c|!#4_c$I0f>-0z5EYlNA9Shtn)Xez}H-GS_-R3!omwR@ok6?R!4z zK|&ImF;Su&YzRSj(mwssE*GfT@DsbfbmYCduZnjgEEmR>sHF@Ymj0C^MzhVT#1 z@YJAp002M$Nkl6n#6C?o!p-2#SY!3F$yClzDBSVu)+~atfa9 zLJyEkh13IW>{`lzIACEtX^e3q>^&jP*2mA7!w!dkYBib6dUXk8fJ_?0>8RDW{^rnr zP~()rJZy?25j9!$Z)ET>T38=89lwti^kQrNid3GOD~03KCm`rNUgr4_0)EWphz2n( z2aJ_eszF*Z&K3=Ddq$D2_*I!(urPOhF@X`GHO~LQ!)jeMQ@0EV_23_5h z)`vFhZ=3ZO&U}{DM|#IWN!0s(zx?>>`(IoA$#?jw-fum_yL{z!zfHyY+-?Ftdf}x0 zbVFYY%!xt|+B#SEnJ=f0oQz2$y*jCIHm*}KCr|ybGpai}^ZJJ~D-fQcGAAHCA`bcr zE^MB^nv1>hR=5a&r+@ssg`0s5H$TqxY6m+y%%5F|!7v9IB=ziBY{uj1IV&-mv5ou6 zG7O7y;;#tetn5q}qwvvXd`|#}e-yd1!#MI5YTN;ayb@H;O<0F?>_w?H&V=^J8r)t~ zx!TAxC()dc`N)_l0@38HdeJGza#+UAR3;i0ytZcXGc+s?7*1`Qp9vc)XrhC6+~N;D zxnS>uSUQX~Hu&Xg9v>$r!GSc!aajEO;`;bR4AH^6OoLw?&3W6$Nk8x;tg-`9zUg@E z)I!K4%@HywLqun0k=SyXEXNKmP+Zv}t1GvpT_OtO0BigPRotSX`oZAU+O!l&+kkvuPKB2)3cex!6h|Yi&oPjUNIJ(vv($%&??{uUjWfzR2ZY=_7HO z`JrX5*CmN(){jRy8IMO+5Y;Xo&RH)EHZ3N?jD6XJEWNfip6U#xcoItp^G6~IGqm0P zaegzT^1}~k<=I05xCE7Pp|a4P#H$k1SPeoOryhirk&e?zXV61jgD_%Yu z=+8$FeG_=QzO%@sJN!*xeS{8g0KUD)8-Q1Pr%viin0Ny)tK-H^;7jvu#*+QJqy0GO zM!_S4@SMMSC@-=Pp|&Mxh{HT{o*y<-PIp!=-TzH{%Yd{7rpw{qBq`M{f)k= z_ubXI*U+D)M~XhYO5fJ|$1kq_#drBot7k6pRYsq(>3@_yx0}E}{yxnZm0*g~*9oTlG0D*XbMxC_mK#Gra+UcQmfgp&y5ZQPc=hJBt4x#bGkg_&Z2hY>( zq;(|x20v`HH<^cbB>{|BUr$c zVTeOefx?@~#*P&4usLB1a!Ev(-%bEWh`e<;4^xp$c=n(T!iv>+XI50ULq(txBz&21 z^rIoP9mn;QQ;i#+I3{Xj`I#9QyxI>(=wpJeWP+e>L&gYXnT4kkDKCT-wbQIRGk;Ii{N@gxG<0(D-$ELh zKx{V?w#9gHG)?uO1>ba;b|og#A%aYl7YDpd>@cW zxUA++(5zSZnI+#|U-SE6SPmr{yP3T0<7aTgf->*Dyp7L(v;GDqk$LzOn*xd7;>E}> zXa`^`LoJi7Hjz=Hx6S+L8Tek8;xA_L=kONV%bZn;ZfFQt^big`4q?NFpmJzr$VLMh>xCVc9*H%y_W z2i{CF>bF{YHFlazEb_&Lp-(TunWdcxKnpzsTgWH4%wt6D4BQrwF$cf5``EMJ+di>* zwR-sjy%YG1K0gNV{WQIX=AFPtcN6&WhxL6(JNg6W167klCH zuHEHLV10$}!`1IO4fp6a0yLJcJ z!|RY8kssd#K4h(a@33nhbIX@Iy$2t&zh{B^SmwIuJ-s^R+qPFf<{s}a-dMfbg?S1*5M_1xoJuj*p>sG0)lLG%E3j~_q)Ukm)ThyLyV z@eaPq?T+W?oEd}i(=PCIeERhHzq~n7&$GKv_pCbjetoEF)!Dat9zvg|2lwDG)7tqt zk!AqXmLp*th^?QmGm@}yj9G_~{@9spo!;X%o-WjLlc^GmC5SOw_}1eqg2*S4g`Uc4 zu$tBp(F0VC%@WvQqAYxx-^+(!`DIzF3$gtxhIeK#b-gUpX*($u8#-jsBAIC@Dc;Jx zDa}7#rc@`gQ`Xup@QKSJCA4!P%f#(%mO_*L@)1EHImqgessw;JBLk=&H5A6- z7F*+qYkUbnsQFPu^a@HpbKR?g*ht1nptqQ_j1xCJ5u}#!u-aBr?z0KfdDluMp8_OP zXE@hOL(~VjK@Z_DjgIjO=4eX^VRCkg*r8{-dGO4K1O%z`q9da`QpvG(0<}<{#Zcnl z-&`+dt?YpHBIn{jy!JaNm{9ZP|~;$bXmIN@jG zqs2q7#>DSCD3ZXspcZS!wT-2&DJx=>*?eh zKaYpd9-=wN5PHtL11RXxG9MF~DG?1$DT{D}1P&ozR0{a)$C`vDCkQJ{(aT zd3_UlKL8X^Z4^|&oL3+JL(j-0^=Ccew2oiuL9N+45F-jo_!QLBj-S#5@0wYLf#3r# zv8K%m%GVN2Ep*ZJ>dYw3ToFAKypNw&<t zl+DX(!rgC^DT-w%M;DAJ~n_%xgly?HR<)O1%zk9DgAn0zQ?meg5%ld2Z<97nzyHZ~O zgbpg*_5DIME_zS+PVZ@M_NraKv3l#n)h}OPz54d*@&_wj1M4B5_UL&&%j!ojtp4Tq zd2_G6s`ujgqrB*?FufapHqwUAaIdcg{=feE!#CdceQm9i9;!L9DtG#IR^<^qPPkLf z;>4M=@dDq^n4rU(lS9$_>5M+pp|7WP1F$4^?P2!G9djIdK2zXYGOu33ra8=UWvh`x z+sYi?{cJU!vt%k(nc|NFc(;0*SuapeYM)56oO<>ddYo~4qQ?T_MBJ)Op5?11noZs4 zG+uk%0sb~aTB<_m(PWC%TQeGIfNhePISX+=%OsY(0vlus19!GVcf#S5if5t&XckVt zs*sHyQ|v}Q^f8s)RIDG7ptU_|2UH~p4FQBweKRhf;*2UBnqL+;8{O>eOGI@CQ6$6- z?_yfuWvu{k2cJ67PZG1&2=gS^+&Udoi_>K?gDp5PZ^GiwKz2%?Da;W7Y6Mj$GjJH< zDObq`8$Br!c&I0_+LjdU9WwKK9>`d)@ER8Z5nB9m3gviMMNn@;9dO6@T+3l<@OFY; z%}zF<6LpGlWk@E6RgP`cxLg!3{*2>gQo3!hnQ^tu)imBd20Gn|7GEaiM?Zdz$LPhu zJQB)m<_rK-uIi+b4n}Q_&%idrGgV-76FpueY~Mk_(C5K+um>@LM51~n-zKQc2G%$~+oUeT4U25n=!VrR<%=SbKU4J|PRNUw{ zea+y;eAZCCf@7@XE%4w4Hzw5y7{V-Y0{fx^BSsqA0idwseE3NU+uz;3)7{j06L?$S&wGzJ`~ma!*2VMl&bB@d`tp^X z@kzD^`s)m%JKKH(FoipHVr%&Z;NhbCwEFby3ybdrKEj*8$L|Clb^d~P^uH@Q66Qng z_as*`^rm-R?w&itrLV4m_4myBvZ7!8ZuOu2Symr>G(W)k!dX7Q>IW~Z{_K0JKm5k( z`KS0EBmLjd=g>Hnt@zHf&!>Is%jf>h|Nb_y>SWv~oXj4y^ z9MURGKmvZIu(HyV&{5wKD_G@l!1V}pnsr223yI3*>nrpmd`E0cq{Nl_j6Z=Mq?L<- zbs3Y0#PCB<9nu`neUXC&5m~rYM_j5L_)uuqEz&_VRq9O--m_~Dc#P&L=J9IJt4sis zI69;jh?%1chFd?Lx zYR;d&S=vZsTfDQw;K)RVl>h@H&F_)PLlUSV8wrz_?9yN{1&ytBB#hI zkSt+=x%lS+U^#Kduj^El*S8wFb?2?yRPtCfI4d8@n{~s;)%_Ha@gD53cwTGAa607 zQEb}7=>+INp9F$31wnBz(rJ6lkjCtyBQu1aA&`cQ%1`J~|F}cDkx}DI&>A}g5o~Rm zW9WR@FAgSN)`tnxlP|MAEnu=97r_AL1N3A@b|`D*D+Ykpg9Cw0 zz`*6Q(=-meX7$6wh+v}T3lK_K1ao<<9}kj3Nn~rB1@Z|qG(E2w0`!m$mKe?6JU~2! zfvnV`!W1#s>Trxp|GFNGvLq%`fst>A_GE_EGa{vvAl{-gWEtvJ^4ar`KDR(rS8Vz^ zpKpKpzTf9JZt3uqp+|8OSc3F-%Rl?g9d82bwZ7g7yu+tq?JB*yH~lsB)9W{Z^^re! zy9vCv${T=n3EFP}*4<|QbkobY7Og%Gx<%;gk&f`4z{fX%*J}Oy80f*Ji(CDLv#uxm z&j>bkaUvr_Rab%tM@;ecc*o2%m+B@v#efP{j+bc zzVS4F@O)Gc*v+EcVXPYF`uuZ?`=!TD|BwIM@ARKp^Z7B4R!+am^YgIM(IY)i5IGa8 z&YavEFQY&UgP%}r$dtyx2WB|leXcGdG5FL>ybb`2@KX*`8vFEL_&g~XYIvWS%wNyf z$g`uFraR9jp&3sok;Tx@N1-%t}KnT5|YHl~zTK%!{THl=amL!RdRBR9IWwNs>E3lTh?7nju7js}NV6L6SUoEOdo)R?;ILcxVFrjP+hSv9tH<$h=-Aiso-Vk9 zW}4a&)xY?eD;pzhQO`OV7!P0xtzpYEUI^5U+{_WZ*l-6BiwWs2=pzfa9M-|lxE&2& zn#P!b&-Jq18~|F5IsoHP>y>%%{&hzWEn1WWuVKrFP~c3nuSZUJiH4qv3AhdI)t3t4 z50kcO>+l-Y`X*1i0d~;};T?fwM^8QMqXc8M0(d0z7}f$z8ugY5lda(Lb0_d=NpFzU zM55rd))om6KN?MLC^j*vG0CnG=HEyOId&@thQpExC%FJ+Y~E}Vz~>Vp_D{KJmS>K# z;vD|Uws-({xOr+85;dMHe&azBwf5!@G8U4lY@HX@jv&51)y#;@s|`lYw2zD&54Jd9 zp_UFZdAOW{E|@V}oB}sKtmVrz6U^7)<59yk2!7NP3;67F9R|kMfSJy@-qyf_DC9C} z(3(u`h8{CwTS5ghjcmO%5nl0I1a3o5!cRTU)EmvX$fdxs>==HL5)h_}0;dN2n`Tfm zUG*K>D8uc7F?2mtZfX#F&XZLGn;fNBtjAAPO`rI+V(^&F8#~tXFZPT}Rl(XlZXQ_= zJ&yutJ>pznoGtsSE*DpQ&o%k-1>g(3%_r8AS+?o5n6O?xX z>q=Pf2R@Q^>B9DZeskyQ$1cr2#?vQvuirYgv%7U_Tc_@Q)9VIZ#OkxFHf{pH{lShd zYz}N%?A_fxUC-!OXM%bIus;HNKc1Vwr?xJfD-n9ju|7BJ+8t!?cfY$u0*>DaeD@N4 z7PC6P=??^SFn{8&?bRye?*(+Jd8ek!W4#Uj;Dhx}J`ZfqMej*Il1jh&Q)h+Nh3+eF zt$z8&>J5E>^R@W_&blPl`*^?imDNA{&g!4Pw0iN`)t4USQu%Xky7sah#@ zl)KOMs$1uW4?o`fe}3_yQsz;ru@;!qYR0xu4jXg6WT+N+;W^LXRA=3w0|Ezc;hU(( zcvf>aLv1sfvw)znrC1V^iTn<9I;g>A@f>TzAQ!BetVitOHzgz)ngpWZpedThphhcq z<8f|0Ap4u5f?}Hv8Cfd!MDBS9aHND|n?He${(6mW7#sPsj&9=MMH0<25M}lTcxa4f z{K82u3a!yd9M`jCm=~rvzz;;5W`;jTCe)%~v5m2VR8T{`3BR|HPW6sKB>44Y)Kku} z@U|Mmw1W--ITX;z3k8?LlvdKA*)x@lyv;FW08^v51Bo%y-VSd@OF=z!tqjd34)m=m zTrx(903Mp_5$=x)gzdK1IVW zIv`w_!#~z5<&0yLECq;TrdzoXqti{$91n@YOwwcPQHJP2NpBk_l_{s)7__6^Yi^NM zT{y);H1nebfxV%VmIOBXoj?b*YYANwWWSndj>O7{d`g1X3&PPN2f#3`B~?Ug^vYq4 ze{uXc)MPT1>)Ex0$Z~RgGN3wY3nf_;n~YyNQ`>?wXE(2!N0~}_;#J4$LWv*RS+rgl zj?dJfb7^LW>nSe?+z@c?S`aOAxd{C9 zoP!pgn8!9*9jZ3?mpBd>tDZm@J(PjD%($Po!nXJkCX5H zwp-o_{MhsJr}!&qFVz8(H*Nx-KiYQ!AAcwC0VV%TOuEX| zm1MrbNLRo5KOOzo$!MC@1@Ikj0vmUy|56zwpQfWrS^Z(Nu3aza0#YB~yvGMP|K{!0 z&-=5iuJ;Ex>qve2(&{_@0Ovn@nGbN*=Q*E0o72*#k#K*$Dwm|{?Zl5i%+;^1fj^%= zvEHvz>+-++hj;2Usp*`4Ie&5<>GS2H$3uNK&a~}Rc!qhs;g_0qt)xi}IZH#lNnd#L zCKjxVFtbY!|9S$j0Kd475(A@Z_*lYIdUA)V$7wD z>o06)Gx-O?>M5^VO5OAnw~rqoNInS%YbO$JZ<%YDDi|L@1xbN4z=yKADGOO-P+s4x!u;S71hR_{bnqTwbkK`KR5&>O} zk}S93F!eiv>*HFXk_1G#S%2$EK}Uii9K&_}R%ep|MAAPR{B;u0Xgytld^owVMh9Mc zu!u$~5lT~&$fOZ#_=-m+{Of!<1~NpzU^hsF2?U#5yuQKP;3)Lylpgk;1n)?2 z#?%v;Uwgbbbk_$e`w+e*$r%Bng2pKve7sdKJi!O6T?rybOVmdE4#8yj>2w0opR9u@ zFr?^cJsu}qNW)NOQ^$j7Sd$dVAqebSTd|fWH2v6VE-q{l>coU*BFhbNj;^r*?L>Z|`lLWEt<)boKK3 zJG&wrpr%{!x;oOeuC_ct?%H&1e3$P5(%hMP8U7#tP19NS*AIY zR1V|^4M9D_G?Qc33kwGdn^Q@8DM8_hrhgn6`e}{OYC@*&FeY2z$Q6}6>yRQ%3nI=U z07IOxCi^O}%pn9Y8{x`QETy4gCN!Ri^FVgcB#?l1KyiCo!*V>MV%>mgQWpDbpKfdw z+@>}DIWgdv!1!m@#mL?$v|8%fHtUh2>Q9=OlWwTQN3j#V4yry3{K64@MaHx65fZmz zH7)eT?=r}>*Vn?(Cz}Yn-p;Aw!%8evCXlv;&m695DAE*ry8H+isyI|Cfd?NVTPkR2 zAgG$@2%S(%ejAYmR6Js@j%Ta^`)C!QnViuYAbz;Sd3bihav6lhk3zDW(ZOI*BceN# z$@r`<#$p+$O*90wI)1>JH0!%h4(tv&)+>t|w-L{sdT7VN@>xC?k)Vn*BBitO(AG34 zZwWh;;YS1x01NWaY{57wb&H?ra5*ln7(842BPWC{ng`n00ed<|l?p?Kiv>B&n$FCq zFddmnPU|rUJ3zWAZE=nJsDUpgmS$v_r1XZ&S|*xp1%^lIY2u zTQ^RhefUl{fptaqX>J1N<7b!QAGrVMU2g*GcHGCePVVXtp%3wuNV*BEcLM7Ju_8v* z(4Q;6dv*OXLUVcpFrR?6b!*4p0L-78>L&A+E=5?EJ2bt`_}Rx6-wAwlH-U9SUVjCB z{Bh8CDExz%b&aaOYUWPwO}4u9)mL5}rrqNvu#XP0eafakqsX0J-Luu(Wz{~qx%%yU ztDn8Ldgb!!tq=4Ez4J0#-@?rYIDdoBviji*tFJz}x^({YzR{Yu_3GP_6j~oBt^Xs? z{{{5p>{AxwXx!iVaOdCs)%zcQ)PGJg9>{$@~iHA^PuShdHW+3sqwv)qK&`J`1Efn}+4+r2>&^#3&6udT>Bm$bHES6(U1ssgQB&MdFU^vwU4+N05m3@twDGV$X!R#Ogvs~@3P01if8ZSOeO@VB7 zI6DOqe5^^|5^PY9ZXj+u-vnEHOGn2-4W@gy7Tuz7(e zU;e=pq|XN3Wk$cL3Uno{4`6$_7^X0hP=yzxdjP5qYYyf!Xa1knLu3Inn8W zLrg4%$%UyWY)39!CKYDv-6vwTVho+5djkLVq1(-7#xZ(=O@_<*i!1g*3S~i&5~CqF zd#)TTTJu{suD}22)88I43hbTUAN$>}oq6a1-U+jL;UZ|{6? zJ?U=xpW5F2=;q1Yz3r1Hbd&ZT%@01k3vmMVfmLsRu)A@^qJvDAL;A=Zzom0aS0niX zq;chZU>IE*=|%s;=ZajH*0+xCoxrN+lNYD#0|gu#?_L3|J|F9?xAorSH*f1b_^7%o zkzDTb=}r1yk_USyun#jXclFm3x`5<=c5bfTe4qF9>f@~RoxNAC&kt}G;OkGVe(?3x zzj%4|lW(n_{}O*=tp9cToEvZJJv-mltBZD}|HW*tzkT~Z{C`(2U%8c&XI}a) zWBUoQ=)vPw1W**aO|V-)%`-~@3I)9I)mg{^*7%?Z)A*F4V}(*S_y@@2;#WW1a%mdo zXMNx*Fc-jv#Z*=R15#a*QS-L7Y3NYw>%}Np6U@mMzNzFqvWBh~G98kE-^H+y&|+!z zd7UtZ0@$Nmz@xU9*ZCV`0E~u75lWh0le`RK2(vojHzZD#*{Eia#Yzx0bDJRc+GaBI zCDbNIa)_CL>$j*^C`wI7X>n^&7zmKG)B)Un8~kIaP9AMl&;+P#nq6}XL4)7%%Auex zpl`EKUFya@+-9*RR56_c#t$BfTgMNw(U6wr9D>>A#o ztS-lG_$zvlYj_1AkYi{MAR@@14D673x&iiHXdHUueul-%Bmul$bR59O z@+#_~V|0wR|Ne~vxh^<2zwn7af*3Uckr6!BrIuE1yOq_+v@$I`Fej1D=6WsV6ii|& z5sJHZJoqqxuwx_v@bvg~dh}AijbU&oDj(x>!1Q6`IuSR7+9pNq(x=`LAePbb10XV( zW(FBaP($m{4g=w9-%!V}lY5C^{vwLMEC#iz<|(?4=Eoyg3ko+QJ5T+NQhH)7NDJxx z$T;GnuGpPSfbtfNngXSOHT2`uVvG)C*1;YaM{`~!#&l5ncR*rxK!-zA*a<|R--Gp} zT!j}7u0&{hjZ={rYFO%Fj#t|Y-G|@4^A!$mVug1c4;&XnuDF^|3ppM0#^M8j+1X$O zjUKGpLT6K+zdR}$s}3+u_H2ilZuCJTSnU$X0otznoIAHppS^JAp~nK+*k1o+@1?Ik z$UA{`BS^1<^OuktoDVkCHSkYg>03AJ6e@?V9CQBC|!qlsN?;iDxe34{$qlR z-dkMss-s~ZF^BR$2&DfUx!XH|y+j-TrE(ArHXSLa{hnUk>DA{#iB=-@twq27?dq4m z<(BXA1Dti${Z)OI)z?;k`qJu8{(tt~?8&a{O7pwO1V9iZF>nG0i6SY9ltf8Y)#b9w z9bM&Chu{3Vx?Wk%yO0p=at2A*CXMz9+3s#Mi``mNy$#d_`?{L@m$&=hD{*pI7)_aUEx~q@%9{uWG z^p47C#eehml^_4?lMg@6UjugOIepG2m^!Vq(^e0(@mO}pr|CLB*XseE4S3 z!jB?5Ir)>V_^6TkQN>u-G};;O6wHb`Gk{q1O(H{NFk@K|bRKkJv~59)&_x>V7K}by zXeCa4;LbP#9cki%0k2948yO@;M8Kw8C~<($&N>h?1p%MTt+V<=27)|Y37fqr#Sv$> zmLQXr1%@ep@z8+U#z{Dc8L$#%#32*1(`VJ_8KrLE4h%g%y}s#(sc9XUnASzS=8w1} zSG1S1cksx9QyU9G*D_38GeCk_R9OVeI);{LmP~2j zL`P?W@L1vP`0Dj~;pBAj1mOJC&GKU~qZJyHScU?tI)W!`9X5j#Z&Xu*Bt(tyqiGpq z7KI?Sqi2{4gqPUG-}N-c_<-Gp+Nwz){PuGq#&j?%TFAg&3E`p5h6>9Nj+EBxWsog) zO`*{_3+k%iifl7^zQ`QJ_{w;ZU8gB1TNQ=Un7*@jIRH2k^??dKt}ynAcXmaF9pp~^ zo@U0It1c*>a=?bu8fRj;I5U9P3kPI4b5p`#D@>kUmIdfoUl7@5fI1-TnMaN-q?^Pm z`2^K~pvl3eVzLTnLV(iK6jD$!tULKyELh_a84XStqhs~)j2?&fL=z8`T_K>P$=4KC z0t)wRkwV|9DrnWy8mtLeMMRoL-t}Qn_#$rd6vK~N`;vI;NpwiroI$$e8EZwzfzi>K zKBrFtKlZ{QeYkMf_8)$K)8<(ACRZXSZK`YJQ~liBp@uKf8VT%F=;#)_=WGR(0Rl zfY!^h#O%@6n`z%afBor4=O=;nj_Y?1bDP9@9| zZ~AfIxg+3!R|iS`#IOipJ=WdyLPhYbiM2%#Z562N!XEj?J5Q(N9%D6-00UR>R03-k2PK5<)_yK06Oo!)#LK|R&-&F?B`dztC^{J;t6G;F zhR%)nsi9>Qo~Qhfl!K2INkQQxT;q3A)GhPb36TVgaKs%;I6GkB*VY}u?Vlr+zG;o1 zk;TT@YG~=z#vyp?il9O3p{93lRsuN!20qau6Qek@Ij&)hYig*IL)WwLp)K9Li{rAb z@|(~y5a5+cArfe`U4F5nKk;il7{bG_>uLEl?;T2NY%q8~mgh1pjtt^vMVhvl!*2}^ zL9b~oY~blo-n0S%v-FO`f({vpNYE4^v>KO_TnS~Enc%`!(Y4Dq>IhtbAmTk*&zWYJ z%G=@8Z#{(RpoW+qiv=(OVN8yMaXds40wUYMa=;^gBo(fb8yLa?3_P7mUq&B3P7gC+ z;0pm@!ki*Q#%5Nvc(lKVy;8Mm5s!e#65rYZ6AjEdx|oq<8NDw7kzqYVA3+TxKv~4) z1S7yB2+i;06o>>$2FWnO<}DqyEvU>SP_WFDK9JEHZ4I|wrVbqeE*JRLpL9_mM;iRx zvxBuV<5}8F#}2&%q(xtN%#tW}fw}8br7n8#%+x9eO>4VmYv2CGkCS7`H)ym0A9$~V zhDkiFFbZT~cI6P+#KIx%di|MmMD~ut&Xznbb{?PTpd2mStc;U*>(SoSgTF?&6UO_r zaLHKmBcl+W8hWNGVT~7oSKQ=L5*q74=i>aC>_*@U#13K#>ef+KtLCyP?mpXcQ!@QvI0B=E&6H=aDDw@k~AO*?(P^GBb~&w#2z zTmBnJx}w%QQ8lY?+|_+%>UOK`;+2&yfCuoPZvyLY5#L(Ftu+2|&hPQDULHSR$ac${ zz*?joH-UBIly7f7#+M;Kc!ck-(r<`f`+$%2{{Ad?eRUa}O$U!|?dl7h_1@+meSh`J z*H_Oziq|-(zL1o5k$&|**1JpczJ_1Def5)z+yC?b@xB<Ro6fQ2kq+(3#`J3Pe4h zzOnTKUwhl}!pQOEV+^~`t4uc@b}%~MwlSxFGbSwT1S6#P?$pTIJYk(QJyOqcS}V?u zwE%#(E>A_CHJ7tqB!cu(7h$2t9%`~JQ?W)lrnEas~*-WxR7r#7RAV;3w@hg6_3!f;Ra1jh*X4x92aZD6# z4|>*aYxGEM4?7xxL+%J>Od8~? zsfyf7Z~vu(nZ;}UrDS=&g_gM9XHhDM%ZVUz>g6kH?W%{Lwnc!F9(DO7@R^q@v4Fe% z=+o_&zy82O$M(2C+>pKZy7Q(tN$MS^d=hwF$leaOvYt48=$&)h=PyX~9-H3$e2I5K zZ|J+AZ~4_bS{D6#^pTm=@nc*7>mE@y9e8@}pbIM9KHT)xul}&pc-QnE;TI;|d(@@Q z7xYPBDg5V80xycqI_f&}-app6WvTiE~^Wl`y^o&{ej$XKfU@-zPb80KUn?Q^W62-Bj}a~^L_&E+OGFh>x~=Z zul0VFKh}GjIiCA$`?dG3{q)zL{y(pNf{RW^KK0Qu%$c*!pE+Ckti5*H^63!=b+q(2 znFM?NaGnb>FrLtj_jx#Yu%OJcMsJT61Ym5&w^yFo#;cm*Pf!LXu7({VKF**vQ-0M@;ir8=tzbwm%XBgFJnJYeR$@WNu(@A+9X_k3!3u7(8Ys3QrjZ7ifP9k&EN;d zBLe4=;X&c0*VGGsTNVj`44oC!zz)_Z>oS96S@hIaNVL;ZogG^eZi1|Dc@22aCQb@t zPE;zXoAHmRj&1(XM~}(Y_@j|?2(F!*All>}3;kG-pkDApxRVY(1#mwMpgAz02perI znCE(d4@f=wuyE|PDh(UYB%>%MqH^TY7?yW>i}b9eb8B$5?J4cwPw1FfnNRRlfb$X(Ay>tWP9wy=1+gO_f25&=O(cJ9@6c6 z9kjl&`ONxFV7?A|-ULobx#-mw3-MM}{{9g^x3lRE^A~v&_@6%s?2F!Qz9UNi>btCT z*nhd3em|n$bnL!B<$&*tUL84l2}?AV zLHpS`&#J z$CqHqvKBij$y&)%B>GO?+ziF;no$uygW6Ju0$8TKm$&=D+ZdQU=oo7-w2}fI?)o1R zwan%fVZ{z?@nXZz+L=@<|I`g~lhT$ElxM>$v@OLj9PsE;cXX3jp?jr*AP(&#OYHFb zWw)c!=)WtC8`uhsbSVU+3Az8%R9$39fkF#c z9ee|8G#=WP{Po~sy-EVk1A@^8=V97d63}eKAOk@l_fNWVjV?_u`AxygJMg$_65>0x*n@dKMIZrt)9A-l{IdNl zp5+J@Q_7j>D1uexH%OS8HZ20uA)NIJ&7mT*ht&xOb5%~`u@>!EF9$LeQ_SZPO_yjj zHHwf5^VU(mz09SyCHfrAsQr4Oo>*a-rQ8~*orLI^VWRRrV32jUTupVm;*KpV= zY_}dC4|R~U79!wBq3v7sVw`|B+sgdt7;L9rIKf9H!cutnok(}AnI;Y@fxE!h^hA+^ zXwG_Qg=XlV@+_ow81&;7kC@8aFpIPw$UdF{GB%`GVOtzs%;}#apg`cY0Co)tu&b9p zId$eGFuS&oKHGlzYeygIFE`#bzpr831l9}dy@>a9+;8IH2M@jf@%3}N|7wvP4sTxf zS7B}F^SZk)OLlYWB4p=H;Lon>`+K#i3Mz$2bO%pY0*CdrR+M`;$KDoh0&lJ!IbPQg zy0q5o@6Rr4Ee>G2x^?4;lXv{7>;njVzbRBzt&TohtBYR!dPO&Wc_`l3O#*TgSZ|Nl zol<=&Sa*7LC8;Av7rk$vTm9_y)vxqjR{8?xi+mb6n|>ek{F&7cpI`mWcUOP?((1*h zR*#?HTKY@gbZqOZq$OCF+S{oQ5#3h%dXU;dx|_xH#7 z6Bkac{gAFsPUtpb(ZBWc=QstFr|{5-mR+Bp;Z6WEn4-=ekP4WW0mAqxq=IY4cwFK2 zo^C&lS`J`O2>}%f1M=Sdm1g_(bm0?I#^jcuGhTW`X?}1H8HW;SOV6NJ82!s*l7Tna z{Iq3D5y;D$n6yLSi4$NGV5>(4RmM|4yf8{2S^SJl_;eiBP$P;Op17~$D=`)%j^5>o zw!#fs3s8o{gpLj=yDx$oFZEO!z)P_3Nadv!M-RScl-Wj1hEJU`iL<^b2p$4~4?*KI zA#x-!2UWI=LhCu?^km~l2{HpoLk5dF&^npHKk+*S*-to1vml!e0D7Y8Jmq+z^Chm+ zz&bmTL+L0Z8IO8uENqHEM+l~aQ814ctvUc^(JD&t#w1;NLknL5g&$^H6^|cLWxc?6 zVCVtXR&mV>J^`GZ5E``{fJm^P*rS0k-ZEjMO;J}Wg%%#?rZ1u9uO+Wp3j#l&iwF)E z2?@IpDuZUGj#fIO%A$PiNCGK!k5f5f83u|@rZosY<-%TpT%dv(9|wejsV_@td6zxx+rbigyv%n{w5lq9N>>r8{-p;O7glRT zA3e!{wC%E7u&Jlw#zC(3hG5h|`8uu4cog|Q23Sw%7kHy(id!)Xllr$D0laAfpxMcw z;u@x4J{M5%*gH@b%sD$i)xQq^Fh{p@m!ainj(lZHK%3ylJxUsmBl18?L*%FzK4x%B z40jgwkFPz60FOQ4jz`R~M^6U;j(zLOg-<^Cjjn-#u5X(E@y{>)+rK%nZoc*Cv&&qo z=!Lc3_NiCc2eSRESC0PX-L0g!gHWlSeDLbo3&%d++I;Bf*35hdu7~=zs;@nMoVU@a6U(wrxAf>z(p7j-TbR6PJ;bDoNV-KTWmIe7=> zNai47`_;*Ym@?JL-hC4W2M9S1M_e=5=5S?ifHSf?@{C8S1=vhA%8`)8<`W-wGD6S7 z!Fc;(H7kJPi5}-xv_TMbon`2eH{~p;t#cZ=0Jeq_C!Qh68mU6Nbq7gECkl%|ht^!l z)ANMEzjHJpwYQ&Idz5E*JYxh6VNl;WG~N|b6Mn)9U9=Qh%q7DDnG;jTMH12-0ACVt zYt^QrNnYTfw7>IoF!0{8kCWpXKU369kcDUD;0jD$VZkZ!6ic0@lO4cKK|NhegTpkv zOmpGL4@^~j6apK?U~gTE^&%Q(JS~T+8n(cDCc=R-Ki7-ZF~3?m0AQly8h z@Wf5u9ty@wOBSOD3>!F?CwR0o6uA>*-AwDaU>Lbj?l{+?4WwHm$pb~TUYc`ePT0gg zE(}Vbl-qcR?eKw^th)|W0i0JN+O5pWeoaQZQczD+BRgx<5$#6g(AW#S=7%LKVndn1 zds?`;UUK$4=UUgnG#I-Wrj;l4ppqrVkgQj+LW>sjr{jf?2v3BcmPzxa0|2^Ec9ev( zkcN2=EHa?5rUK}va8v>2LJ#-07*naRI`nQgPn-oRT>xm6j>2YT8wiw(T@n8eR694=R< z8xc!9x+sWkW17IVRao@c>Q035@D|Eu9{M>R;>S!_Tz|qKD3djjLA9D2X6uJA2TRv0 z^Wkkh%1PfWd#_y?D12eOY9Rb=o~ z$Jw;1BKzo_Uz~j6n};^`xV!kPx30c-e(R~zcYK#hU+weUWe)L;5hV?iUTODtzsR`PLoX zqI~!KbzS!c`oNJxPo3U;=cE3R@vRB=N9gOIKiK}>b5r*I&_Bo-t&6UBbv>zz-UIoS z!2wo5k1*Zx)j!?u)itfIZ!dkmI{O*dy?Sr+JZ>CPSDW8>g3H}!A6q?rdXG0tAE24*nyUy|#VhjrXs<_2ISr0^+~_U*3A{-Aj28*Yn!qd`P}pSDzQ% z&-swW1eNn;PTUy+uP3IgxKF%1Aq{+d)e_DpT=h6TgK{{N1E}-1=QOrQPcqgQZ#>%Jqzj^23D*wOl#2}hnjz%x5q(vL9fQ5TC%Da(Y$aiNDuBCi)Vl&gm3 za2OXRj-*Fq{a7LC+W`TNLPO6_bIvzkg5{^jI9FQ^5U*{eMmyz@wn7T#=)gw@ghuf9 zVia9;dlpMHt2Hsv;cy!VP2^~C6~Gx_ey5jWx>i{&Xmt=`2FHc!AD#YLCR8s%Bv3* z_y_x361ob+V#cYWYr66R zJ2J`fgEP^aGjxLjhvp|EdlPOA?+IBn3myeDu$Z~4twCmF@8iepi6IZxvFqve4VOr5 zcSe{T#1Uh!cIX;ej*bP7SHp)yP zsYVQSzS>oPiap?{wO?7RXIK55fD4D`aG)bYAOExdv5&kobio6bM?Ee~)-^YM@*PI=||yZCp}{W{ZeUEHhl@4KqHOjrr~w{&4t4(ZE>1LfG;Z z8`>;K%vcb?oP;`N-lfLn)wj%$WuO1M^`k-K5D&OAAbEErO+zAOoDr_krXL!o{~ zu&C;)lAyGq%gP*d@Y~2_XBg+og$4HpLv@i9BaBIamr&vN(u<3T?#mo%+Qvr@E=`pK zDZH_fZmlR$9CevwX%GXog1Nft+mc`yk)uW%EY*k7>JugWLp~8J0Ul{65Wm&}mO-Xo zG1`Q1FpWnQ8Em9OTcv6iitR!g1qAMtls4UHq7miHXFA?!b6e3z^2px!kOt&^0 zBSt8WpH}M`j|mOFS}O|5@|z-|N>6B#QzAx0w5jiWU~vWTO_bzjcNv#Q$TAnmylhT2 zVz60|oz;|})US-%5vO*GdiwE&9Ir22hT+Dq2163O6K1^(s!YHq7p(S*g+3dFr)>f1 zFEa9?Op8St9|toJ{(#LHRzf6OBH5YQ@H>GZY(Y*#tj7XjaPFQ3qs@g%Hw92leIz(3 z_hs+HS>uRE1P$^iFc~nmTNZSo55j=7b38?ao5#~io z$f-39xbXxN8xQiLwnfd*#>%jXAsyG#G|n+rq6cXKyYSZBM|h+a9QuT)M1WSTd3;)r zHRd6W9{iGyR|iW^x*86UD5a-TsfdMl>T(E`wHTM02)o!&=D===p2v$IqXHOP|44=7 z%{=pXCcI4kUyomp;CKB!RaGs1X5>(7slJao!;4PSPDBAi6g-X~a0bxHkx+#g6)-Cf z_HajC*y3%U7_i9fBCI}o=jSJ${PxCPe-rrEZ(n`y+}2Z%-tmpc+ywsQ5}!8gcLbNB zyW2f}V&l7CKm5x#Z*miO`|8%__Vq*hM(A6F@E_OJE#(2zr-Jo|i*)TeEO*_}2Ug!b zzdddO>(W|pihk##{v_yK^V;#v54OJd+yQ;J*u5#a7w_EZr9FsSefZhxosV{^)dTCXM^@i{X7#P7_@{S7FE?E_>mvaDP+ra)eE$#qul3$V zMfAyV{l+B!=23L$(Br2b_&sGALdPq@KjG>i7KsB25iwBBqCo&BL!$7gt$^DLI<30mv% z+1~K^dVUCkz^rcR@f;UZ^x1-*NU!>Yz@B91js;k!J&i}Ku}1Bv&v;R4kUgsx=?=Q6 zkMrR5&lE`W z3rNQS!e8-avYAATG#+^2>H2?!nS{77hu=CQmxLa)yv5#d&x4B&~rVqDvyll-*dNF5kitGLFb5wN>Z z#ovztF*x7Eo?%f5-h^xXFl%GBqBAsnaXfTYGeeuBk?f)onyJ3bW^#nW$KazY4iNNu zMF2vrX$;jVlR`v^1u$YLG&v+Y2V#sl<@c0_WJpJw-ueP?YG=H8f4-|NBTNN+eeBj5xVX{E0b8T9dH9yR<}BU6Gfax(NXnIU#h z%f8s)L6E0tGBPVh^Lai5j-qa*JJRoJuj{GPtRp+_T7U?2gqEHxkb?rkmmVZA)`r}E z+7J$Wj}ut_`q%g^9^1{`vc6Z`X9)a@3OkG#YIcL z%W8a3_P%GJFFex?Ufno7{SY7S)xv$IFL3^dJH5YtSHI3!eR6SrfwL}jUp%w=^XFH8 z`^xIS`peZ1o?D$cwZ{i*MWQ!yE8j0@6TjZutjlbDm({6x`X_PuKMXE$|LJ>^2e6j`8qUKz*xV4 zBAoo-a%2nPsf(p$3Rm?T;C-#T!*viJ3d%3x0u#GCo`cQd;(^Ui_EwwZ`oZQ+%K_RE%mnc?4X|R#7 z_N7l<%|c>_I90Gms5TMxtgwk2tJ8|1Qbb%9 z#l?t{qObtC)g*BsE`^0Ms!sT=&bmAmN~i0YV)vY*IvRNnEbV~c zkGrZ03^yvv3_C0pLenxb)v(@!Gn4CMuPPMQ5uhg=2Nn*20t%+BkDsh>1Z5_3wils; zdPNYWACaNF63L;GQplq_&E_;afQ6wd%L#@9i7{3W&0Ql5*2?kb`Dg+!0hmfpO=`!~ zEDr%ZC&p#~)ZvVGHlReNAI$}Aki6J?2Lpp%;&RchF$)VWwXvM$ZIkmwdT1TUSjJQo zcohksm^kPwjjq4TBN`@{>y8*jA2EsPd`dCh*B8zP0Bkfpru3 zosYJjd2HS0Z7^y=%Z9(`oa=;rX5lXJMEr}sYS3*qu;+%a|6!+fk)-)N=I zpTefcX}$nlm%dka{q9S()w|FyU0GfHe05o?#+hvO-~8wsKmX0g=RUofv!iWu5$gFO z*m?e(&rl{2ew?mzu1vA(M2*R3Y^)9dI?olfeOiWu({S)UG2>@1zwq$6IcT@$()7>^ zyzuHkMgkQyfi$guj$;Fe9vY9vBDS8!+eQHNm_aR6rgK|vo)4npc#x+vo~!~$Ipv*v zZFXTI(D}PcEoYDVL@El_{tj>zlDycaYWiIxXKfLAMh&*{&Wh6T5@gDV==DU=Wkh^O zA5^q21=#4TDGPz$Yvw@4Cuj?B*1^M^3aMz$(K$G&0iXO?8mSoab07wvzFQgc8iEA8 zg-zW=Vb7{$!xklscjeZ`p~xI_L#Mc^CXwz3IgLKeYB$hG<^k)L!q$I)#KT@g4#J5{V029Jw z7Kc)jbd!7K3%_6HQxDr<9+T!D0un9dasA{=;N%@85in#xHEZl#JaiO>NziRm4FRM^ z1kI`gr`sHA5vw$ zQj8i+ww~Qj4NQrD=rwv2EuljpWDPAck)f8kvmH7xdd3a>N+T*zIyR@K(Wo?&=3lI+ z6Hk@mJi^(%^@r31^MD_bN>A|Rv9##UXfeB($;3iQ>6=6wf}iu5Vr2JaX*8eLe~N+2!lszuQj& z^QUxmx9aE&e=of!PjM4i+V|Y*Ch+x*2M*uj0$A?439PqOuiXSba_HM>n~4dhg@a zKfb;C`J3GG{phpR)qYpDZVT(8_j_Mo{mYkEfAhW7%g?T!I>k-b<)%z^VCx;odv3ZP ztJ{()#XWAjKi0cn#Cr_%6>-<2`|35WZ1u5TebbnJiJ)s>y@Mc|4lo^8=k>nyPxu(N zK4hUq)IyB2@8QjjXU`n}yH`JyiRT=jD&?DpV$R{~=R?k)^?Xt1)8)wPuKJV=vlKQ#OLunRhoqigk`2;tqdr!nZ{ttB;u?LlUMci?t4P?T3#lORp*I*ZvsYT#*B=ZAI z$Lq%)rA!G=4Vm$@4RpPY_426jb>QMI*{n$g2`6UA93T~qD7QXBLJqDDm__is;lqi26joH=boJl-js&X1<@fJI5^x;&_bmALdUqoC=bA%GLGk=Y(HYdpJ!PXn3>(mB0WPiG^% z0+SqCBz;RUwR0hBca?d0BuP*oD>Ec z{%657-5GII;Ni`D&b_BQ-z>`11D7`d>NFlQ%Gr8c+7W>CB^W(&N;K*j6MWbQyb$s- zJ#k784!}cFdylKJ2SlmASFKmUkS=-BXQUqus+_gTg__KDz!2O@Eo3g6ZA5Jk=Uehq z7d$K~klpo9EgczgJ`$>&R%yQ>tQV*Q61sw_tGX%HRFmUDdJe75z59z(PkwvPo4~() z=juCWx1M=?-Y*^OH}8D#3EzmTcaZ9m<3Qe@dHUgvSH5xh)z|mFs?bf~2M%vv+1k8z z8#jTa{EZK{^||7ag1!z~e{=Z4LHy-jJ_&qIe{X5t1b+JT#@h$8k06Wr<5UoCo8U*KGS(fMZC z-25i64trg{-NmL~8`U2!I?A7<{!`fWn}U3%SJ$^Y-!E{8i(cL4)y;W*|Mt$=UDf%{ zH%|WTU!3{zPd>=$POUd~#)fwStB|XBd1>hY8(Z9 zoO#6aqv_$?b-LDMqczRQ!yS5raR9|tM#I5yMmzW&g>d8>eiy|9>k(ZB_54!&R$#}` zINt@4!twkS_qF;MM76~2a3IYecOwc^{VI}U`h#iu&tW+C9y)qFgM z0*S$qfU*(U<1(2rjc4f=tU3(&Y5tB44XFy|moFwp4$2x+SEzUMxuflh_;QLU4$Xkw_v zW6r`CDicDszv;_bS&l~`4>b5wVbdcBqwAT+$R7Gbs&;1r7>pmX9lG#DNSCl>#ABel zgNB)}RW5Q$IyhD@9mbBJ+_g=If(?8k8-k=d9`ax+5-0{fQEFy7r^e6(uxJA!gQ#F? z+FbO7n@|oX6ArDX&i}Lih@BgQWdI^UTJ@*DhButal&AH87uG92gt`83K`3kFr7hY% z{w*kh#62E9z+4rSWAM3r=AM3q- z>noElO=rHqS#Ltl=VNtou1}5r_TAM_Uthic;Yz=k(I-g9rgt^J^vvq7zPb9*E2|$q z&jqk9TKvWtSi<1Zpm^J*k5zKkN28cVBKMs=0BZ}^{RSW2;IfionE!N0Ol`0 zcU5%bSD*ORUsu*IEOc{Tzq!yw@|bPZ-usuHJMsVi^6aJ0w>bMPHqM@H$eA;(&ydFT zY&qF~hfPzMEoE^c^(nUT(J9C37)PwZ1;gU`l&8E>VUYvZ>Wz0`XRr*g$ZELBR!`CD z_36JljYm(@=SihzWZmcaW#M3u1uaMxWwSy>%ocPC(0#}%591Vb6qdI@qox2NQJ+~G z;dH5K(`icx$E-T$h@)GY5~n$Bpr|H8Bhxz+N5GTcu+GG}>M00#Xmi%TJVgjB40bd_$< zA*)cuPsEO=eJ)DXan0Jndql>NNwuy|jHcK0STM(}ko4E{HARl+bi>I})|c)fFMAYd zz~*wLiNTf*5S{38^qF@Vn!yhivk4m3(mzNu5r;~)9Rv+OhALsQofQZVFhesvGKqVY zkU6^L3`q0FcF}ui)|#@1`=HffIft7%VZfF^lNUIPQr@rvuKF`%D?OUhr2a9Mnc*O> zF>p4~rlm6 zo4~?f-MaC_$@w1E2Ol_e?t=cL@H**Tjr1Kzx_5W-p{kg^6iYWqKf5#zsJkL6){fBnkpFJI(+3a1}lZO#MX4pgfM4Jelh8Ya?eN>pb9k)7hiARO1}#L(1CLV})n}Avc;lc0 zudUjt1tTMisea&vAATVPjmh{HV0PvS?L83JC!Yb<&<5H>GKzR>+feC_oT|p`30B@2 zMrPzd=kZ`yr{U`86@Xv7Lec-1fa0$gYKlH?P()JPh-)731G3nA)w zh>+&>bixz>G_x84h1P9H8vJ#@AOipgQe?y>u8G@(EE8z2SMyIe;fQI-I36qrkR6bL zq+l~JUd(;igqb*OpiPX6`E5v(NzaGh2^&@LT?dT71kiNifZL04?*LX0zq7Dw$#2>n z>(`Pi#tfxi4*TIx#L#MPl&Pj?Juzr@tQTSsQmUG+*B91WxPk$OA;ZN1!^yhCah#yt zFz@IAaDwU3LJv}%5UQ;Rm>Fd%?T(=sK!h6lxn2<EE z)AQj5&pbaEpQui?yYd_f!_Rnz^H_##4o!p}Cf~*3?YZQcuKVC2uKEy#0|Uv$G&tMh zeLLW+O>nbBhQ1DZQ-2hApPRs+T-^TQ3;Vy)H{b4tOW)(VE=B6W-2~qJhu>~xMRrF# zvU&aDl_T4?dlOg}9*36St9*brf%SKl^v-8}6gVOuKDe)g{`~5V(~oR?IX8h-XI+-) za`*Bz-ifNduI;}f+xP-!-LvI4EV}5uvU*Dwy>G03^X}>$e}S{ExUxNXWcB=+)t|kv z`rGgEr+W2e&W}H`#}_!?X=>uX*-hY$`cU+emXGxw<8#RRLrRjZ@8a6;9`e%b54W%1 zlHBAAob`*L3%cn2j61!0UwS_Dd+)zkdHmF|PcL43{hbRsx#{H7XGXenl$y%W=XakE zbE2)e<)D`!=S|Jj={*5tH8b(n&aXUeVbCn6Tm0n7&bAsgxq-qB45Jcg!avT6asMS)9QCU7kROnC|DA~TzgdcnuUh@Lhl=MGqHBtpaj z#Kt(&iH>9Nf`ww><&l4o4czDy-n_)q)><-JZnQ9r?k6Dt<|CW)d$Pi)qi9|hZl;2Q~T2Ka>86ZEj zjSe0saTML4bsWv;cmRMDxYCBze(oB^kohSVZ)K{lkwrhlEWBf&HR#o}lQ6f~^mhPf(0j(WPvB!FzqK0WHdFcfasW^1qE zt@*LOHKRG@)z=)KBGhM60OfLmy^K}4HvC{$t{>sJkr=QyU zCh*4>uD|%ykrNNy@oh5QGt><(-N`v|KsSMP;iqqz(uZuF*3L#ZesdF88R~}c&gos_ zE7xv3d1@x5o51G}>L&0F-2^_geiQh{f!zdNm%S^kdot)S(PfDiE+5O(MXxUNa_rm_ z??E`{3!HV2Hy6FSnAF>7^?gXcc#E&IdgmPX6(v5KZm8<3o4^0u>R*0$^{>9W`u5Yh zbIt|l!EU#_39O4c{SHWftVj<5-RYHb{W3_(c^LkYZaP}@9%dze{sQlC)@^Y84rTl@ zLSGN2RnwF{jIDoqtFyod{)?4wKX>Ba|NQLbEA>WbNpivG6aB1xRzfXj!NT?F6H`u~ z1D|tqFP~2`h2pfD*8^j1)e(Miy7fg(KdoqPkJk_A7zFDlF)>+TMK{X2TMlaHrpWLk zp^Ooev1~ijUAzz~CV}J}e;is`b;>mO6~^QvqV=?+i1w*Z+-h~kTcFM6WpR?r-|{Z< zaqtSLorZaFR_#Ed-qXk#Fgl$S`U=ikVrSa2fK@5Uo#$U>Rl#iT*A;x$$l;9iK~+YH z!;_!2S2H0D=b}~6M1ViC5#rFmN<);Wm6&lzIbzFmYMLgpwHF%$^6D%=XbV*WAc2I_ zYO)gWz8noGK?MjbyrV@SF2&DYLo?T+G_=fQsL;SHz#VLMf~w=tH=4Pk?Kt3P(9y5; znpF00IXJ60;ip8F0lNb^91-U*c<5vAs*n`I0JI*uEQ!;y@G;*h>(6LLf@yvOSM(Q7<}>&FjOM03_R zv&gA&qEyJDr2zG~PCYFjq0oEhIDye>%StWQ%gZ_A_<)3#r1UQbz*sNa5mR9V@lpn0 ze%!_y7JlUA3X@)2k|7Baw6};lzZ%g_fJi2xJXpEDJk#+&Ykv z$rm-ok97oXe9Y!Y!IZJ!4>eP zfU?=raUir=d&-reTF84M1Wd2z>tPucg`s~OR`BwOpG%FuScw9Ec?6HI8LnU7KD2q{ z_#;m`{?6u;OV{t^Ca~yq4R9cvE?NKKH~W4PSbqlT;#J)Q)~(%Je-e22M{0F}eNdkS z<|gpsZvyKku-?2q*7sgYv0L`Nuo zAB%_cT~6bi2lshBz`4=qZ9CMdlHE9+`usU$X~ySm@9WemxHg_B`&BWgTW=NDe2!C3 zE8y$-uK0a+mXG7Y&L&vx)QQgVv|A3=Bj5tBpryypEb03xfQiHve62p{hb2bsn!e*M z_zfhk)xzn?Lfoo8Ri(Hr>$7>})XSy}wE&e=L)kBbIWb#Q8us;Sz$1+z$Pc}KArh~! zCxf&go4;hWMF3Cr68L}-&%`gvN)gSNvM?mP^%V_{Ib2}qLSkiDM-urks-LVrfUJlK zQ|qi~^aKD=ZxGZ*C=XFo_Ax0;DM$i|l(rIXfa$`47qm8&zx&k;Rg957@QU94WU-G&di9iH*suCCXT!vO}mys^fO0XjclF;aIRI^rU<_9mM`R(o~3E(8}TkF6?&j(2W@^ zL-YQpU5pvEn{0^iRQLz5rW#-NVcijN#*RZ}LC|qLI9B|UdFOBLs#BG^MGfB6(`M9~ zpAP*+5)8X&yx10w?A*A`L1LI+z7y6fmDUd7oXqMGWv*{lw$|6xb0g;*4=93G!4|Q{ z$0SV@$Qsbl+C7s8jG)$!8;WMqf9kVT_Kwm9T@KgyM zkr&LG9&$%F>WJURziBI7Ybb=B4UL0wjBQhEBB&DB#f7+ZRK62W&k~D)f*T*gQU4Cq z`(j+`@j>eVEjD6^5Cu3XSY_&b?KJQyluJ^u3gB?SGDk1uttZ2Q7|7&?y&QVR77Cs~ zFjN0JpG-RY4MiPJgehg|0hOP`Swta%nbnpP)tEn(6R>##ELBxb>(?~@YD;g9mkvZC zXycQbM^`SLKehi&;OEaAIeF(dfw#7}0MI4M0p0}G72rGP`mfe>&e`iG@U`s?eG*s+ z-OWwlqleC4ysp2+a_^ho$*Jp~wVZ4y~iHlujA-m;&0yLuNJ*|mcHJVolSxtKe2lGnbm*#t<{fyz%AcrALFvq zhxwNwRu^(N`6O_^3;xSc^5w_S<60NJ`m%R@VU_OX>Rki+)k!v;+BE#w7rpveuf8<9 z{%X;erSfZMj{p6uXD@!fog+afygncM1lXrb&bQiVIqfb^xEV0FlpMUD)r2-JE)GhR$aioD<>^(Pakd(|(!6>2A=EXAP}8X7mMj1)WMbwpH|vR+uI-!f(>2gIBgm#rdxjfdCEXaQv{E^=sG zIw9{+#Z92GCJQVgOXg5(kr zeDm8OP4rfq=rx;E)=Wqq$206;dNbaZ7A8cA>=go2401z11QorBre#TAvkBP++NGzs zOkwI!q*9AmAxL;LGnWNGPn1zSa>)z>>mRF;8H_&X1L(P0UprK+nleb9320wr?6o%L zPr`-QU~ztvTUbhnB480laL*V&=o59l{@6+iEb2zC+jV~CK`&zN(o+QBf<{kKVv(~m z9ghf5RiKW&;2(G}iQNqNUEki^JpAB(H-Rr+|KW>w^-16d>w}I5brbl^sSSM{^nRZe zJhFM?0-ppvboB6T-2^`M@Y?q(A3JjBg9G|HXx#*UYVk>6{Y~J5y9s<_hisPffHr-+ zcHC1vAj;dK(HA)D?ZLX3)b}Clv$c9#tS+Bke}DD=zrK3oY<+>V4_nwy9bbLx>D6C; zbM>#kzxs<8R?j`bo9*w*mq^|GCh%=#{s#rpCGO3>!1*dSct6w^IG^Wz&O+*4^!H`c zx%Av;S6_Sk!gy_|lb%nuePWcX?s5`k=reRZ*(^__l|kSmo%M6K%@CNWM}B_K=~nc_ zuhVk?7F4G4;}|bYW{vD7^j2=Y7Mo{*3f;);OJkVS`spICx51;w!3Yj(_*-Mi^|K_? zp6$t@a;X=#-iW<-06(!hiIBy~^*OZTORz)+2Bot@1X+@d`;KK0u)xz13!@Q?okBJHp(WFYIO{wDDncjx#vAoDx_BR2p$rt7*}~(J;rh1&59_SVqS#X-b&6 zt8d+*b=Z=j*?u927=ju!R^9X^h~0Q8h8SUM%5g_7bi@Fl*Q>zZ30zrHcIO0bAbGJK z9mH_K&^5F%mxZf1kxVN!rZhI*fWg^IyISAUT~n2%K*eFaV>%7@ih`-+CTr9}?~K4@ zP8|z!=*8(V)h3ST-RW+s34d4yf5J0CdWqzIMG?G>&ZMaAFsNn}2QXP;39gPk&F`Vb z41Uo5Nhf%<1CIrn-Zxov$5qpwq+)>Tf8jm0-7pRtOq#9C9EyfG@K-OeoKI{@0bnTt z4iyhcAf5Pz&HPM65K}By^XD`YM-!MIlt=1l&UhQ<@n8X>4OIn5NQ{eL+i9-(5fMRl zuqt|W((BWvwK9pL1!+)<(NjjIBiD{WEb;{^{elSQM5<$o64i4f-NBzu4m|atK~krt zF4aj!4ur!(5A!itGf2A#0}3>U0d{M_kj--#nQ@M?+dH0xw53aJ7WfB;dwx8ch(PMp z3U(kz_xjqigwapp#pYcIMu6zEuoO95rJGse)zU;5zOb0XtphO`Q+5^21Is7}ys3Yq z)N#L-Ca8o+S&BV;cvYYjK_f4h%@zhQB|r}UyLGPuI01XgP%G%12(VgxuA9JTUfT0- z0)KMx`Zu0Da_ZrI-tOsmdp3H-e6Tlx^=(!9E~x$fxbB_a1pfTmjWdf+0_(e`5Ar7P zp|wu}AK*>kD_d(HVBWLxcW2Cj@#WkE*4HoVT37FI)kFLqW@deX^Pj)4`Y&Et{nfWtFFeWL4Z4qCBBkqXeW+M(ZP2@*@5{CK-L3CkcLCnX6C0z=}43$j%YfDLgJntub~S%UJmA zn2;T+5gNL(YsVb?#<#ceK=?mNC)-64rB$2AMhS4*m@@lHJ3=PSnBVLq78oLtwV$G z(~%o<;>>ytd>K6tE-Jy|0p6YT)oM75sHt%B2PbdR@D?TlC3?&1yo?ur@NqUWv<@y( z++bkC<~WI9dv(VyVKuZO;W>UBggQe6$#Tok0qB-|#~S!ybdL5$5A@AeorrYS#(H_+ z;YS!PK-_~j2}xlURdt-DlTSYQlCDXTw`uGJpLo=i1`mrrMo-I+qtSvF3> zP}Vkh3J(RFX>doi4K~B64&?;1Jbsv$6+8|A?QJ_A#;@@=9*EO+!fMPf2lYJX>DV3A z_zq-P6oD%b>#P6^mY5Sjgp?&~2MgT-5P@yb$i)Q)jh%*Ws&0!G-v%ZOle239bm=jo z)T$r{1Q`MiEj=M)i;e{zj4N!Int0ov(N42d;{lm%sUHht_~O`l7VE1CXXAWf8N%qa zLuC>&wF{s|gs8wItp2XYiytXQ8ea~k=lCDx43CDxSi+h=(W0RH2qh{@sSV*|1&AL} zr9hztQv6*toMR?qn3g)AmjhmqkB&WzCqVprZ^qCQyaHX{x^n*ge|qeh?*rbo{rJ^O z|LvKRyUe#R=#S9o&5*jer1=%AkUYYg!AU@A}85obGu zmerj+(NvD|KxEWAZUP~~4laWU9E(!$6SF~i1$AS^1+b< zI%*vrSOUSrL;@QIUxwA1U;ef?e>vbzckmAwXm8d-Er{u;;z~M88O8>{EI-kTkB^4Y z%3`j-#7_sKcS*+ynm_i1fLb+K62NuERYUX4@?c1UGeeDKC1LG@Z@-9WhbGLpkzk5! z*@F)`?7SY~FO5p1RrdO7#?f&Kp}jpqU)kxHxA_^k0)#1}Iwj8*K^Uj3sM4_?Igvq~ z8!uRh92hV7dwqdnfSK?DZ!~1UfP@=e_Ai0qN*pGTV>pMVHn$d# zqX=8*9m8>LBTZZ#&xlzT0NJQ#_**mB z%SF%h2(CDGBSOMLNObVPou25Nm?xr=#FK{F!rNgde~F=zS+8g_pZx&HQ+~BPlMq#r z(eUU&mpwRaTpkOo;oG`r}e1D=_b$8!d{2X8vWbs*~n&L$J8 z+=q*?M}yy>1{7}W5?n0!VWr>{1BaGnqg~(+%yqV{qI>le8lof$g=yW%@!Wy1Q>Ak5 z1c+XNdc6{;+r)1b2s4}#WW_O|yNVj(l*Mv_4q>(Tr?{)^i5F2eG7Fb8^2oB%dC zdIfTV&c`^?F@5q)Z0n0>3PL0p)q+M2g>VbaT76>2-6{uz6Lx^{z$A6o18D16oqzY2 zr=NUjsaIHa6rIU#eRZi>u=(~cN~V7~DLEPC7l*Jd0@kL!G$X9HWBOat@r1Q2)) zVb1f53~W75-+b6>PGPD(XiU%@cn|Tl&z|*3SrQlhC~*KML1j{(pkSaD^|gp0mP5ymB&L`m?CCwb??HszJ-J#dzysmRf2X z%aF2Lq-UaTv_ScvgGAlQVfl;`x7v2-j0A8&;Lu#QVoMZE$*2U>@fuAoNmrEtX#EV@ zQeZPvOF;vV*Nn!fHZroZZmprDdJ+n*PD!k*uu(p*96VLS; z@}01Q%L{(oMN+zU<)#^{AUa57(3;;oSv6}2*Qn>{2n;{SI$Gd@hi1UW`Nj6AbGXuA z4;9SEExYcZ9_E>^`xRmGXJtBWa_yi_%N}j909i1S@!Co$8Oq?Kg)9C(9vt3c#0stHokz0i^L6AqlUQV7f~@M zN(t)Oq)m)L%fQ^;gGXnTsb&x~J<3%k>X33(3qC2#e4Cw_rU`vh+M`UC6AtJjWT6VN zsUrzW3Wi!BTfERyRf6((9Da*aO$V6yhE85X&#aWtUUycXShZPCMU<%nIa{Y#_&R3r zTF?hkRM|nDmFiNXvqQEpffjn|pfxwhS^qF$vxkXhPDHfQruBS`m0=PI2zZ!GE2oUD zF1lNlYX#Vd07TBAUN$EBxLQ+`isB0YNMJH+b%fE^L2qns9zStLpxvAPP|%-$^X@+h ztke$dlfb7pfAYI)`@K`QKMA~XJD&vB7ucRSen@YA9{KV~;E!*8GUqn?A$uo-Xi1+yDMo*FL{|sh_#( zXDX)A-O8bH9$7a3YM?6)-p;MqyHia118Rt<}dk!x4)Agqm;`E(+7)QF+y?pvuJy zu=WfazQc+t*R&OsAuJ_36}M6Jn0uC9X+$I=H*U_<|Y5AIqAmQgo(~AHAHa|&3 zK~#%AnueI_)T}XX1|B)>>SXYkvpqE|OoxF;mV!fUH3g=G(d|w7CM_>dITMqB1u`bS z$inPnC@brd8E?CFaDT})ZG68@LXrz5^3*enLaq8Ja#X8A4zau|d}ZhY^-%$8ils}K z@Iye3IdT%)_$m*R#t(jGv*8p8K0aHHCb1Gd%0S2Bl6YOn2)iaKfnmYmNe33nj{;W! ze8S+G($bqY^(s{=tRJ6SP-8h2t8ywN3`#E|C)b=skZ0$5nUSyq)%8r!#(UM|3%#i= z%W`ZgV`#{cNRpkl<;y5E^^^rRveMXipq9@J@lvAJ6Pqgm&|6f&wZ6V#7uzgoc@Q0V zDuKS@uXNc-Vnzav)g0?(yaSjAjQNO0pVl*lnfL?^J_+L7_?FtyTO=6r3#kUBr16gB zhVVXC)lh#jC3=$SlwyxKfTl10!ZT@lI^csw5!;ZHfsM({T_U!F@$x_qa;zuDE+}^3 zQDP7y!q8BkOw($^Qe91qUJeDOi^@*H+s|xW1Tk1osltT=7N4otN` zd91{EdElF<2?I$u!e6?xmPX3mu|_%MZc6J3SJhQG&lG}w@=0Bq!6;*?SSxcB{5!S< z!Ve|`wV^_jk5AXaUg)prBT0h52n%h^54`Qs=qcC2Xsf~(_w(=l)9I(av$46yP2jga zy!P6A*Isz)j&A~g@agIskNYO@LkDvcSQjLJ_3b17_b>Ok3B2K(z*lt>c=OodTi+JRC&-6{;P5o`2&9~0pTGH)AeB*mA?d)2-u8|2xbo>-g36k}i6+`X7C|+Woy{kDcH)uioDL?CI6fFC>rK z$#r6M9iF#0>$-ivKW;S9f5<(pZ0_{xP0l;kMZ-&1>+Q|LjPueTT)LlLzJBb%hgPc( zbJq2#R85^2cb-3)Sv=m2>ZcygmU+Hbhf^fAU>`bW%XOTfWvR3G!29_NXDn_-vV6Xi zGsIYFfR3#~>O@_%evW8d`3;|b)^k#dA*YG&L|XwTGuX_ayuh0y3DK?k#7cDaTF*p9 zpYc8Gm<10oY{`mXrgD97U+`*h=rBC;t0!+lreatl-7<`-XG*H*vN*}c1Ggx@QXwCT zodQg8sO(zO;H!|Y66io9(jhbJ&dpb^9QfUOb2ghts06@PQ}9yN<+gbI;`QO zN63*W30bi-({$tQurv-m#xy&c61_Co07=R9yu%5&h)yUE(~-B8I7b9I06W|kLyzN= zw(4mlP4e|C8N0c{P*_Q_z*FHYvG6X7jIueNdC>!M>pOMIJc6>&{!P@7}0yZgeF)rbwo1?Jfo}c zqFBDs!Xr%T91NMxOipp{>`YG)65hc^XfzjoQ6Q&oKN6gTHi4&OdqHxNG=XPMhW37L5_B(9#aS<2$YehF<^+ zGm6*^uLKI;Q5XF9g+GGEFc>jGOwL{#R|%xd-ldW%ht5)02MIeMilc8E@$I{5DuC|L`mtfxAh7TeC3P$u0Z3h&O{JuBRrM!W?C!2 z5m*r-%o>f~-nw$`-T(0T*ZwSCJK7)r?BWYgo!Vi%r(JGFMxHetAD!Rn|q{}uW)x)Uzqg%$2%{sl(POt zkv`L#>)wNUJHWkEQV#{au~}EVfAk;g)rWQSnO?O!-a4U&(C1gU*{e%mec#oNOX7Pe z?|t!3rmiL_q+7G>lZW>v#-yG~k9lWMHVw`l0LpMO{;7RP|u* z%_A}+u$(N#B0!Y32BXDk)hpKoQA9)lPZ8pVcG!6x5~`wsqZ|;%TtBCR*C19;5Ynk4 z(SqEfSDj?CfEyJOwT%ahM!2+V{t-yXiaJceFi~+Kt3WWTKP&D)X(ZMuxRr^`EHG&+ z3c74edAjWEG|nb56r>Fb>3V8%P#JFmp}bmhaFS`Lwcy6H_xcV(ViUlG35#w=w+|5s z>d?>xJ$neEW|4s19w;GHg~rNM1!m}wiEE80A+qFVZy8V!APz8KKu`74@jMpfacqXY zKw_32Rts4$)aLT4#7sC0j@m44(#X<|WV=8P89>Sz0&N+YiKZsC*T`148hYIP9!_}t zs7x^q+~|aB1O&*Mcq5wWEr+r|Rq2WWk<617-Tb$6W;_?|1`8(tP|(6JWJL=dWTv$r z2yH49O4y7C;f`3GF0FrrDE`DXK7@i8K0;Ok;ZI&!--#z`juyvBOs89E*)nulhWN`` z9a*D0X>=wfHN^Iu`0C++bKE6`QZQPNUKqkE_#E}aze>R>X|n1QQjhT?2>gSbu^od? zO0?FWAyZD*!zmwMG^gM-5{77UH!Us;elLxkaBMv?c=Z_iu;IN@P;3v*=nyTD+94Us>YID~!8DnaE@UJU{PU-%86J%;(#x_PYkwEn;2n>SMiHN*yp) zw^yHB=DPQTk5^ZA{oX*o_|R?Me4W+F<9DFpi-Z1&e5_X&y5mmo?)S9ogTDDpui69o zZniIOz3zhf*Kf}=Lr#618~LxsJ5IGalX{fXY0dl8+NcSyv!lH6p~@1dJuE=uQJ=6hS3iB>0bcBw!WWRNd zxw%G6nFfQydI-i@SVAJl&-hVKt1JG(XBAwyWWKDYGU+_BC{X)<7R4jK+G$l@-*6h~ zylF}UNt;S6G7DMNax%qjyhD%m3crV}f@@%HU5)TBTEc7S(8d$1))(XC&vGFEG{-=s z;gth1EGWl-fR=AO`Ql{Ij6L{}OhKAU97_#y zy^SihHj_>Y>Vn{16HZDZ*YI91J zoSyR{a@b_^&@zg!5~w2quR)lS=aGVU1vSy~$Uy+pIBJ)4BENF+Oes;mRxB68eR%tL z0KmnHSKJ3Jge?fX9pWD6a99xZc4*UVQtnSAs5tRn5l5Xb!&_rSh2Jn2L5JO+6GGwJZxAA1xpZPNf*S zY8{0+(P*eCZ#e*zV+|7yr#c{ICukFESlaASdaznY(Hm7#x}ONqQw!?U{$qP*`Xk46 zUGbjbqK(?9jj|L;w&W$7w>bWgAOZ3{KoIzk%(r|D;CxA(7)W3^4qz*`$UyZyqf4JAv0@hRc7V! zwf1E>t(7n9r_8mSYQ^xf0m@5oEvl@XwUj#f*>dg0w3nK!&sp&O&cG5xqu%cz^*`PK z(8KzVR11K*>@-clkgW+($kx*iEw{XNfDn54b)4%r`Bji8q5 zpCuxFriV$HegM!K>3ZWMXbo6;B`ro55o(I%ZI+m8>LfE{SVYKihOe`sEsb_Rns9Zn zR^mj^QKcjeLwe>+B8HTJ!O(Lka6AUU9>p)WhWjM2he^yor7NJBIb9$qmEp2O_`5uo z%qY@1F3F(_zW5n)`8jq1IC-17({va4%-6(U_PEUVb$SQsFidmiw{WJ6g3K3Xuo4-t+>$O#e$5cN7!lB0^dR2D+Cg7l z`py9!ia$Bxk-RFVC;Kb9`Ro^OQPgp`<5ZxM%!CCI{x% zCkZjqEv-gO=Z}>XAy}hbLGxF5M-ww=1ra2`VWGB<3+|>ltRY1!{7jC#dkBy8ILK;# zQ_OZo7+}0cI^5y&rx2O1!R9VeV?p(p3?ziGvzhokHdj(@9I8?-HC<}rY?2aXsu<1; zJUO~x(Vwb9>Ezw0-5UK<6~Y11WE>NVypowCR}`a$6eL)4PhFiW@th=vmAy8myYVA{ z8=*@Pf=xKmtv?n=f65npwyH>^HUS>i<~Q7Y*Q&coCFOY zc#A2IR0bt+-`Masfpru3o@ShmZ=K!! z=~mCAa-jzfA3Si+&WG1eT-({a@8sS%rRJD<`?dG>PM^|m4=tO1$qBfu3^BBwfS0aKZ z;@JA_%Q|D#sH}xhN<6VuUt&J0K0{LE6&|bePf+w! zH5owxZ~gUtR}aCGImxGv8np|Iq8f3?v$y0Pi^zysKOQ7HUa30-(KhLzxSo^D98Jer z`u}y4mR=p4R8l2ULZ{L6V6@d>KBb4PvQ11uDqV*JZ!T$qNA2i!0u;>WnVoRJ-45C( zt{jE{!UOG{70qt)khpBAHf{d{-vzZR0ZL>bW(?Q>9B9bhf`}6aTYEzRyLlaI&ss_-;n1+bZGUp5d!Hc3JHKmjv6&;;4;4ji7tA~$`ra${*IK8YBHuM zp%t-(L0sx-)wxB}N(+XL1VWH!1}|KxqK55iOjOE7`G6Y&fUb_#h$nLJ17w)T%?57# zOU;5uMdL%5NPW7R0!gG&MmvlM#6qyP3<#~Z90G|j>v8>=T@a+IeL6IdrG4xMz*$(Q zMwb}yyJ3Gi(`Gp^YwOa1x1J=Bij9e@3R(?bEuYz!ycB2%9tawVV>x}kxlkhM(bfY2 zrEd9w5W#hlgGUMOim{JLf-pLO%Oe)CmIH*avWbf}aP0zALN?CyrgXax_;AZ{NY2z^lK? zc%=xp+SRF`Ygb+L9y`WYb}wylWpz#;Z@$FDt!x78em);>evC&q>pJFz%xc9!y7jZOE8KN)NdG z95ch-d%%P2v~@7YBut%Wj0G$N?e?@ob%(Jajj@AmHDLCMBz`147-%ddto}3@8VnV} zjVP<^8SD66P8}PsM#24ql>Hebo#_wFVd(@yVS1YSH{+K9hl!pJ7;FS6@YL{xO?cP4 zfxJS>yN;zAB1a0(;8)4Ow~rcP2!=zSOe;zlVuQvJtKD7M&1qRO8mN83V4&SE0NX7P z;{cmNyRryiX><)XP3>$!h4j&{Rm(M@MzkyD=GobXMoqZa0fm=qfqBTcVwm7o`~ZbwDQnDEKe zbc10_h}d zR@Ca3y4i zpw|u!sG~@NI4Q0M2tSB zV*?Jc30&VEsg{UvhIKcL+rywXeLp{-IL3C%J#HvAuUpw=s_& z)7!yEY+Kt0XHFj*uzOBy=vlJ*KUwdKk+~az5 z_Tuh-u2|w9xJSPlYH|A1;?#XS)atWvHNH~h+wbZYt}bi!J%Y2B_`O8>zX?6vDw|Gn zeVbPwO4n~K(i6z?KNr8npL1SY%yXCa{^4IPrY8IQ`(BlYd2bYkvV{sr9+7fUHE+rbsHaX2oFa|XWBTlA^v>0Tn?*OZh zqC(Nqn2nhl?a?bHU!PY)huAfepALnxO5+Jqr4NGD2-d-H4Dfh?jOGB>E; z$57)1LNMDn0w)i2Rk-~3gVT`=!|mc$=#vI)^25>TaBRiHvm8o*g@Yq%jw68jwBw)y z^(?#^%|pYk$xHhpm?a=$W0Ge%;8t-mA3|JZD$X0tFqA3Err=E^qaz=M1M|AucnsT`T?MN^Dt-@+KbEf%%e-x(DH9f}6 zb2Ze}2D|xl2*1ObcBDypkX;$dGnphY1o>h>y1O9<^IH&|Isss?l0+|j2XX)qYRISJ zscAPvM&i7VB%oB|1f=}hTis0SJb{84zO*y5(?UND*VAQgIdbT583rb_@MA>L(ZQDJ zlz_7ZPxBkEp87pg?#TfWu(7oa;8pc0-8h(!QHM%{@)ObgLlw~@sOOiNg;rYSka01f zlpT2Yd|J}02J9n0L*g%p<7WDtt$Zk-#!U;tnWT##67Z<;$gnH|5Ym(=oVv8LIUqVM zsNm7>y~s^NH2gt2t*Bs5EN3JrdzanOXZ0ESA&Ou`l;9Q!3LVLkR7yzM6{&)XhUloW zde2ueb10rnQ0P-AXOa9Pr3^_QKEe+j?$^9{gbGA;NGxNN1%Hi7QiY%dZl-W0+qyX) z=o60Cd}Ba;LJ^e~e@1<6mNoQ+#(^-I6!lU@(+`LmLmYT@iC)n%e|BUbk=+Wyu;tld z_OUd+(HL|B=|FN)UneSA%+mE(5HnqnxH8VC1VWW^R{8-g7W;eW-}>nj&wT^0L)*Xo zWb2F1-14WOr<=eZ9@$OcZ@zTm2fx_X{o6wtF+6nN&XsL$0xuSQp|BQb!vd2N|%fNbS*Nrnl zuB|>4fVGshvfnhS<7L?IEL!-ypk_cw;l0C2o0eOTo5cOb>o|X_!t6~Auim_Kq>*={ z;)5T?;0fEyxZ`*sp5DH&MSrvFC|=yK@csqFsx^@JF9LfQtc}_`5OMSV5(4n9%~GDC z*9KCf4p3DTjazL;0MzY3+`=PFf2n{E70-k=S{U9$(O>QWhYNPMgtHR%X_mp(u>&@X z>UtP&q9!vu#c~yp<}i@Qr}tr&H`Oy!scZ*%$~&^!h9#+DsVV~zyAJlC6TEGeysW8V zQQ`v-jQ=FMY}IhO5Sfe^>9D7h=xU|%G-PE&JC&Q(;P&hatl8k5U@3G zA|aNIeOm4w-f0j|QY4U*oLn1UC9>OImYp1BDH+q8Fc+KILkD5Jn7--gIlvl<$v70S4zI31>J zIqHt{m1j{Ku#bnjVy2Kmq#7v0R#~_TtU+lH}K#QxN7W z&n&+B!s0K!%-dIDAqkHck ze8}gS^|=X6mNxBlH(t}E52e5TL5&`M$n(+a`HZva{QuV6FDTSp0LCM$T)`w$n38=B)gN4|C zgi_Tu{1j-Upo*W~STp%yK5dF3R4c}ZzNO2U1~kHBWR%UZWl=MtwfE14=GU;VR1J;? zdxSZ{pbe+V6bp%r7kwo*_~~1N)n$~h;gwtSGi0+Ga54`Xb;nJRRKfZcaE1q4UW|qw zXWP+_Jkb)aBd2H>8lMUW2i`i6GLm$3a&6&ZEJNuA?+m;ndWBMJwpl-1X;6`Az6P&H z1vvv>C)Z^BfCQE|=>>VUbKMM1k*3cr{Zf?I*lX3bWw=9D(QoAE}Vi=U_~N z1`jUtWo1wa2Lt2f5H}e) zp1Wo^w6{g&h*KGzjdCt>*&E3%!fhSg(@#d`9oQzh?s_q z5jfR#bZTFl8PtwE1&d=6pe+-+19!gA7r!0rb>ZxUbNMX@ScPdl9GwwP)#-EtjYr9_ zoIoLNJ>eC-(+;20FN~0?s`0|O0eKaQrb8>RGqGgHwKyk0WS0?0@UmO7m~Apiz=O}} zRiK1JGkOv#^X0PS^+ZHA1aqv!UGcPG^8lGNzw3#;@NrKphcck?@H3UjU}m68)l)SL zjEJxFn6~>4Zv?rNEB%^5EDjxZ2b!%vN#Af}OpcTj3aepHyZAxLV%Zf)Jj|;TA(Ep3 z-`n}%ZQTU^rd?Kd`X;b$0#{nAgE#C?H-WD#p1S4VD7>Eb8(%p7ga6&p2ea1>Kg6T3 zxCy+szc+opc`bCoRmb}m_nw@6qFCPq{^0U@<{NO_(EQE^d(S?;Ill?42SksLu-?$^ zV+>r{I=JxR{v$WI39LEFQ>^&Uf;_f-&&dNdawnqAp+Rs8uU7cZURa`&0joH)Al z(uLMt+@v92>(!<2-M#$2qeak7_?th#Id^*btwk&xzu)xn?}Jz0-TC?J+dq5l`r%&* zes$}z*InKwYQ?MNl+{n=%eq|+SzJ|yzXt2ZgJjBE4Hwc9=rD_ z(2DAa)0w~U$!Ou)qel4fwC^NM(UnQ)< zSzXT&FTiex5keuWkkfpDl+_z4R&(Y2nV%|CUQ;WyjzDShnxq(2sG*_xheIRgv7@H; z4S+&h>kH$`AmeSC5>A0;xs|MFTPAdjl^t^ww(uuyEUO9PNF2(=Xcn4|KeR_8WSJxH zgR+GrN`7nXY--}vHD+n?x1x4xmgT&FD>kyG({e@h2uiT$GHSLdLaC?nIf@-=i6aDKozGdbDeo z!*GYRg@E1j(Q=l+6(FKrVJtW*n!^#zezUUzjfO#wu2G*U6|*opZNSPQjJ0>XoMQpc zBSIem_O_fQ@6Hg{WLXjC=K}+w84(KQgNGt7`6m7FdAb7gD@by6BEi?QUCP3UQG9GA zJe}UVco917aR|C$iQ+g-A7<|>fQIc@f$Ds&-m=@^jmJ{gCdySJNR4JrfG8<>4!ohe zt1o{2?~k2W|C!hC{Pja$dG?k+2>sx_i|3v|i5{MGRM#^<`qj=q|LD-gT<3n_>dDL3 zP8{Dnxc9_v6|{#AAN3oC|Lmm`J+qAe&uhC!bq%cNKY!uObgTBY_xJP|=ffI4f#snG zHop48iQy>yy4=lQ-v;L{qQ2IvFZAl>;mRhM=0X>}FFnnZy479T-n+=xO+V#L=Z3z@ zd+$m1^Xd4MW!%wldL@o$S*>}1^KSjhB7MSH&$asfrV8xs9lUvN_my{dbm{x%*_|7G z$@%Klt@q!3BX1(|V#U)!*Qb$}RxI9X8SUhyk^ zMRi>7@bifn{0_kZJ?=YP`f#@3C=6m2+2)F#sM<$pY13ni6*dFRoU&K|5PT6+QthJ%i1bFZM1f8EQXZK?KTy@s@Cr3e zIJ7nH4)iXV*}_kGH0YGwvMlttIx;y}I#Jbwsr?L3MeU%S<5CHs!wyiJ@s&s8G27J+ zB$63R=nUC;Wk=1S=fpFyc;Z7`#`x#9Ng6MdU6geJ5hRG=G7(;W-ba30Krj?P$1edT zBLTx7nDEKhlZ2y~$NakM=%&TpkOYXL%$L0qI^}8PpqCH&w9WX5t$#>Gbuu%?frw8^ zK7Tkp^vCKmcgax3Mmh7Ufd&~6I|;e;R!|tk5Zu1)4_@vqD0=N622*+5zFmK@*YxI4 zjG>2ks;9Ke-?L>sQ@Y@$EwQ}si9?E$fHxc^06Qitgrg$JX8qA4u`lm$O#n-?hnWSk5TP?Ea%ujdCzhhqVTuZbK*=}kJzcFU ze$LpwlOBob;Et7?rZ}_`K*J6r_;|f@LRo6dAz=fPZ+P&ScwK4@ShCr}K^8s-OyRa1 zLm!^@NYD8A*Xb!sCK$zRsA1#$+SuPe_x8(AKKHGdR`$9H{N-D}34B?$-RTf!^B>`kTw3JKk@d+kN%j z?N{H~dHw8e|B9oVCA71x2SKxddSwOah1#p7T3+fH%lfGUE&h1*9Lucyf^sZ3y(SBu zbp(^6ID|Q}9-FyVb%!H{eOc+zW0=QU-XsSXKnw}k)nBp%g$Hz3^+B?xTvJ6m92+VFxZ4v=I zhc{OoysufJExZNUK6Vwrbpzx9>YfwPjTQxg=a=z7i=VFf+m5d2n<;1)Xe^(!rW3{$ zt67UaQq=qs&3MnW3CUay@247+dYl>MkQ2ZV@O0gQa%eD~7ZMIwE28nTfvv3vqf^Fd z(D^p5Gqe%iWT%7RjVr3^W+1`gOf{PB@G)`atnCoLZ4NZ015hCuvTtXCW!fSmCBOA;s(@C;qsa!lQwW zemP9|kO0+Y!I>v>W0R{kJGed?zES=088vr18chqi=T!%`q=>1Kl4ZFZ!Idg2KuhVt zzx7PErTI$O1a+FiJC8}vvZCn(?b=3WosiMftf|NdO^HVCWMs4(xOcW#YqZXv`ABI^ zpyfT`%%4UJtJh1yA#GM3ms2eEOh(HEjz;OpvV(q1;Fl7x5-J$-2$PN_JyV>ed|MB^ z9jJ+hun{iQ?4!*CfidCa=eUfgaN^V-iZZbxOb>$o!q@-q*opfl%313>fA!#3{$S0o z3!XvNG{;R~eaQCamtJd}Z(#cGU+sMN#y5d4UORc|>WR(GgZoeJs(d%!BuT$u$(1PJ zPhZUmrk=tf9%2f zc(d;J-qN$I^y`1cd?z;P=T5J`mi$}!=;jnn4{+B1NAP!Np-*g*OA8ghqoOPG} z4i$MG?l+>X1@@f}xYMggTfKgEXJ_ZuUVZPs`{uQ4Tk};q3wo_@_5L*~(JN{UW64xE ztH7KH3=3#4tzPDbItQ56a}#QT&5Awwj5XG)uir1SEQi(aAoB&tJWa;x4K6B>)9?7p zW^056JrULv=;3{*@{<`#m`ENyOVO=AQ4$wW=y5uPmk~Q4Q--{(EAMy7!vbe_fbq5z zgwfDumijqz^leA`kS^`+j+ER8hvy;M!AnZLXO~!LE44J;bzt+mWK}8Ax|RGVc-f18 zUSiiw_6q7i5>YHpfl|(B#p<%x&pmO>IP$CXO<+Or_xw!_>It5h{DoKzwc3~;+B`A> zsHe8;*>E`=`mv_*9%)K5IaW#!S8SFEj}@R1yU*bO0#vf@792bnatn-Mt1DbN%Z9<_ zp_ZkNRBW&Fuh1qbyPSZOoMn81YS`0P{FR>Fn_okjCaZw11VEdq0S`~~*wMwHWqZcS z*if3N_+M{Y7yq3rU*U`l+z9hLp(N^Y)!ZL9Y>a&DFiPE=V1lGyPs@< z8)e3c&NR&{D#5}M2l92cLsDGB+%yS+P->ggM>4veF04<|1RC`LLoyXH4M^HT1p?}2 zflv;oV9k?86b`)8^_((kE*7+E64Zy1PsadCBu;X$A^c^OTef16nSz2(Vcix)T|^k3 zhQrC<_#|Q~hpF`w_>kqm6MsSzj6W%|`N5H0>5UL|T2KVzo=}NlWojBOirMJ{75c#! z3{MxN*gLgw8Lu6xY|#O4i-<-sIePQV)Ro=oMh^AQ`GaVWi^Y8MhXT5?!*BU5wRBF# z64nkTm=Z`_mnU^}1iWcX`4%nOGN5DUh9UBp-}(82ILmdT%GsW{If6Jx!bMMlEt0|b zi-12Ex5+Hm{J!D1!(N}@bz4h{w&;NNiR`%Qke)gUUwK8_&?zjo82mBn} zP2dy%`Sa}?{cfQL@7cL>{rLXAZfS2En^IpdQ5PZlzV6efr_U-s_r&q@myhQ9@0}0! zpMCs5kJn1VU7&uQM?+j#A)o-DoCIP?K#Ju*sP=;ag6XBLm1 zTA%VqTJ^*!-Aq2JO(%@L)~oOI>J!dK^)dLP(sqPAH+g`w?rM%-)yuD#s?*^Jga77H zX+eAMqVDu^(fitaJBPp4`!Q46+uPOEua`kq#MyGlQlB>(QF(P^nH-Di^7<(VYilp0 zaj2EC=Sv*@{sTKMc4 z&JSVD(NQRqY$Qpe_U7HcO>IsM42{wb0)c*rARUu^Jad!u~~Lz zYU~*_mVI6qgCE`!;59B{&1Df0V1_I?Ne94K6X$Zs!@&SJr~}RfU>t+uu>enKD(F3S zWSOBD&5=S33WzMZk#?A-X_`3UjLGXKVcQA3)lzly!RzSBfv)9rH&YwtMV>6T8bvtm(aeR-b~_Y zave-wiR4qW_gPQv4(U64X-`+Yue`ghi{7i(y*%Asq$`&%iXba$)-s)Jyc^7ZJ`sSb zyYktw+^ernB(TRPp6aj}YLwUKRru`v)Fk61XI(`>SSpB2*b_H{I3zsyh9_>>4d@Zz z9mx$0Js9TRTRy{SSWhyVvb25?wC-jCXC5ojxD4=Ev@5F)TO1iq-I8h11c*$*qE=H9 dKXDx_{vXxiGabX{yBz=k002ovPDHLkV1fzK3`_t3 literal 0 HcmV?d00001 diff --git a/web/public/assets/welcome/new-db-selected.svg b/web/public/assets/welcome/new-db-selected.svg new file mode 100644 index 0000000..8406353 --- /dev/null +++ b/web/public/assets/welcome/new-db-selected.svg @@ -0,0 +1,23 @@ + + + 椭圆形 2 + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/public/assets/welcome/new-db-unselected.svg b/web/public/assets/welcome/new-db-unselected.svg new file mode 100644 index 0000000..e870392 --- /dev/null +++ b/web/public/assets/welcome/new-db-unselected.svg @@ -0,0 +1,23 @@ + + + 椭圆形 2 + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/public/assets/welcome/ob-selected.png b/web/public/assets/welcome/ob-selected.png new file mode 100644 index 0000000000000000000000000000000000000000..b3c262dbd7f330e2fa13bdec661ed6f6af3e6fb7 GIT binary patch literal 1505 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 literal 0 HcmV?d00001 diff --git a/web/public/assets/welcome/ocp-selected.png b/web/public/assets/welcome/ocp-selected.png new file mode 100644 index 0000000000000000000000000000000000000000..de1b4de7edba825bffd33b98bda54af71f7e91f0 GIT binary patch literal 2140 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 literal 0 HcmV?d00001 diff --git a/web/public/assets/welcome/odc-unselected.png b/web/public/assets/welcome/odc-unselected.png new file mode 100644 index 0000000000000000000000000000000000000000..78bec976d0a25e678ac9a53b1c18c678a2318195 GIT binary patch literal 794 zcmeAS@N?(olHy`uVBq!ia0vp^HXzKw1|+Ti+$;i8jKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(;Zvw#`F1}W^m|1ySwfvLsQ#W5s< z^=;I7f8juZy3GnpJ0paJg_n9LJzQ{9Ku7#P8~+`SxCiUp^kRH>I6Cck5%2UN#b=Ks z%a?6ci&RWv9x%D-H0?etlFR>LTIHMSw|0+AGRyA2`SW96zFFnvyIQL9fes=9tS*f8 zq6~buejRgjyjqmca7E&$n8kmd_3xEesZRa>H>)He!JgAS{Zi|)zxp>%KD%{)GLvbl zQ1(u%Ln~EgI9_UP`x~Dw?ft%ACT^O6;g_Fg*GwNc?NMtf^<2Nkmm~h>HA$xFeAz8t zcP^XkvzwuJLrlj`ZqMe~Y#VZUyen+)%wufj z-qw2VNcgVM>jf)Iem|G2K0W>z+8hEQRy3Za~WBB?Sv+Zr696 zQOeo;XUm3k-a@4A$%vZm!B&?Z%A;Pqv_}wAlzK^V- zYpvGwY`J=Ns=QdZ%rg_eqkd6eede#aT2rSl@$<6aeUo!*3VD)x1g!S=PkWb_sn_iZ z4&cBC`@F`~1}XXt`#v$>E4Y@rPbTSG9iJ zBsuY}r%1w|l$00uX7RGrT?+beW?94G8+{T9cg*H9CYGMw*0H-{!?7f%8?tfyMx2TK zvn~X2TuSWS!!8x=rnco+(uKr|`GUJYry6cJc1Wo2%EjVUe;W5y$T{BDVgDk3>iW}# z_fl_ny;*WqL!iz2diICa%Qxmd-}q@keY%W7R=V#>RZz$`XiR8jQlDd5Ua?_ER30c@ Ndb;|#taD0e0syVwMyLP) literal 0 HcmV?d00001 diff --git a/web/public/assets/welcome/old-db-selected.svg b/web/public/assets/welcome/old-db-selected.svg new file mode 100644 index 0000000..9f9355a --- /dev/null +++ b/web/public/assets/welcome/old-db-selected.svg @@ -0,0 +1,21 @@ + + + 编组 5 + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/public/assets/welcome/old-db-unselected.svg b/web/public/assets/welcome/old-db-unselected.svg new file mode 100644 index 0000000..d77377c --- /dev/null +++ b/web/public/assets/welcome/old-db-unselected.svg @@ -0,0 +1,21 @@ + + + 编组 5 + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/public/assets/welcome/oms-selected.png b/web/public/assets/welcome/oms-selected.png new file mode 100644 index 0000000000000000000000000000000000000000..8f8dd14bc654e7c63b4d4230f39900eefea0d2f9 GIT binary patch literal 960 zcmV;x13&zUP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91JfH&r1ONa40RR91JOBUy0E^%0TmS$ADoI2^RA>e5*-vlNFcbjr=X6s! z3?U8-_yS0b9=Y%(`11weh7hc!{1ew5c0v@^4mj{hKu91YB!oC2wII$&{1FGlKw?|h zn)g;&TN^vI-8?6eVrffbKga$#aho^*WhzIY9D#BK3N!*DcwZaxHb}U&+pd5Xbj1CT zeFzI~$Th@X9|H<#Bf2@3$G8&?tivi;Ky(;z5;icJA8dnFXn+o^i}6c-uPl{MQ7T6< z9b{Rq#^$Ukc9h?Mx@;$h%vQ>GhMV#@4B!iPuj0`~wlmFlh6ixW6HDX6cBc8jThPUh zf2Q7hCKfaw_^IgQ#e4y=KRm%yEp;^C99GJvJc)Dp749BYSsvTe<}^Q;bU8wY0p|!E z4xAHoSa1%|;lXL4C9K0E(V)Y*q-?;{!!*9gJkUu8^qWpv;_jr?`-s*#UL&jfzeiA4OWo~hn@;fz!nmn2)4i$4s8TGU<-xT zg69s_?f}SpO5(8HjHEoh{r6+fp-wz>^hNd>3y#DKEpsH?#oy_e!SHw}Z(1I9GVH)0 z5?3cPo%h$oC#=(PuD8E}0Ik6Q#+4}lG)rCoR^v5?@hkun*!OL~zsgWN)-~jmcTJwc z_*oa{Te>#23v9#fpKqh;;vuYXMpwy@w+WFr*Z+3t-A;ga}%mM+VAsP4WLKjG4$iP*#kfr(hF zUDNZhRprE>D%7w%S6J#VA9w)Y@c092#3QACW>p{fz)!??ypLN|4LNMtu+#^>Ijn?r zNlPu-1vM42Z_A3McKE^6iXECA8xA}j9RwQ|Y(@veh6huN%kl>PSBq>dd^_-vvddJC iKsf^C2$UnB8G-*Hj!tH4KLhqur zE6iiPJ$1_V+kH@HcHiP^g@-qOn~|B^d#Q}XVHoQ?%2|4zBE zR&=+fZNSNIk+*N1Gf3u6UznV#qqh39Pd4-Azb^%f{&zLlxQa*JR_*n8|G7UktJT`z zpv7eN-rQ%kmD#MxhfR(t{Q&kKgpyc^PlOx##JP=l71i zniB52c*<;ZLn~Vtys*mn_ zpuJ@#=TT|NjfeO*JicJ&pfu&YY;d`B?2yAN!g@^T6eMUdF`za?-pR zlqZqxAo*D8M}o!PjoY$TUlY8w>gyCq-i8U{2Uri6&ikHyz>ZTYze0B9mD*4HZyV&e zS6T8ukX!GsS8+7&>%-8)-f_)6yP79lnq6U;c7&r`(M+NDyFf*d#2g`p8+F(73J>0y z9abWfZ}RT2^w!=C>*UTG(${aDEtfPr6l?e0`Z>LDeI>+IP%8o_M;w(y?MuohUIo2N6`-KOpL77_jv zyWj14=j73pn-MRi6SbxBX6I49KPTc(Stl%7K5x(QtL$p~mrn?ppl%o&amH2p$FACs z>NPVD)JF$tS#6xr@onYO*ZtKOIKQ_>6{(aY_cm-4mfXU*#&82iE?2h5oHjF{V~+9d zeOST#PNqJ7li{UeE8VNx7gx-HrR)F4IsP#II(~FvcF6~GP_FWH^>bP0l+XkKj5U~o literal 0 HcmV?d00001 diff --git a/web/src/component/Access.tsx b/web/src/component/Access.tsx new file mode 100644 index 0000000..2c07268 --- /dev/null +++ b/web/src/component/Access.tsx @@ -0,0 +1,97 @@ +import { intl } from '@/utils/intl'; +import React from 'react'; +import { Button, Checkbox, Menu, Switch, Tooltip } from '@oceanbase/design'; +import { isObject } from 'lodash'; +import type { TooltipProps } from 'antd/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: { + // 为了保证 Tooltip -> span -> disabled Button 的组件结构下,鼠标移出按钮时 Tooltip 可以正常消失,需要设置 pointerEvents: 'none' + // issue: https://github.com/react-component/tooltip/issues/18#issuecomment-650864750 + // 判断逻辑参考自 antd: https://github.com/ant-design/ant-design/blob/master/components/tooltip/index.tsx#L88 + ...(disabled && + (children.type === Button || + children.type === Checkbox || + children.type === Switch) + ? { pointerEvents: 'none' } + : {}), + ...childrenProps.style, + }, + // 从 antd 4.16.0 版本开始,Menu.Item & Menu.SubMenu 支持 HOC,只需要设置 eventKey 即可支持让 Menu.Item & Menu.SubMenu 间接嵌套在 Menu 下 + // https://github.com/ant-design/ant-design/issues/30828#issuecomment-854418007 + ...(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/web/src/component/AobException/index.less b/web/src/component/AobException/index.less new file mode 100644 index 0000000..ce41b5b --- /dev/null +++ b/web/src/component/AobException/index.less @@ -0,0 +1,61 @@ +.container { + display: flex; + align-items: center; + height: 80%; + min-height: 500px; + + .imgWrapper { + flex: 0 0 62.5%; + width: 62.5%; + padding-right: 152px; + zoom: 1; + + &::before, + &::after { + display: table; + content: ' '; + } + + &::after { + clear: both; + height: 0; + font-size: 0; + visibility: hidden; + } + } + + .img { + float: right; + width: 100%; + max-width: 430px; + min-height: 360px; + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: contain; + } + + .content { + flex: auto; + + h1 { + margin-bottom: 24px; + color: #434e59; + font-weight: 600; + font-size: 72px; + line-height: 72px; + } + + .desc { + margin-bottom: 16px; + color: rgba(0, 0, 0, 0.45); + font-size: 20px; + line-height: 28px; + } + + .actions { + button:not(:last-child) { + margin-right: 8px; + } + } + } +} diff --git a/web/src/component/AobException/index.tsx b/web/src/component/AobException/index.tsx new file mode 100644 index 0000000..1b3216e --- /dev/null +++ b/web/src/component/AobException/index.tsx @@ -0,0 +1,76 @@ +import { intl } from '@/utils/intl'; +import React, { createElement } from 'react'; +import { Button } from '@oceanbase/design'; +import styles from './index.less'; + +interface AobExceptionProps { + title?: React.ReactNode; + desc?: React.ReactNode; + img?: string; + actions?: React.ReactNode; + style?: React.CSSProperties; + className?: string; + linkElement?: string; + backText?: string; + redirect?: string; + onBack?: () => void; +} + +class AobException extends React.PureComponent { + constructor(props: AobExceptionProps) { + super(props); + this.state = {}; + } + + public render() { + const { + className, + backText = intl.formatMessage({ + id: 'OBD.component.AobException.ReturnToHomePage', + defaultMessage: '返回首页', + }), + title, + desc, + img, + linkElement = 'a', + actions, + redirect = '/', + onBack, + ...rest + } = this.props; + + return ( +

    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 kPCy$)%PT9; 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%0DN$N<8j%zLi^dn)_V7R7pd^NI9>n6c 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%0DU3IRvX&&w3%|epT zC8J@rGRO;8|EXVw*e;Uvzz8h`T_0A#L-^D-3lj#z(6|N<6)LP{@?NrKfb5?43AF#k7y5z_J8DxV|Sb07E&7e42;>df@yCF?cX?h_V)YVJ;MOTXo1tfSfdlOg*FYHS9M)*_87lBzr=> z0>2+;_Uz4IiOS?_;MUCLjs{>b-(!Gf5Jmr%R7!D!+Ra5jtvAMF=T@^J}g zn`Q~xXgZ>h$p6@KxebRmInTSmY)Re!!Zi|w`w$=mUD4Ed*l|4Z<+UUypbP#_wH=_w z?E*!EG$TNg`2WXVUsF0y0LX7aPPb6<$HXykp8OYnMN9t$B9!789ZH6Qft&sVm^J)N z;^4r3$$?;r-2a@oU>fdUw~NFf;skQne+MM@Md&KmPD)s^DX&IgV&ayt?eB3NxAzP8 zR};XfEe?T<<>8HFkKO&kBc0Ki30J#M}KfFVM#?w z-~rFVl3#d77Z#ietTRG7oh&1HU_?o~hs=Mz$5HvZPPmVlGsFVtNnzSMfQD+mTcnbZ zoRE_y8l0%a6~5VB@{~`Ga2Au~EIkH{MylpURVt-@{?=rr-4nq4ljxQBfOL4~oeUH| z((+i5C861)q9KgBEs`F;|FZ&wu|r&+A1kMym!BjzeHR>q&MRUD`p*yQXNH2t3{zFS z`xQ&#p77j^OlVmz+u;Z90~Q<_nt$-xZo7-b7J$n6zVN%mX)gSQ-o_-mb z^roJJQu_DxMVG)7_zbXEWivez)caLtJs!8~tC!ZwmTQzO@S=(WNDsM6m%Col7xX88 zJqp-=$W@5$REy_U%j8R9K6kQ*^|57)*}SgUxadK+fFE zCfr-3G1bQbv7`Y-zl8V)T`8uBiJRFSk$&qbw<|+=jcYQRY91AhFc|Y#_~P>oS2Jf2 zTSkG3ZkMDH<_HcHB@f86+)}}RLrv^rQh}m>6;ix%+v;}6>KaeMD>9U?)`_^jp ztpkCMGD;=DN(s1bh#4Ky;5+c4`jqDpCUAz7GOK4-Ve?=Ygn_sGKC*=j!O_?xd37TS#hBx$eO74! z1ApEOY@)ti)@G1e4z;O;CC3{IT^<#`o2+h+DWI<|I;Qr*vH${@I41 z=?u9l%+E}r#-T@XTE!ie*It%c?v$c35Ku*pRS=Pi=LCKdHqrSRJkfM z6y`jm^i5OX@L@i$d`^qx(3HR6G}rhTHTRTQ&c*LKovJ>J&};IE`!Z@rVt+4a(d4<( zM^}%t9oP+FgF==@C?R35d*rTCKdF6tz;Q7w9T(^7f4?T)0-WYC`ilPa-_SS020Z@s zuXUI9mid@uR&Oucd**H!NTY<#z3%=s1%;(SJAafItFJzAt2U_Di43@Ex~lr(3lC|=J=vi%0RI*T}5HQfVU$n|zm4T$V=v&P4yvHfOgewtOv6|0Tg{9FF z{svV?u*&C%H6srqXKm2(#0!+tVC)kc$mF0kn8m#%|A;+&I89s|rH>pQT*$nvE7Gf* zA1wU$)&BZaeFbeE|6H-0wytD#!;)l#qwo`AKagKa2zQ%Asb z>}FMB;7=URZ`mWXiy?|A?>R8A6HTq-QCL1NHsTA3Svr$d`Oa^<1^Acr@u-PfTYq9Wt)gd~`@ga`(kH-+68cfd3TmK{>l( z7f;+{ltQcsogzJbrXcP8?E@O1M`9Cq7faCDmQg! zvKU=0%8b5QlFK(X#ai_&hQN@6Eupyo8#7Ka_UaJrm$b1nCP-$=VLysVrc84^ z$2*qMh;bzfbeZ3wmrG!Cyadx5M@_PN>T~R~X?KU=5@48Mcshg~-&ZZ;BW3h$c7!*t-(6Nb{+}XE7=d>Na+H@v zuZ0gIK}0ChTQHdzZPJYqvCil>l&h!)p75E*Q)I)h<|2`tTL&2OX)2PM^xVsgNJ?oG zpgpDC?;igq{|3#1U^y;>iY* zgnK_^#u^rnS`4jkzNO9yZXD8{-lpek;6-Bb+sf0-evguSCV;19KK!*ACRzbECRV8n zlWFtaLbd{Nn|Vvmj#SfVtWbtc==ZL~iZNLHIp0W}2alg~I?R}@$Laf*(S0?6Q87s= zf84d#=dm?IEk7NVMt&bS`$T4o9+Ov{+eFOQGzq8Gqa`z~n!P-mmABVd(;b?yyk<~v z(^JBhR~xoO@BAvXet#0hipk+KHysL3hIvOf>b?K%YF(A0i?4)_kXp71`+(KUK!cue zx1AYlfyF0b3$n-g%|d9EZi&*YT&TU&^j*ugvs{XZvc>UFYkT#fWu#@i=xUvbOyfAJ zJoOe8G=n-U^F9nrcIYv+hr2M0t@8J;kQhX^Ld%gxD<)p*lv{%&fR3tVgMjU=Dh7|2 zaknm8<(GHk`GF4#71_VhD|u%3URQY_H&?1&S%+8>_zl1m3En z6fi-W2daPARITIZ;gTI2a`9Rv#=ps!aFgOQOG$8m2??HiCm5(%!Wkjjl_+sX_!Jkl zO|>j-uqFdtUP_NaN@5Fhe09nLyb!C3EhB+=4i6_ECo<40Yyu^S1x0UU8>}biF@g}Z zt2H9S&ck63OU@9a;n6~>lN zLJi>zua`Rk$$e5&@Wr4s3S0x1#$n471U-;aFUGU&e6#*W#`_V4ol+F>DO8UAOFbR-qk$wx*ji}f0Qrjqscq# zdk@5NID|h}C9B~L5A`2n)^G|vx)s{)M)6&UnY>^6Vnj(XL$Y&rV^PC<8IYc2;$nfi zUK7HS=r><*F`cd7a7t#XpLg2-MF8*Y?Xc8Pu0E#Q4c+f=&lB#h9{y|VoKs~CU6^t1 z-{xW&f8-Od6E<79No*C*04(R)UYixCck}mEUYu4US!gbP?H`?3g`bp@Eet4Vk)TR+HE z6@(I&U<70ZpAaF-4j%WFlCvf8VX4$)HTNb7+{ztgq}!^ua%P01PhuR5K*oQUET`bl zUJQsAz~#{NCV|F}*39OnRri@R&-it{Ca@H8RoM84Z0!;$`@{_yiMQEPKOx4Vd+d(N zKvI_Xqs_ai9Lnr42CnmS2IZWzs2_CoRDZ>vQa#nL3EG0DNsBSNscXurWgWnk4R z&hH{(ydpvK9<#2)rb?>er#(%zaoWg3k-wN>Tf@&I3o6M_88T;TJJx7NI4e; zeMXG6#l#|N4bC|IDwK9ARxb9DR%-ck#Xg^_0C}1#6Z@m>#V5yG4Li>QiTKZNSUw+l z4q_ua2(6gtz)Sfda%mPS4QjQMo6JFncHxqFk&l6GJEntOY_vYx%F)sIHU{A&3>QG@ z8b#;dAggzajo|Ump7K)==3j>c^;>SY%m96pQm8mmN<+RD{f|twUECZ#btGqPeUHzQ zMo{<%A`nwRc%V@ua9zeXBPXEg2?8XvuMM!|kF^Cc)DyLTfp}=Ka21v99#il;D;K~p z%dDD26}|#brcx^2+r|3{Cy6cqe9XIx@-Oz^j{i)o%Md!rkQ0ETbhq$He#{F=C3pfH zx;Q*d)`K#)?0+C6LV7vlI2X&1gul^1=>#wgD~cg`2Z&KXDAoHZ=MaQ18O9J8b6CQq zhKGJ2xc*|=(gakzkuiT@5(1vdSt+c4H}>#{2;Jtz0^i@}hkqc}Jz-$xq8_`EPgrsP z*KRa0B;nlY%=^?K3Usk~AWQ@$VnX6?aPbt8~Hwc7gaLJlg__#0AgX)uv1kG`*rvOAY?~17a7v9 z+ni79fbR8GxdabyV)>gO(EO%L^w$<}==O^6k}pmHg$>>^Pzl65n*ey#u3aR>d4{lc z!-NeyULt`hG6)T!@h_08C6P)8j@V>;cOvA|F&Yq;{l7yHu_df{6HDGZcvtwI@^%C- zL_Z5!|JP|#Bap7VckLh92X;CBpVdZ!dmte~SKawS({pkbN@~4Kcg2i3>FYbT@my? zP8@asvk$vUhyOs^H(S3b=!!17Y(%Lmm;)6@j}hM;KGVx-h9ZZdN~P^8g-dV2%m=Si zfhW-8qmnKJBcXcJTE@)0Y|^FHh7H?(4&@ak3>J<(1OrN=!V%h%>TKGUE1w_;ZvyZ+ zn}&UeVv#Kw$QW=YsyBfMci3p^sPykxD&!;d6b!&*(|SO-;ccXJeL<4bFqKTkIdq=@ z^tM#c^|mUWM$Alz8o@g`Sdt`7^xmflIT?Vrbv!=0ClV-}+-y1b{Rblh6`l`5EO%W( zdhkGBkDu}Eo>y+fYna=`|A98Wr=1&1nkq-0a&v+9%~69Tq&K@;R&&ts=^eDXTU`BG zdpXRvjp70wUIxjy$G;kaUxdHE+#mb4NiF_(rM>Ats6gYx|5C%9eQ~md>&Nr zRQ%lkbT#l4@JDiJcTa4<*0RHPC#n2}Xu)^if!Xz2FJ21P)?ME}P|~GlX-%<0T@ndO zBOmj`<45&x{wpC>sX66E zCW}BE#qSo^i)WWXu#oW}u@Xq#)^VUn_@I2Ss}+<1xW*;~E;DO&ZlNmCmPn!rmlqMP zMy<^(dQe&u8IcO>y{#{`x^3$z9ON2^%r*zKC?$>3l~;uu=7k1Mx!u6Odn_lXSz%C^ zRToKA6WnWfIyS{;lu$T~G%_~4LoZKVfpX(8!X#kGrb*A$OF9GER?yuu;A~L?H|`*; zRirz@#=S{W6-4})S@#PnKw%Hc+jGsJZ2U90>%^B^>np79@mo@JvtIh0wM;9JtI!@J z=y(f?%vYyZtv)B&-AqE^w>O)mK>0+}{j(DCX29*a4zqpzlv~SijV-sx5KVI%t~uOg zV0F3m8qeL-t1ax1xr zHx+enVjS!({r-VYib-?gjk%3*qcRN`*g-1-;ltzI;p-{bm5_0^VXS)LSP+r1gj>fD zlcwSP9VyQgr>fTwuSQR5R5@35p0S?di` zGV*%|5&1G^slVvf`68B+HMs26c!ozKMyPC(G>>sKHaDuE$83iR)U%B97}B_VbKw5H z+To=a7zv2k4Cda(fS5cp{V0&nc)w+?;J(@2z^=1xDG49(uyPU1Uc(*WR^U}C={h&2 z*zOaXqryiP8+WGM+d$pyX0|*DTDY6({{CmdHuLT{p^Z5>ZdE6mQ+o~Q8#CI1#vK{M zr@%Mcj~^u$e=IWf@!XF2qZ!|oi(J)|P!v6QEA&hS0QuPGt^K~at-_OuKUCwbdUXjc z##_1-#{3+`DSYehVqSaj5_ph+R73uU{22Zz{gG-_n(mix38H2JOgM5p&98OOO-dTU zbp_H1g71}PZjSg1085JD#_!jR*$A{PE4054Q{3ODuZ7XcY*?jdn;CenI&^E2FS1{(=N8DzBcm}7Aor-cacbYA3lYTL8Kf3h&{if;* zl}IRl(}3+v`Q@^5;fJG3Rsm(9ZnQ+S$@wib$wIJD*o*IC_$K?;!oSgXh`p z%+EF+KXSwQ?%ez$0e2k?UMI1Hc4hY_u|&6s{)h;OQP%S1<0H;L6W$l$@?jBKs7@EWD}Vhg^m zjH_^v`mGQsS{}4kyPr8ts3;cznn;~X`c6I#Cv93s0cTp6dXK7i7L#x8LI$>}xcxY@ z&0gQXxpUSu&6^R}kg7Ayyeq$tbF>eCH7jb=tS?@J=(Va+A> z(qlUc1w9KIq0?vKE~JwnS6N%)zdKQ{IYW&Iy&J}#D%0g*3DZ@s;~l^v^?#g4bo%COg3It>Co_6*^(OP?L;t{grk||?F^4N z-z6NX$+#X`7cY#k9_qpPZWf!UI7tPRYY^P<(fo3%Krse2wa^=XwFt3CdHs&ck%YyA z80tYpnIn;)PBnypZKxJvKD;#yvyDWED(7ak_x|?1HU-^{NQ^j|?MQJutcyoG^^}Qr zBIxJE2alBTmQ3jp4sKPKS1;*J3W7HC#x4wL0M&ZKuj&8H07KiHM>-BTz|3?sgcBI? zV&JTx&pH*>d5cR0m&$}qe7wfQ<_gg3gnJ|V3F3Lbg&h=;-LA)FV=g)vXS0{rlMxs& zGg0mE?_05w%)6O6p2aTt=oqvA##LmkYUahD*oaYXkV!j z*C{zTpDvbm)nH4S3it$)Rn5*+p|4p3a$85}Pp14#(FrdE(Ih5Vlu3D$9o-lsdxP0f zPxaRI*_>?I%*duXZpTGYm9#H~qcmD)XQy3*$tO1;wSqzC` zmh_Rx`_3~QC~As`X%tT{1rY*>qiu1JHF&aFO$U1q!*M|Pt4GN`BJ&iZ~~kdYLO2Hi%cGIFe6OjN<$Jxl$5OXZLI=r>4Dr z`{dm^#K)S3#fB#n=>XbK+Xb^&1B%7aYI%VBf;SoL=zMiv^hYE(ooGr`HY4W-W+!x z4$>@TCnn`tM9b0*Vde3_=5&;|!*_5hmAJ#hsaKk^{#D-sGk1uH>ym-gZk}MGn1jF= zDJ2H^iiu1f?JEdW@AsocOKw7n_#s{<;Zc*XD{dv&6Y}ssf~&`9ZI)O)}U8?`eM@sG0BySsv`oIXI8M*zLpwIX=XOBy6l{yzZiWlN|F#U{yXwj zDd(uHY&{O4Ve^@{*~9BVO=*OI>=Y?N<;6oh)rcOn0ZF2-bTxw;OY#sKd1^U!+cVY^ z6y=`~<|EzLiinD-b=3f4W0#86G*{I01ZE0Gv0r);cO@Fo-~7(ab5KBFl! zhtxhAYpc*ZA27@K*z`Mjt<~uHAv!QJ=p(2kyQ-i9rqqJdCaoM?$oG5BUU(V?7++V5MgL=5wKV{Na&OGxiMBv0z zAjC7DWLY-x8e_yFoL}}i{IFpjA6R&0ol2T)-&w_-r}bpHO&jJ>d0m)dxG%3HImH3I zgpZL;K$}c@BfixQMwHK(Vy)%X_~n6}WpJI>%A2iZ*#FpNQtYTy!#Tb35CjzKj-BT-=xv!2=>HZhx`}yqxfXP;<#rxcw7YM|;hK zb~^Th3NEgkfOk|o4=Vb-SJjwmUmvv`C20}o7e-n8SUNtQb*{@OVFm^H7*&1v`)o`> ze|H<3^2y;g*r(2mtJdN3am>Ych!-w*CS+*h!B<*nyY^@Qld_9{psg!VIpNU0J=9aM zPtL|M^DN|)32%}obIy87KN1OP|LsN57ox^Yp1FP6zr4Cq=J3l4K@N=kYql$lw+H3K zWH;w3;74MXq!yPT@4I&-Ssd;y^#f|wnzcv_9C&~5T#x-j*r!pK%iItB|0HRY|Lo1m zv)85qhSU}#WOxT%*`sl{FA&^SKVU=r!`p~MsmY}s%ShAT@_=2%zoQ&=N{P|AP|&>P z=b5CfgK6W75|}eOks{@^f@HeRdQrg|6^E9*PsDy*p^njrPZl>=OpQk*^VHH~1JIee zPEx`Z3plAe9g_MCFNSrf%Ku^Nt>fu>0RR7cU7hzb#xPg6iD{<0<7%e6H!;(uo9XVZ z>F#Exo9XG88sq&v`~1G~`%7Fd&W*?QJkQtb<(1X@=T8I5jLuiD!$PF}QRkaP+iLp- zLe&GR6S66EDDO_8q$(;mLUYI=M4PK=KA2_7Mu9~OoqPk)=AJISy*W!RFFWjN9!NzT zEncexE`uwRev6r=ktOFm*^9SjV^W(-P`|DHLMyowH8Fxb0jo@?KZ@icKzeUA)l6Tg z%P=emOV!LH8YFBC2Gyx!lBxwz$kIN2}}#g*D&5vlTMM$>lMcE%Wm|$1hPMfO0RqbNaKl{?;N2 zj~`Zzs8`7g+`E{Y^(JrK+P@!;@qXBN4|VAJSw_dBN~reILNyo1XHh{xK|(o;9Mh&i zI<7B{7(@etf_?9H|Gd*Exten|h{<|oP@F}T&X9{~Qw&^;3gCE~yHuB*FSQvX_Zbze4hM~DY- zn~VlvwK*G>KyTYGV29L>%9SEaFieOJfMY4D?%9HJq;mdz!$5>FX=3;kKscKfVM1`3 zF&Xg1LxWWJdqOmuSY?Wi=jnVly#mZ2vszM_tpNu>Q!C#Fy({?<(2XHD6xPZ#RXoJ= zhu~fskkVRpgMP1mq9AXOYAQUvq&MroSo>$<@QWffU_oqFT~Jks6Ll!w^h;J5OGV-U3OqGruNW?%KrhSiTMe)p=}D#n=w|cPe0W>`Og_;{dfh@=)uG)$Q~B&_g7Hs}FB#2hqo5Fp2kB}<`3=ME>2gTI@W*h!>@&aY$bLU%!WP0q2SZ&INTkleo3|I z7oxcp>VV}kW zNUquVK0MPz;B0o!%YEx)I&{INgRtm;X(C?aZ`mjr?rET&kvC^_P#WkndRzE<@!s#6;@M3X6qggPsedA|ukv9XsB9W)2whn=Q!69JN zwujx1-Q(tFNd>5f8}xnj33xPn8hoU0yOmk%hNvW-tUEXn?0>drxI=4dzY}l#^aipg z;N)SoMh#0RDc<{9MR4Z6bVuL#z}xoVV<=c@qfu7u zyOK9tqJ61`7;q=iL=Sv6{twiabJBg5bDMXDCAi7BdiVPDQFq+~HyiDYH|pdu@-x$~ zQN0?1GqyoI=MA*+E;0Ghl9si((}|#6L%Y?r1KEnOPVc;T={=V{r)!GZ+f%;JT*tl> z^V}ENW(D(VZ|&4UphQ-ctx^mZm|PY&K9+aE^4*Jdgf*Gz$Wm~LuPZgxtgeL4Ff}^$ z5tqQtl}-yj)_!P2qT1~1(sv7jZ`gVSh2Zn9geXSYh#90UnAi2r-&g#$`}-Tk z6!OWg=`0 zd*@5*RCW_SQDziP)uQxqQMS_Ds!pcrFY49(r6)`3lHY3H#!oi+U!vOSRK1EeSuS^6 zEyAhUMT*bQXE6_;8~YI{Pkh8z-osog%>NN9&v~r`m|H`=B!~_fOy(xyOttSfA|5g( zJ43M-%-b0F*y*BoRi@Qgr#VJQxTrq*O;^@}q9s`uPI#GK`YsMDv~9;1q(?$|RooRk zcF@vV;js?UY2?;olC5;@*zcv;`HEB^+Q&xIV7x{MmazY-+Z2Rm`Be%{&-NQqBwngp?Q$XjS`Iev33x9_4 zZ{$i3%C2AAn@E=NT*+_+7zbi*+f{YwE*_nr+N%i<*~CrC@Pm-;YnRQsOJs zCZ9hNkHU9FjrsaeG>4@3(!<^+NQ8X7+_+5EPf7gaWcmru$wO)HDP`@WgSZ0jIW7V96ME&+DKDPol%4SLPKT0D8T;8)CJ+JMz zia)sIg?sK2+Ut} z5&hZ?>u-v->=QK8r_0SE2~5B54bDXd%ILAMkj20eQ)RCs z*L7a`^>;WuFn$xSzrGZa3@rV=2jK(nawS>g`v!tm-n!7n*=}Q-bdOuPI9EWUOr+cs zO`&k8k}X2B84RO3wP@65VqH!@A3;a)cpyZ7?>c6btLqLSf3JW-J&=5#5uu9>o^<641q8wz&n zBgxD+r!87hdoIg%Xn#bprivzQY>5g7q-suB#%)oMm+@SrrI zRM?YLIO~G^5%~k3P-K~MYoN;Q)M{I9RU54#6?1+1dp>=aU8omTfw8IjgiFR?)7V+* z(7MD@Xg#5hk@1knrccBghlSWcC(9KMgC0SbwVp++a80b%X%L&DEQ%mzfJ57)Wf9sJO1qWT{Knt(=H)&Dm$OI>hqw10C{j;XWGwkwRg+$R*0QhQW=oDhYN;9_s)Y21r{dELyk4wk3Wj$W z_-~LmZ+`q)5K*Eb&{h>WcP5oABU~}7X-SE>GC-^jW-&8H@rE}rbA#nr*kZH5Nd4hH4y{OR1z9L701&MKulkARw)OhkmLP|o728HCs; zAiq|trP{C8HU3$*jGj4JlRo%~N^`!BnFVDsOI|1Ga4Ci`)fHC1EgOeEazw^1p+u9- zU?EcKP0@-g1=XYbWgthnQ4gW5UDR86H3;8nMK*iaCfg_9;Ui)dGwix_#$+C~w6AQZ z_Z`bRp|W&=amrOk{x^(N`9Rjc5{E{jkMvs`Cho<=p$RRJbZ=)eF99JE`U+UPvPzDS z+)S9~Ul%~HyYvMO71AW~gF%<&JwXI%;BI zqOVi6b~gr*qTD7*>DZ%G)`eMNO&pM7y;>Nu-7g-Mor;mny5B{OMs2kU0f(F6q!RJj zI}W}_Q6;;fRO95X_(6!gyU=coJC)2N%NO;jA!INA{F&mVH?q*MYC=`ofD?NY6^5XRg?-&k>W)rRhD5l_rl+GSKBkO~cX0|r(_vZf7=Et-nq$7P?6+BK8t9-(DU~JuC4nA|2(hW-7snw9mTw^f zmhuHuiw@FDu7oI*iU&xCQM#lhaZ&BjRV-4Yze;Z68SvttP@O4*V&idYL2O zRcfmqQa+eHn-k`{nV!Guf4GDpHeb4cwXa#{fjMWQtE$zcUby``c@0-AwQG~6I5iy? zfG zh10*AzFqsFT)Vs$dsu_%A>4LmWb%W)Efv*ug>{^m2u=xI#n?2V=78vW^qZthn>8(l zZ{rumZIum6VU4uH`UXprZ|SeMGa}kKaImX$aXRIG&Mg#&md2s_y}V~5Hvf20$~*f_X;oEIr3Z)?9;9))()#xn%B>-}Kp zkvx0->pu`@N6{+VuuVj;8^&;w#=&bSZ@OQ7etjcaMTNu4QP8}BgwOZ-aPdoB)s)R|$ zl}A$pej~ADH=%P&d=Q5P9_4wY4fA^|`CETJ@P6odPBX$hsWJ9ffi@Cy@*4Tjvv$Jm zq(%9n5Oo8fkx`y9-3S}ZYqUnb8$a(J{iu9Ab|*aFSar6p<=!@IA6==NC0bh`TwY#V zjud4uVYl+hQ6g!N@fkrKN$~FG%%DVZkDpySn)-{V<4f;i_#G}wX$75OZsymDPQIn` zB&%6AnyQ3KO}Q-yS^JNKD_jNCkfrYj_B789XyqM9qg5PMwgV+Frm_5EFaHe8sX|A3 z2eMWPHIxI4?~sp6M*V~Oy45|&Lm~=N@GuLrnWael!C*RKC|GA3lt#!z7iaTC!O%P| zd_fz>T1cDpoMvvKe}#cu!Nn&@2gaw3a-MA|N1nP=P|_;}@IXUHc#y+RP6Yky&J~3bg+~___aq`WU=gIv0oBg;T;$ z9v%CKZs*+%Q*6}LR^8XzXx%jQn99qkg4Mvj1T_V3X1@6w3>wR#igLkW9Auz19GDYg z%*+*!A`<=n?}j5I`udowr<9BIM8T)GdH>wM6%>fuUd|9w^d<&|9ey zhJXv;Kl`;xMMvKcm(OIQ$QG0xhbcI7}YZ>e9dJ^h8%FGB%JyW z4k;jy4N@c8@Q}Zr0mo#*9ss*quZc*FzZd0rCXI$U{ZMw5UW%u||CEbvf=nVnwO{cd zwi$Yn^#$nM(k@Wm+2(ohU*U5BEVV|*o}2(6C)qq5cJD=TN#^TE-2_aR+Fe)vnh`1c+-4po=}J-tThB`w(p@^py}nFZ!xwYrwIox5}HbEW_gHc%0IKfLqDI^ss< zYfcm(nPnF~p8~U{s(g6BctI9SN!>#T$P#LS$=*uAY5e&TA-|^yN41gGFmnQSsAIOJ z2Yi7frqPQxpm!80{eXtj^*^m}#TCFeX{aInn^pZECZ+^4NAk3ekT3Q-zl;%}s%4;P zKKVD3@V_qv-VhN3Z0uh{Tu$t^@$)J$5c_{FlR|wOa^Jdmh5@~5r;p^}rdjmVCDSKCcys2ZtN~d4QX2srz-+K#NNva8sY;_&{n1YC4OcPq| z{gpYpnI`Jmx?_=Jg)1NBat09h!@4%fVbTgjlwo^RaD2@qz*&XRu>xV`ATsgTFEPg0 z$~4Y=!xTpE+T%qNRLH|wFW3GW;|y;Bkdq{Bh4)>Du$eU}VEe^Vgm3U&1pHO}6^V9t z-g7B940w(a^ie7pPX`AeC*bjhw*{kUP@(9T)XBM;CV2V?2xJ&fzwiD0ft!vWos9Py zXa~f|kr-YyYj_5x6v9PB!jVLJT!0w$R%h=|A&Rz+H*vS;tsOEkzX2xYe!lWa1h&^M z|M{F^<8}(A{Oq&imQe+&DB&tCl^7~+U0F#|RvlHwXWL9((=+&EK{7gsy!OY4ux`aoTuHS>e0$m6&|0u@v5H>Fk{J za9MPS&6z#_$LWfGi`7U+ zd%m+k32}9%WB?SpMFIthmTfxhCFjs+@%M30-Ji`eK6~g38r?OYi4=EbjJ^4=vWlo% zTXd5ycduF??sa&gA^64p!&-7|pxI9{#PJ_?oxbpx0YirtCKy0rp2aSs>kUdC zO$fq5wPPyLu?N2}3%&3}tXGwaRcY{v*A)9~@_@gVkeM}*U0X`m#d&#D-?m5~s`9oi zArMTPB>L({c#FQEWut8A+yx=9Uc;AZ+!K{8KWFyki5bL7_zf=gBxx;9_QUA=PeN~5 z%3K&%;TLa~i}bIv_!zEt;q62%#9|>Nj2R~6N}gkHR2%I(2Xr6{uMJUR?4(smBqTFU z<^1_4NIfb+idbZ?s3`c(EZnrvh_+AO)98&a+w^6$Cyg47_UL-3=|(_5NgJRRNo`@7 z*vR21}hb3jU#Y!%>tKu9~!LOC6P2Et+arSGS73vIKN~fKrpq(0P=2 zl7@KeG^Cldio8{R@gmAmAOsdBuaqjpXHB;|NTG@#O;9F1sXlO{-?s*}PPHF=(x4=< zZ8k^!F|g2RzDQk%&QbvrZ6>IdW5IB^nx`Gm>fOGcBM%4{uE+7&S8sKj`uJIU;Bzp^ z=jDoSX>vUJmG$7?u^&Sw_7~5@8LEskZN0LDsI zC>HH0aD9}IisJn{^YHI5wQh+f%)9zaSIU07YkcQtPEBRj6s%FUBIC(4&0-=gO*trc zbiEM}b|>J8`E!mb?;ohjFUxEgpr4ApF(O`>HBR${+gbbtEh>$r9}N#YQ;R9@3AMZE(o~ZalmDlmerz z@dTL$19VHlK~e6;fkUV(nUFMWEip8Q8+>>O?VV#gg9LiMgB~GYc2;5(9ZQQ=7Ow}b zd?df5zpxc7YzU1|#|5A2z;T*wW8ZVPuhIG@%-b*?s@I#`{tcu~XgZG)o;6?M`ho!G z7lx@Ad(&EVjB-94;@i`E%9HM%FS3Z@mn2xE@7oT!Erc0QHjj#IW%=wZ`X(HbTO5u#a^V?_O-Hx zXJ)?L?a#mmZwZq-=8W4(my6aw+g38Gvm6kb0a|p+T=HzQnpK9UOpTFh6+AkxGE}RQ z+_(Ekpygt!5Y&kWjI57LyZn&qdZ4{@`+T;&#+ERBj`zDHWRigjM}(GvXnGaJ`l_01G9Lc z=3-Rp5PtBFR;00VEp?rILFNYkLEkw47lH)81iif1UqwHj*=C#xge0nd({6R zEKMf1=8UTcSH>NtyE&;(y95GIHM&||_c}n(2-=TSm;9sdM zlfkU$%0Dy3Ah8Uj#Y75?G%t&8cY@c`8jNa-ek|O)l=(<$2!R48=KiLo)yXqK`6KZ$ zh~*Zt*-jjs(&rHxV%xs>@5K3KjL%qzmnw9t+V;}|SU5lE!s8n1mjbQe7Ii>wsZIv_ zrXA$*$N!JKrT4wg@Y|?<=D- zg%05|uB=l$Do>)~GbSoB>GxS;lSDn;y=sYgIojkgiAJqD)HBmT&79zP)xZTVWXh<)OS88uydSJ(?Q(-Qll@U01}VERVANy_5>&qlr(wf30v zgBBN)~t$(G2BH_(u_PQ3}u>vq$c-14z66%H!KVgnzUe zB*u&k+%BR1HUJa`D-9aYF(S{Me)F6nmQ2wQ-Luccu*5LS+ptqka!+bpPTif+z0hdI zH>LJ>MOT7zvrRIWu<*)oM7;<+=_RS8ts5m)->7P}&_ZKJW#q=ImQ95(l{ z3)ms9q36NPHNXdx^Lh{ldsw(40u=4Iq4sPAl|rHSa&mc%9w>vvT9oJ4!{ zA|b3_P)!b3&JISILnMDv_Y&t8F&rj{qfE!qSmjl?I4IZ*Qog`*)Q-ard%?h{j_jxa zeF@qLuy}h1j3t)=k8P=ixo%(pJ`m5B zeHX5egix0>v1j8OXeW3@(UQ`ayAVlngqhjvqIw20L)MRHZ#C1`pcAfjYgE!j))2mb zoa_(T(%UhhF}RWnSg1GRG1MUUkE=zSA8fH*EKYo8R$fnGo-a-uM5DSR#b|-8@}uJp zZ+8|Q2xSB);U*>30a8m#elxC|zG`Fg>n*~BA=Cy_BFRxzq4(VLtxCk&I^4!o?&8{t zHCW$oo^!^A%6n@tsT{xL%DxT65r-4O43C>0-Im?8Vs^g&;WmBJ5>5m*OqaDo3o6kQ5-zf~K z&9qJF%#~=QbMq1m+}1vddV{`@HF#~t-Mx=%e?6V4re@Af?YZXDb0+m zQrj0QqfR8lxCBpGyK|=ZuHQ0l%@l&`KGTJ=j$d6nAI_ih>kRyMl&of2C_~Yz z1DO(^v_pswNmv8VAbctP!;q|FlS&gFlWgpycufx?q&=lCvfq{&UV+&)C7~G80R|su zRZBMyJ^ML=-1+$U)U;irG`UcYv?P9OBEnhqwFV~@)dFbchHdVT$grogbH%Rf_wQah z?nj_jGS^uS1%5L0iitKhl5y7y4kL9%r}W<&B0hS_Ogp-TGhh}}$Gc{4NuqD*Bb7wY)V7ga--AqpjYq0V1WRAss<{zd)kIL#WC zPgv$=2L%n7Q{>vsc7xTVH52Bk676Un{v;^Dns7>06x&t&;U;m}Awtct0D->I%35mz zGd`70O^1EU__jGl4G8{yU7bPGF*pbVsuP2pg~7~-ZH*;zmFhYEXwi>tpNG}+g#7F!BJCMb zuZ+8;pXr}BpC->AejOPMicEj@=|5gnbOW(TN59TytgU=N?k$ZWIP=9@UazrmcqcLT z@$)&odclvzGUfiEZ`vWRMVc**$;F)J9Y4fJfrsDcd%Y1m?1UsgXO#T-zJ?%P)O|VU z9Rzm9dJsH`9o|^}>o<$0bbA~879Z`*cAnf&&)<<%eqR~HO}P?>{4!7dljyj^$a|pD zbp@T;@6m3e#$ErW1_D2EUv85jeSZK~ z_jy*q;>Gk!N*Nx}Iv4@+g%I`D^)Mg|HJWV=NqUVy7J(XdC++)-@bGN39Y_H1l?D&b zmehWRfX0>_*7W0C2>G;ibEn4}lbB0q7MLah}pc`gVn2ZR8-09=0S8W0`N-+$u*4WlsLhDP zKPs01Gs}&K)kWV^Tul>=>B1FrB<}wL#+yeIYuBT_3@-g*C_dT{fCJz32MC$s<*oVw ze5gW>47}|Z4#f?tM1KB!Vjd=#vzgC~XwJG7685D?UZGmnx``e66>+F>+I^w!A z8~z^%5ESEplK+ZkD?vs;Ihz8!H}&kE2HBgR$jZCU_o9D+1Iw}M`3xqxXvfTwAwK%PO?5du_| z4;OHi|3Du^V1Pu|3DfFRslk~lsrk19`e_4TLovWEtjw$<#haAkurlfo7s&sxW&xS< zKCqub-t~$q5+`=wM;H_f{4O%LPk^e%wC)Q306~^beVsdn%iJ%iw`&Fus>7#u#4il9 zNW9N6grV=yT$*)1=2@80T?55yfUPD(Gn!Qr6(2Pb{pGDMkj$jt_K1G2#)65!nr8DE z5-e2;aRz*8yvVy;KT46131gso<^)`4{ReUnE9l)n52%(}7d? zPM^6VV4cYdlHcAy{K7a6fd|fk_8s7>*1T!zUQ_aw*?2wu9C>=MzN1zr^dHD(b?fKT zl$Tg}tefWwG_-BP<+&;8xN@Hrzv6HIgpBPU-tPZEFFwY4 z9L|5g5)vvgN}Vg@76{Je2K@(`g@nByAbxWobJo1#)S6@5xwJ9)Sa90)xSIXGvElV% zM^pRfSlGd5%(n6kmA+3*>EBn!-L;v+nJ37wFX7SNHCcxpn@WoUWI%^hb8SZKOY zLZW!VN+pWP-^5X!sJu{X1o<*B&67Z$FTrSnvQoBxD zhBe?XN?MtmNJhQ4R7)*uBe)@H_7VrpF7jpcvX&yv&v{0w{M4eTNImYEo4_o>(qI!R z88Dis@;u2JMMv0aB+|i4`vDGprcZGoBEroqaYNITm}Qb)yxDr_ES0eWPKH8u5{?jk z828LN+{qdb#grMDzZN$`0Zq$9NqIi2vNreaLT){q(C-QJUoHeqO>xvRCYngL1k22>fBJVYghx=1)o&69cko@tPFd6 z5)p=jpbdU?i(}!VTof`eWDzddAW1S0A+vu`qBvvHF{U%xgi+5#61_w?PGDLUwgA1E z#?+N^tFq(K9Q?}UKobr@^!G?l>yf?ayA__{?LzsE71y|s@CJu!9yumci>>h!E8T)t zP5FGnq&$aO%TnfUIL;d^)4GA4oEf@D&P^WFKjPf2gbdPVZ(mfc1met+c6z$vmvS(j&3Bws8yl&frKFLoJBZgO?iXSSd- zcPa%!ud zR{Pfa-hLiZTXutUeCnES)PH<-qfAPc2AZSr26A58z=sxEy?m>Kz0g9n(gWI$X~(Gi z!>^-5rCfB}^dzQdTq|O% z!c1n))u9=A(09HhgG-NO^CK!$Oiq=ie1V)@!*p$|9KzLDaqZv#RR6lbq#Sd)^c}Z7 zpg*kLHV&U2{abm9I%$8mu(CB#p+gIm1B}otTD>s);3aNv%hh zn)wBpX#5R{5Qt8?CL%_fv*}N&J4U6Bs`)LHcsI}G00o9nWCNM%&oMl!_GyW;LlK?q zz;jF!e;0(zMOSYzYeY&E39McY7rkEmAQ+R%0!Gp#_VbSxSH+ir5D;XZt*&Qk8mFu= zF%%Dh%5>}IdkjQtuJ_F5PAs`|burka&Ug&B$cngA?TA>tCtL$;cY;g_iBAf(La38s z^j)}UX?|I$-2PHkSGv?uUcodZPoyF!m0y3z)!7KQbD7PF zsd9hqYuPis&sl7~! zISj*rPlVBojYA3vBLH7|%k>a3+d4`4H`<6Y_&r7X&x)`6)*;buuZ*PO-6oNL3G zCD71l!wtgC%$;o8KD%%=AWf4yt0FflVF=_>TBOu3rW3dPxwb>0OEAW>2rq}FtJ{`m zzY6Ln6T8ZmD&R;MQ6L4Q>yD_!F*AXYFgcUV4V#dmyaX}9);O9y1OwCkOWbQMLo_bIjFCa6I_#0k%JqgV`{Ep+P-1o*so)|GTa?kdIDHroe!iGdn_8h>uwn!I8y!E4irPr+q6{I!ow@J@oQ0E zf+zzC=8Rha??X4RGojQ8-*gs(_@af_xoJW!>U)L-w~~+d2nE)eL0Z_X4qDnAM#W;G z>Wik4Pogqxka1CV&mg`!-J6%Z3FbVqD)jCH3=8uP7W7Cp0k!mUjNkf*VODZtgUr5) zV(=z-!biI8OaxvV`=@~>!zjaa`;ftHshD7v4>36U>T)h7lwiKaG#k=dpjmeX+Sn17 zUP#G6(yl+Jw;w!U+%&Ix8Ht=^$N(HwV#eJF`&k}ljw^wnR<$mB4(0?}v|cE{!Od!o8^3G5&a zkHMIc%m}*>!x21F2NV|?kn$y847-&MnKZxqCS-pIyhGtAOUDVivTv6_ESfP`_Vy&Iaao^nAg`y42P!#E^3zHq z{5(qC-!@H1S-}#|p^1s2-JOp^XrL_7S87V5*$THjq^Yu_UqLPv6&zA0XxhN=0xyn* zo}Qic1G-V;!_xp8lTL`Lif-n5j4rcYj{y3oY!l1=!z}YfrG1_zxqdMg9SKmMqW-Vx zctj+IC9@5p%(b>%M;3F+aK5FwPr?-47_*rHDwbthrC4mQUcT!oMu(&?7M6^Qp61-l zcq(}IcP^{j{As1rcEM1Od)))sH%}2U7#%Z1GxC#{+(Fq+Mp_^V(=3wnNc+3%-)7jt zTyYc_4rK>+MfnEZ9s8GkKX;>h*)7lENVGa`GbbaLDg2yy4OeHUZifol0g;i_ZOi7d6&IqSrx2`pLIL zNi1$hCq~*yx7E=vy16tO7wvnSP_wq&&UQw0*ElTQjSc4^dcy=W)x_n?4k4!4QIa4u z7Q63PPl8E%-Ltta?nx&C{CJH-3LlcNTl7v-5bmy=8QALhS z@rV!wK4C7w?Y&f|$%3_(N$GS?8{|3akn`ZB12qNvs;``jQB;f;dJ(IM-21)22@zaG zjF{;A?EKYPDdQCPtW)PP>V{oS!VP;`duHpydQBx+8{C)*VjW!8@BtT6@3(@M&j)hiC*@k?MAZJ!&2g)*Vefe z{}m)#ro1{9a^)jf@cT(SwIpfp?J?kC^`%R?XQFcBgF0&LZ#U}&4%!})$lnyWK6DJL z&avnF?;?qEYpN7SNQ9Q>gPeB-&Wtv0o4;OtT9nd$^y_V0SMUxl?mg(JvM?F8PtJV~ zYOHm!16gACEUdokx;gb5GRT25?muke)^H)c9e()u9|-8I+9vB-D^GuVyl;Lq`t^it z^?h|DHDsD|&ifugnyre3p98sBpbeHbJmfzod=$foy$MY8-QDd z==0(8e&)o>`{!yoEbxJ7VyL5VY5b8dC|Upus2H;>`a6}G>q`@^<9s&xyt?}*qYU&o zKPMoQcJtW@lryA=EAsjk)uz%d$jg@$R{OWb`&z2`J^JcTT%ap!xBWwd^3qAhDfAs3 zFQ*>>zG&aWn*IZAH6%9oy#)&W6U?F%$(#NGDrJryUruE5-lqquJqF_-SK4MI$?$+9 zz8sZ*%b0bjG$aYsUnGYCYiU(qQZ}lK;-F(Ftm&wMgBgw&yLb3|n&?UEVhioySnzL& zr2gS2RO#^xs7MOz7xKmC9WZs-PUrD1H>hdGJnawQe$83Fd*4CcOd$+&B@{XVf{>KY zAM#n-z7Kd!^a8e2qg={bR&VT(n2_(k3}l5XIwzeRbyWEM^LcVu^Vcwn_B-o{qkACO zS3)62kk6*j93Th)G!cTsRu16ET$qtQUmg$d$^b)`Uu4iZj)y~Qs;Bdrr7xfLp8-RR zk$Og@hI|TuZ-f;h;MSZ~Ae0ykqS%j)eQI%;CYrQ6CY|b!`HLJwq)w7ol zP9T`&5BObsWhV$z(LdmRKj3(_V*Wyq!C`-manS&OE2(Dj{t^)EIyJp;o<)EJscA{s z-|i#yn`uISSw_LT6QE?}Pi(N1&hzP_v}sFs}bRp95|i;BoywRZ9wZl&An@@yvwoo3W?AqhTul zU%2sqXB_|MjT92@1&;_`-#b8Bs~iBt!2cI@OosZ1^aF+ZzkuF;$H14S#&t`w0Yj$f zo0571GN&C6fx^51^pVp4>#;d|dlL;*`ZHt;nH^9B>|Fel>oogaMfz`r-bxW|^~Y>B z16!t=ihsM&pE(GCtBfcH`I_t>)^mT17uFg~)pq zLzuXw3SKDq-xMf8K8s@Sb+(`vq#4kIW65C>u@p;Q-p$i5tah4rfT;vsAjqjkCrtP5 z{ctP>plu-%YY9YfNgYT5`7PWb*X7;``Lr&&g&ZasCmDU<$np4(z=Btu`uKeHd$!+7 z1@?HIzs~MTYzfL|iu8IAOQm_ZT)IfiXByr1vE=&;SNZ-{3g5@a&uJ_F4d-LkZRF|j z#-`1k@AzZJsT0MSAKF@^UeVbh*5-ZJuL3Qh(2y&1G>`4ahhDx_4Mu7+Y6my|?+VEW z*UF*XqUAv=T&UX}GJ3xZnb(A(4Mi$`O;?R0!lLP4DIQWoyK~;0#r_ALnJCZLSb%c zTQ-~Rm3h1Hlyw)ds#vCDU@run9Qs~x`2tDxIDTHdst?}+6;v-05h*?AKxme%5H9pZ7zYyiB$SG)u4`Gsq+Zzgr7B)Dz7>N zm#~hTk!q;UKb$?-d>Hu>X+|IPiZ6A?F5{59Hmi>-UvFrhh;xBNYo<|8R*FcU|6APN z(kOcxIy622m)u2582JYtmRPRR-CNxZ8{9%t=7*#&E^=cLGi|4AM_Xw@OG&G`b&C5x zB_Q~kINH%w8}$R%t>BW}JR*Q`lH@H( zZl9tmXg6K2Dbyn1Wxa9ncjTfN1M!jIdiLTXW!te_!WM_|+N#SyIU2@t72H*wQ86`3 zoPpPWoxE|OpTq)Z&OiH6>{T>3U6D82`B~oR&@8bCGgX#_2x}6l-|R=u(TH)>IlDzG z3A3v8>NvLmg;fi1grbo>vV%2SkY8g*X!9FKpv7-PX~vOAcjwJ#d*QaFC(*v=?Lr-s z)DU%9h*N0}Wb)cYXJD4FEk$g4zto4FsSxMOMMo|8I(-pzxzO$;B#L8|@-hLL@BrczdnODv51( zEAE>ZFq1A4(O4i-$NysMt%Krt<8IHv-Q5QZFgOGWPLM!w8QeWsa7eJh2e&|g1P$&G z+}#NY9$W(q4#DNOoqPAbwY#4hcP*4! zkuB9zquOwa_G<1=8j$Hd2!#{M)4{@CNoZ1HSgQwXOVO}^v42yh6l0@elcq^DwpjI8 zvApkqF9!-&O)G;F8)zR~&Wzca&R&UYo z4aE<;i79Y=BpG*}sZnEkdj-vo!EsB|^l-+!>S515lS8>_*=U-gzn&L{mNMx*rCPSm zlocEvG@qjE?OxP^<7bEQ5;DPCzJmTVHN%4nc=G&^m`US&D58bRKz$zFYtYv3YaL7c z_Unh_*j<$O1g|Q>OF2J5t^a1gQ7u|hDD(7oM;g)zRZ}buURCC96v}ZiS%cC{HgviJt13)^yY!b`s;X`OQe@WN(ZTjol!b z(hIj5!p?@%#Cu=8Qa3iD{-muwB{XOjndT*=dMpZmZygt>_YsFt(@?wHAOmykM|sRO zV*`Cyed$JTkLl<_;_QA$orIBMIb@_dy+nN%k&ygymfCPIZ@yLMiPzP1?Z;Xy{n%iP zM^LAI-l#=X(=N6Y3L*9cO0p|a~dKgwG{kkBQ1K9Q7Y4G)uEW6{@a~m^CQYsiIh1p&kJe#b7A&UYlCz+>i{wBXQ=~(M)k;jrK==swLq{~Wx#Tl>cg!+$BXc{#| z#)9oqghV80r(cd>NB-wg2RIn+W76OD0g^da3QW{uu9^>IfyL%tl~6WLH7iTmS!a@a z5|C|P8m98pmnY83OwpOCZ~uOs6VgaGY4BM$=U4UQz3WF~b}(~c4=SPhw#SG4y#@$j zby$bd>er=!Jx;w$m$#4)_dQ_)Q_^w$PW)t)b_e7vtKixEk8vjR)vp&xBS)=hP-yBB z+-nrH!AtWvjfz!5in)z>_TLdE+pIM0pBr{gs%#QAIk~v?D7Z5cREYFxP&_XA#8YI} zy%5+IWQEfx7^IlQJA?yPxPxcz?1P*qvWCL-qEpQ-<(QivNEbDiaEw#YxW;fPmnq$& z<;WnYx)ZqZn>n5ic#)_Qrkn45t@)8szx{Gb`fd6WXFUClww@t%9OjCWKt1}>H%(#J zgaH#K3JtgaI~S3YsCNx%Q2Z@zM)=qBKCC1U(7U1CHuk{;v;m*OFSTJ=!@cV?tC&W9#=22Nw())L4nOm+%i?ytA+r&7dv&5gHm?~5_ z8`Bo!c`eG`qAQ^tTXT-ReR6L=sf12Uzj%Ygq0g@%gbyiuM`$Uy8eqhAm`u+$dZU3- ze_A6y77H()MZa;(j8ExRvyniy5P1n-FslAG{w}gY8|D)mK=HP^Y;=Em&saSx+MQ5E zA>v5k_N}`~$@`;I$<>(S??YLY&)LottAPrOx^hhQ8rmrk4;7@YOH@2>A+aeAxfun! zd>F=ln^D)+L6%~^dJWl&0!r=oUu~>&h+=liuciG}YXWyVd;#1R&k1*9`h?7Y-W>Hf zyDgzu=wxqLvtCydBGWQX-h+@JzR>re-ucA!$52LN;?(#$EV?3kE7M5f!PKCbF;m0e6gI0GL z(N^bCpEegyC4n`$V*+|Pt*xa#g`=>J6R`>_QdR+#rHk^h5Oqo!E7@`H#e>!NncQX2 z*V(hT3T`I`RM7_B3}hkM@H6 zX9c&KUzy`fGQ=_T5jSk?XWK;^9Y*qW2>Q3&-VfFKc^4+_L`qwpb^|{|U)r_&2SQ|j zDz9$~ZG?dJ(wFHgBmId78)aYFM5QTj*Km}KJ2(JSqXM(Xh3>`Iu1}?;YezHvB4bQ! z-1fCXzgPD2D-Y!L%3N94Wh!G#s(euRAuK42us^M^Sfj=2MO2*w&t)Vhv+rXeP$%0m zXozl2_*WfHsyePJL8?YlXUNGV- znrGGbT!IwOz8%cQBeLKhCCov?N|Ur%z2985XtJ8GQBpFu1dY3=P;Nvp*=-yZJ_Ki2-M1hH_X zq)m`U?!pFf!0@z=Ga9Z_$mYEI7YxeMDA9FXe8{Xc}a&Dqk^mXtMBb- zHpbF-qywr5H5;8Fuw^q{PqTGJyV-ing-o-HvUd;q=?difsi0XI>e6}8gFPlYY(Y?R z;c?*Lc&N)!s9KvD2;;fo9`U3dDiRa(nsqF#EsC8rL&z($^zg5oADQv?t*)#zU6b;r zovQqn+%0!FTMc`y!ydtKpR*NNY%BX229-&@GItIV*lUZz5SqPhbycmilK!GMrm-kk zDn*)EGanq=-MH>{bzU;txiC2MQApJf0=hH`StF$=ktf`s?yWR0fqX8y)v&v!i*N7^ zyh^_dW_z7i(SC{#{W-Uj-|qT5^RTSfnqXp^eN33a`#_SU*h`Jz;NCS&%qufckg$ww!G{0_hmO!^*-&ZQ{{cRxGE|NCeMSxn)*7sR8p`jvl-Oi zaiu0<`IOnR7T^H6=AmMJRTQwkQx+eg4FdWd%aoCcaq$h}L)f;{H*(kj)6>;*!t&Xg zsN3=fzfH&;lYFQ2`zp0Vtj0n%>F+l0Q^ z-ITzr4RjE5OeBCnqA9A#Z~FZHxt^}pq7K%rNu-mK8vxf7XLqIr=1KtDE+X)yLKAPQ z_#?*fJZMc3-gMZKaV!7v9@yrf4wmvW?<{&f4zDTWHXbOcWMsjY=3PGktXywON>`?8 z`e)_=sZ7g(3UmFvTFd=?A|QzUyp-MWdyI3nxIYGjpbX}8^zE4iAnPB*&|F5rXx2kC z{JbSBC=KXJV{pD8L2&K{)-Uo4Ky~5o-w_6=?#rc@92u!7@3t`i>21l8oZw@G@GSs; zFWK<@NA2>cx_wM!7@n2ikNuzo3Mj1Up(OMpsRKYu%@C_?Hx_wvye81Pb|KJWbY7yxqN4c#+!0vG=k@QVR?tsH2GSw06q`hXZTe*Kg$ zdIVGzeoRBTVBjY5%x;cr+|q>$w%p;P>=y6@H=WBMF*BbtZwb@56!3T?(n{(fT_s*D zMgx{NeTQJ{F$Q1Tg?1Nz%RmjT6A6 zLq}wQkq6N1JwPy#-9%q_+VD@z3g%~v8nieH^qbm! z4%bIwX!^Ae`uo4t7{jnL>4xBHcqJA?B5YD90P|0$tf|3l{@%f}c#iziZIM-R5F zW!Np?0wk*cyJ7PG@dBXj0Y8~+^z!wi)c*!i{V%UpMex+jX4hH=?mxfPO9hI1gXpAU z%xDHWKq=$ar_7FKcKKr){Q0K_LB>CSS1c9-P>BHOLPWzeeu?LRKo=KW@~=+7_#DtZ zwxzecfNn{B6ien0k3l-k{&BAqz!` zHVF0kG;vtofX(F#kQ2r$WH3*F=SzoEZQrTy?E!zFFqc1|7xK>5Za&-n@|qajg>MQm zuM+#+yc9B*rSyetGS~_=2^&@bZ ziG%yM0cP7~0VMM}R7MI$tiGJFWB}-CM%N~aeJsQsvf!cNSrX>k0Cjj{)=b?M%Ct@V z_16$40zjXA(Jda_diwO?srUhKH@5}mH3Zf?u$W`DZF3eE}Hz(^EdSwEFni%vGaWWsP;2(Zt%xN!_3%K z=w3qde&v6lV-7rVL{WLixpENp)7AsYjpswa4avj%lf*{fzH(9d%hgvmt-`5&vuxD<&1?1( z)ZYP2!c&-m;!T4aYaKc&VLpL0Od<}tP5xTMT}}|};+T@osOibUm=tSvSjSd;RE`Sd zM#!SBn6-KRjaJ7=&j}iT7rR>g^fUV*6Ak1?=tgYE>8r3-G{>;?pe&7JgQ_gr!k@V7 z1W=Fo!prsQ5RNL26oi&hKP*g;z+}|z^G-ZfX=!U?%dB=<(9SBruf^0=h38jd%PzCc z5=tl+5tG@n*@v37-EfvZc=K|nOR-=_pe?8fvKw!iY*@~7Qa(rjMY6zdB7Bs)Un}8f zS>ET;0e=5$Oz{)Sq^9l)3SGMYKyS+vz>8Xx-nm>kjVdvHwYuCUN%A}RzdseX7?ooc zhJ7*hV(lzix?u}U*`2MM^|ihKgee*|P`?9jM03Ic_2JuGgn^|@$EcCQql>$pxoDRlL&WziMer>%kMGJXge3F-bgr}rcr78Y%nW9#~3u^EOv zrw8g|v1rluk3pT1nhJqqbij}jlk*#iif2uX6L_&+`fZC!;rSEqfMfACEi4^oYd zzp%Qy9g;8bp>tytUiZKt{riS4`-p>)!xNL@_|7mtcDxa{E z;_LNE*C($X+^`?0J&zBcE3dQHt=Fd$0jl1*icsiQTwb3TAC4glIZ|jP`%01qQFR%r ze2wWW(8*R-fl3}pPk4uuzO5J6m@7AJi>CH<2g7zmKV!f^g@cXh7n2ZE%h!yiH=K2G znNU+o-6lDagVHoR*X%HQJ=gRn`S{i>JHKP{(XGm9O2vog&tu1zuh0ikAaeX>+WFa< zbm_oue$U#yp$hqiT)&(1jiNEUiJb{a*@6ZOb6!6t=Z%7mkCpDc;))z`kjz0EqIElQ zH8;T=sns%Nuvg$ax(Tt-AiVBQ7nanD8w83UNiDAwRnznxZ}Q)W>*RBea;;#jopV6& ztJ{RlSkSif^N1$djLf>}79|jhbO`2*Sf(UZ{xK_JU7SZ}^)z6(z%e84^(@0ka}O0B zLyI_oYF^0?)Q*CrYNeHtPYx)v44WSb_q`i3y1crP>jJ!uASGUwI-TI8TnPC z*s`MUX?E}*G*Ohd#u2>7fL1eztNb;!(r~u3D8aG#tNV{0DjSd-k~E_aJ1b5Wam49b zeAgSEtco%y{>5o(NI+VxShATh9ehcM6-`zIvuRPSdbQC&Gu%$JXlNW#2&v@JYeRll zMbD5U#|2Z`Y)Yg}w{j%0LR#j0jC+8}|KZX$O%k1i&NqE7o5-FYaogd;p-dtm^fufX zOH?g63kj}#sI<64`;H8gWzH%f(%eDrWS?6?SFp(#z$f(VmnFh>n|{X_Qo1U*VRdu7 zR6hs9Nvq&1FDWz16wR;IqcgQ@u1$fJp=l8D_v&+wJH9UG5dVy|``0l-H}b{CVuPhG zJgmagap6Bu)!LE{@e|Yrm0r%;Ag;_6vC*Tq#w1UU(4T%q{fxl)c&I<~N^FYEOVZGI za+$I$80r$2CfS4?Q&mt*CW8b`o{hi&^Wdc_ z=^Mp7N$|fu2{km*w!asV)7)c|P=y*vSja8KQ;al-_I1Pd=Voc92HokC`>?+0wJ8Z~ zm6|v02O{@Mw%X@1Y#Tb4PmezFf1@Eiw^bxCCsYFGN2AbQjP9@W5NPmgt+~``Tvt1z zmt@QlXTG3$ZeNV%b=uB?c9`32OJy>x-5Of%r6KWX8MTF^OX#@aCRfs@&C32g9JaXS zN>C~5Cj0{dvY5C{4Yq*~$dx`_tRu`rbGijw7$-y;s?6;LILtiS83}qcZa@G2DC1qj z_`Z?9bKipZBsYbZ9O0iFpijUuVaK|-a>~2@6*K0xwX`qjz-aWs;LkR zI&%rzsDGtiDVyiXl7XddWQA5u@Y@|5InmhN6Qz#>OrZMgWl+(3;rV`@|)Fh z>_qJm@~lal#k;DLqj5`P0bfn&WYtj8WK{ZHN#>+)fAJ0*i>6;;n`Ddp(C*#*8$e@N z<;i{`=4j4jn2qqpO77tVaXQJ+wqk)Z(ZvA?rRl3fL2?Vvu|#!*vOnT1cdwvl5xL2_+*NOOM}%W^M35dyJ>ffYnLPG zu)4JqVy(E(;suV&^h=%vXiW7gXhp+@S}ZN}aA6WSn7hKFUc(%?HdY>lNc9Hz)9#=9 z3~l@sUxUP~S%rbeq-9pO-FORB1X@$myG2_GTtc}{ZDk%xxQWQx^0&raquD#8SY$Fw zOnJfGT~&bD;ST~RWmzcv`1~xGP?IvpN7*@rvS!K>}+x6wZh5ov9C#+ ztkpWs9tr|GTa$y!-|-iY9ek}jNtnYT%&XO9qdqb@S41hLWg#msa0Yj)iz@DU71pak z)pCc4B$I+R@{D?v(4ZB%-o}TcNCzPfwbX;E)tazxFGAp`jwVeqJgV?^X8iH*+OGsT zd+^Jv?$i0|=Acum>2gK}wnh}u>#kxcCh8{L%b!97I(N=r?G&f+E20m3)Ied9FzU;R zKau;4`Qf3pmd)93dgZj37-3PLjPZYC%Id^4dg~&T@h24G25K~gTE}_Sh_fbYvBy+S zX_5q?qZKi!=qHx}77G%j(Pl;I##(jmc6DDlzmnpIl)hjg+$lf8#6To7nWBB>5>=te zk5j#tj+;f{eAOnxR;X3k5z0B3`JIra88P(`!exWkh^5)Xe;jr~`N-R4`DylsIiitI zw57VkebfLum$ei-5hU|xF@Em_+GnEDb3&UN=W%I?bmH;$@AiMaz56f-TmmH^Lh7bg zSMy{B3qMT9dK17y2h-K9%06BnBwbvo;SOtfw^TRWT{BHp?a8lMbKZ~qBIC8)9&K(a zU2rU4UArk5<52Jr7-(UmXSq0Be`>#dsPxWPulsiWN|0e?78mnB5E_HGA*FV3bWp^j z_fy-$)Y?#jPbb6vM@eV(ZhmEayn7?f>K2N^9Bc?W*-HCq%yr=EwC?kk>uOn%%y9=> zLRLT^)~vsE3t0cjG?S9A%#cD;;`{!!bGsM2!0aJ8Vn0>z>(i9UJa^c1l8t-&X;q_YnH~8 z%P1&-*ok`F;{6@(@7D`e;(W{v;wK&pFadv%nKVHUL)?8pa1dbH`MWLdtd!m9yJRnK z>84zb>-o=T{$76Sq3|M~+VmDOxzEFpE#sTX%S)J!YYe^Ftw z{4XSN6WH7c08u37Ax{$ZeVoOklCxW^^*=8aTGirwSdRCV7?29M%NNgA zP7e;5qc8!llOaFI+2^t44L%W|9YK&mK<$fk&ZBBr^1tv|21tGQ=3^M44WO3zB1;oY zU;(9t5g`5{VQEo#SWkd19g)YCsxr+9?lDa=u`eh9NN;uP9kmAvc5ef2D56%tyksXF zKbpHdFYgfhu_>g3!8B@G3gbOM)S^ZO$x8UrxPuv94*>R>(Rn|&4Vk4tj31~#yP>*t z((Qh%t@$MlL7y~$GJn&o8p4tsjVkYcdxGBwY|Xd?jQm|S72D_ZQO|8mI}pB}H%CYb z;(#HlF&$JFHiWTvdmm)Pw8P0j!skc1Jj*k~0)zky?w_TlrvML0s}TvIG{ZVDvOk$N z#>w+iWjAg1Z-O0SvyMBA>u8Hg9I)j{XhNk>k1;Xq#i|mKbfJdatHVhQ-Wq{nMnUYYCkk~dvevuBU2Qr^O zTEkKS5vT|y1NlwmN7d-{#HR)YXQYD%*WiKwrNh)CNq0#D5Oh7%_`PSq@b*_h^r@R2 z7zF-@AqDuAfVRi*+p{}h&Z7tPBF+D&ZRvkxp8wmYM5Zc?@th=y>JUTyf6{inKwqV9 zGDE{ZJDoLPYSOVV2#ovjnhj2CW&LjDY#q4yOaX022lFm_Z+j>>;NM$gu`qVKPyRW4 zTz#G~Zd?l386Msf1~Yu!kHOmyl*Zhw17Ke^E@yx-O$*~pJY#*~=9ro(`f(%3>`N~| zegdkYq)dY7+n5TUf&D`&O=IyTq|+=YQ_xDrV(kO>a0H-}KtZVrCc4&#IS3=5jNS4iI zc#b9v0DQ?byun%wMWQc$Lm75Z0Exc)_`Kq!fbLdc<1)Me%LwTJw8H!&m%8ko%p{*h zk7T~dW;{SPL^X=rIbULPfWHtRw2=+F{Q)m?dg0;n%oZemgpmh$!}4>KLh4rB?s7vS z1q--+0yiEpZ}DKu;lRO{`*$zp%-`(6PM<1HHQwLWcs+QIE=->Wh-4liPTOf_dlik2 zwH;14-LL_}Kw5)9Et7YD&G^2jn7v9yan|3-0kMP2Rp}H&K%+^n=JYq?v`YTsT1@do z_lykl7@$D%^K)f;!fHoidvH??pR-;~OLyyo{fYXW*j+k>zD8r<@QMINmG0|b>x3JW z#)}cAA1U;%4HBAFM4rNLX|Cz#?v~dWLid@feV3q0sZWwN_RrbgQr!K9sh#fT31$aJ zfm283B5VHEYe5WS{+=sclJ|i(5tnO_=c&%)BgCs(!)0?d?q81ThF?<#E$k?F_p?@- zx_L{z?qVPXb?AJO*S!mSX8uK2_?guo)Qf;h#)+RwFXu&-K3RVdu%?Q#H&MvZs`9S# zC|iv_+!oHMp#CLyWz=8+d!_Z6{S`l-(3}Oz?10e%FSXYoTTDerSo)^~^({H@k9)RJ z^yN}0E%savkXtITW)@h~P@PYgVEak3f#rhB6JPaLuiVc@oQ=^s{tpsCDnha#U&ew{ zB~q`B65AL|#$8Z=5HP%lGfY^rz&_CURZAf$fl}Uy3(|OqpG22_2*vWQ{d@R@I<2ly z*K9v%QS?wN#z>j_Gu?m$iqA^^3~^U2CVhiW*G#E+q&G#s-|J0JgY+VVN?!yQ(G!az?{w13rwbTLBB`OtWlc0Q8R$?-`s zJ*vEs>Z=J}6o`KsWzIWhlEvNK1n2tIaSPoRzcI>4tgOWjKNU6%gHxUOhKkcAT}VCT zg+6mDx}wx-`jLr7zsSZg_emcUKRW&|9gP>AVw-gb*qRmQF+vd*%slS6~_@9dq1bQ;jynE;qz@4)Ur zP3W&uVm}Lf9ZFh0v|1S2L{$2LK{>7O=NQLT!}Ln0t_dXnV6{2uwrvWIa)PO7tp!7? z6@xdo8fs?LJB@n%7K7t}Tm%f_P`lJO#66pa)!9m}4XXGQZTnk3a$I+o#@BbD(W+IN zkPB77Ib(`&$dPx=$0uZYT`h2$lRF_E$~^#uD!Aw|rk2)IDr3>wemZm9e|M<81bdky zIc*|#PwGjE-3SVz8gl33OU*E|&Z-z%UGb~lJUV+;X;G|cYaCSXMfA#07S$1$CbDta zSRo~m9`;>Ivgqz9!21@Bt_}l$>Z@P#Mf)Vgo!jVx`Ce-_5eGpGC%N9s7!^}KvN|Z1 zClGF1$UbSgU_K~K55M0sv8RWg#5i@fpqd!x$SiHj-?a^bq1@}n_u}OE$fnbH7~mC> z?LK@ou0KK8v3y0UmSblh!0IJ1vg+fX;usI6;e%|+(yGXQn}B}AS+Is67<95`QJPehQXBRMHIEO! z5&*_rf|RdsUa2N?DZIlH&n;5(Q-~q48z3S9s~5}KXe$xr%%{J{8CfZ^P4m{FP(En2 z7}SC|qQOa7TKcAT(DlE}Sva6@C{+VX1IH`!Zx;p;s&d-XEuZNF`>+k8}GPi&E{p%r%@3W=7N&+qX zbc%W`OtlvH5*86IeNmx_nkeBi!|w<7mUs;d$xK3{bn&dNJgl^_^t}(7HIoKxFvVs0 zn=-hGNXScp;j;vBq0rC?8kS;7K2x9%eJJ}H zQ-&Q2$0y_$7$ik9{P;r_Ys`Y@62*tROsVLPa_TmT*EjAN0Zs49WQGg9FHa}}j<9sD zG8sffo-O(t60vru#|}EvzI_)zr8OfB%=wLWlaM!KJ^70rn9JCJ_5{2T&C2L)uLSD3 zp~MS?{B=sda;_4N0}aL?ee80d@+=I9HfuujA}7bq@ZRk_ENTV zONMwiFN3IZ0F$H7FN30}Nk&|;|D9&7^kb#c7=VVo0!1-~f#e8{sn!<)2jUF`l{Hnf zH@gU;QW{E)P2at#8hDBBc**T*%4d>NR9>wv1M`D~QBVHT+hcj-Z;;(m@VdOk2WnRe zM{edwkpC={kHBG|?ZwvZ75nKuB#*}>Y_RFc6{@S(iz@UsY~RYz8NCl^C!9Ti*~)T) zk^UmgQ+^g5FfMixE-otG4OC#7z(5qNxnWlbE@v;r-fU71oll-h1Il5Qkqw_|W^pXB zrWiguRwhRavA;?gXERR!bJI}DRqOyeU(X30i(Y!yN=gbgS^N0k|#jMYC(qKuD$d@#i|~YCIvTqIt9rJ+|y;Q{`;tG3~*mI zBKIbz^p*EIzt)T3i~KHw7VYvSO#@fnab;gw%&uUc*;sLBgCaiJ4?mC>lZ#Q8VTAP2ZZk+_REe@nzf6gwv~-r3MC6CVYdGAZx8( z2N>|WxXskAr<+nPG95irdEcj(g@ldimbC{3oB~Kc)U414=-Jz;xRXFvl#PGRowpKY zD$A4Vk&|KuLu~EG8oeTPk-*WM@E2^+dt@Q{L}6X8$fG-V?X?wDD87YSO-y}U=whuf z`-aR7tx^V6!rU{KUF5`#|I}Y$uKX0or)=`KCL`uXBZBF@fjY+gw)|RkV5psMD_