From 9578a291300ff5153c3062f70288a9e29d42afc7 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 27 Aug 2023 14:37:59 +0800 Subject: [PATCH] first commit --- .changeset/README.md | 26 + .changeset/config.json | 11 + .changeset/tame-phones-dress.md | 5 + .gitignore | 5 + .npmrc | 2 + README.md | 81 + apps/aorta/CHANGELOG.md | 25 + apps/aorta/babel.config.js | 29 + apps/aorta/core/application/readme.md | 11 + apps/aorta/core/domain/Base/emitter/index.ts | 3 + .../core/domain/Tracker/TrackerRepository.ts | 5 + apps/aorta/core/domain/User/UserRepository.ts | 19 + apps/aorta/core/domain/User/UserService.ts | 49 + apps/aorta/core/domain/User/entities/User.ts | 25 + .../core/domain/User/entities/UserInfo.ts | 30 + .../domain/User/entities/UserLoginForm.ts | 19 + .../core/domain/User/events/UserLoggedIn.ts | 16 + apps/aorta/core/domain/readme.md | 132 + apps/aorta/core/infra/api/Request.ts | 143 + apps/aorta/core/infra/api/index.ts | 21 + apps/aorta/core/infra/readme.md | 1 + apps/aorta/env/.env.development | 1 + apps/aorta/env/.env.production | 1 + apps/aorta/env/.env.test | 0 apps/aorta/package.json | 67 + apps/aorta/public/favicon.svg | 8 + apps/aorta/public/img/login_1.webp | Bin 0 -> 56810 bytes apps/aorta/public/img/login_mask.webp | Bin 0 -> 25330 bytes apps/aorta/public/index.html | 17 + .../public/locales/en-US/translation.json | 11 + apps/aorta/public/locales/en/translation.json | 16 + .../public/locales/zh-CN/translation.json | 16 + apps/aorta/public/locales/zh/translation.json | 16 + apps/aorta/scripts/dev.proxy.ts | 25 + apps/aorta/scripts/loaders/babel.loader.ts | 4 + apps/aorta/scripts/loaders/fonts.loader.ts | 12 + apps/aorta/scripts/loaders/img.loader.ts | 12 + apps/aorta/scripts/loaders/json.loader.ts | 9 + apps/aorta/scripts/loaders/style.loader.ts | 30 + apps/aorta/scripts/util/openBrowser.js | 155 + .../aorta/scripts/util/openChrome.applescript | 94 + apps/aorta/scripts/webpack.analyze.ts | 18 + apps/aorta/scripts/webpack.common.ts | 74 + apps/aorta/scripts/webpack.dev.ts | 66 + apps/aorta/scripts/webpack.prod.ts | 103 + apps/aorta/src/App.tsx | 28 + apps/aorta/src/components/LanguageSelect.tsx | 54 + apps/aorta/src/components/Layout/index.tsx | 14 + apps/aorta/src/components/Logo.tsx | 54 + apps/aorta/src/constant.tsx | 27 + apps/aorta/src/context/auth.tsx | 33 + apps/aorta/src/context/domainService.tsx | 25 + apps/aorta/src/hook/useAuth.tsx | 4 + apps/aorta/src/hook/useDomain.tsx | 10 + apps/aorta/src/hook/useTracker.tsx | 31 + apps/aorta/src/index.tsx | 11 + apps/aorta/src/modules/Dashboard/index.tsx | 18 + apps/aorta/src/modules/Login/LoginForm.tsx | 159 + apps/aorta/src/modules/Login/index.less | 52 + apps/aorta/src/modules/Login/index.tsx | 71 + apps/aorta/src/modules/PatientList/index.tsx | 7 + apps/aorta/src/modules/Peripheral/index.tsx | 7 + .../Report/Full/components/Heading/index.less | 31 + .../Report/Full/components/Heading/index.tsx | 27 + .../Full/components/ImageItem/index.less | 33 + .../Full/components/ImageItem/index.tsx | 84 + .../Full/components/Paper/Foot/index.less | 15 + .../Full/components/Paper/Foot/index.tsx | 35 + .../Full/components/Paper/Head/index.less | 13 + .../Full/components/Paper/Head/index.tsx | 33 + .../Report/Full/components/Paper/index.less | 15 + .../Report/Full/components/Paper/index.tsx | 31 + .../Full/components/Paragraph/index.less | 6 + .../Full/components/Paragraph/index.tsx | 11 + .../Full/components/ProgressBar/index.tsx | 42 + .../Full/components/Reference/index.less | 18 + .../Full/components/Reference/index.tsx | 20 + .../Report/Full/components/Table/index.less | 43 + .../Report/Full/components/Table/index.tsx | 58 + apps/aorta/src/modules/Report/Full/index.less | 48 + apps/aorta/src/modules/Report/Full/index.tsx | 132 + .../modules/Report/Full/pages/Aorta/index.tsx | 46 + .../Report/Full/pages/AortaValve/index.tsx | 24 + .../Report/Full/pages/AscAorta/index.tsx | 46 + .../Report/Full/pages/Calcify/index.tsx | 56 + .../Report/Full/pages/Catalogue/index.less | 91 + .../Report/Full/pages/Catalogue/index.tsx | 136 + .../Report/Full/pages/Catalogue/interface.tsx | 20 + .../Report/Full/pages/Coronary/index.tsx | 55 + .../modules/Report/Full/pages/LVOT/index.tsx | 40 + .../Full/pages/LeftCoronarySinus/index.tsx | 63 + .../Full/pages/NoCoronarySinus/index.tsx | 38 + .../Full/pages/PatientProfile/index.less | 70 + .../Full/pages/PatientProfile/index.tsx | 102 + .../Full/pages/ProjectionAngle-P2/index.less | 7 + .../Full/pages/ProjectionAngle-P2/index.tsx | 29 + .../Full/pages/ProjectionAngle/index.less | 36 + .../Full/pages/ProjectionAngle/index.tsx | 95 + .../Report/Full/pages/RightCoronary/index.tsx | 26 + .../Full/pages/RightCoronarySinus/index.tsx | 39 + .../Report/Full/pages/RingShape/index.less | 6 + .../Report/Full/pages/RingShape/index.tsx | 59 + .../modules/Report/Full/pages/SOV/index.tsx | 32 + .../modules/Report/Full/pages/STJ/index.tsx | 66 + .../Report/Full/pages/Slice/index.less | 22 + .../modules/Report/Full/pages/Slice/index.tsx | 44 + .../Report/Full/pages/SuicideLeft/index.tsx | 52 + .../src/modules/Root/Viewer/Root/index.tsx | 7 + apps/aorta/src/modules/User/Profile/index.tsx | 7 + apps/aorta/src/modules/User/Setting/index.tsx | 7 + apps/aorta/src/readme.md | 1 + apps/aorta/src/router/AuthGuard.tsx | 47 + apps/aorta/src/router/index.tsx | 4 + apps/aorta/src/router/router.config.tsx | 50 + apps/aorta/src/styles/app.less | 10 + apps/aorta/tsconfig.json | 34 + apps/cert/.eslintrc.cjs | 29 + apps/cert/.gitignore | 24 + apps/cert/core/domain/Rbac/RbacRepository.ts | 59 + apps/cert/core/domain/Rbac/RbacService.ts | 151 + .../core/domain/Rbac/entities/Permission.ts | 20 + .../core/domain/Rbac/entities/Resource.ts | 6 + apps/cert/core/domain/Rbac/entities/Role.ts | 38 + apps/cert/core/domain/Rbac/entities/User.ts | 32 + apps/cert/core/infra/api/Request.ts | 115 + apps/cert/core/infra/api/index.ts | 82 + apps/cert/index.html | 13 + apps/cert/package.json | 38 + apps/cert/public/favico.svg | 10 + apps/cert/public/wave.svg | 1 + apps/cert/src/App.tsx | 17 + apps/cert/src/assets/react.svg | 1 + apps/cert/src/components/Layout/index.less | 16 + apps/cert/src/components/Layout/index.tsx | 84 + apps/cert/src/constants.ts | 15 + apps/cert/src/context/auth.tsx | 32 + apps/cert/src/context/domainService.tsx | 25 + apps/cert/src/hook/useAuth.tsx | 4 + apps/cert/src/hook/useDomain.tsx | 10 + apps/cert/src/main.tsx | 5 + .../Configuration/Permission/index.tsx | 113 + .../Role/components/EditTab/RoleBaseInfo.tsx | 138 + .../components/EditTab/RoleUsersTable.tsx | 44 + .../Role/components/EditTab/index.tsx | 44 + .../Role/components/RoleAddModal/index.tsx | 83 + .../Role/components/RoleList/index.tsx | 47 + .../src/modules/Configuration/Role/index.less | 28 + .../src/modules/Configuration/Role/index.tsx | 71 + apps/cert/src/modules/Login/index.less | 7 + apps/cert/src/modules/Login/index.tsx | 57 + .../src/modules/User/List/CreateUserForm.tsx | 73 + .../src/modules/User/List/UserEditModal.tsx | 74 + apps/cert/src/modules/User/List/UserTable.tsx | 132 + apps/cert/src/modules/User/List/index.tsx | 85 + .../cert/src/modules/User/Logger/LogTable.tsx | 7 + apps/cert/src/modules/User/Logger/index.tsx | 24 + .../src/modules/User/Management/UserTable.tsx | 117 + apps/cert/src/router/AuthGuard.tsx | 32 + apps/cert/src/router/index.tsx | 4 + apps/cert/src/router/router.config.tsx | 58 + apps/cert/src/styles/app.less | 10 + apps/cert/src/vite-env.d.ts | 1 + apps/cert/tsconfig.json | 43 + apps/cert/tsconfig.node.json | 10 + apps/cert/vite.config.ts | 23 + apps/dmp/.eslintrc.cjs | 29 + apps/dmp/.gitignore | 24 + apps/dmp/core/domain/Dicom/DicomRepository.ts | 13 + apps/dmp/core/domain/Dicom/DicomService.ts | 14 + apps/dmp/core/domain/User/UserRepository.ts | 23 + apps/dmp/core/domain/User/UserService.ts | 50 + apps/dmp/core/domain/User/entities/User.ts | 43 + apps/dmp/core/infra/api/Request.ts | 143 + apps/dmp/core/infra/api/index.ts | 63 + apps/dmp/index.html | 13 + apps/dmp/package.json | 41 + apps/dmp/public/favicon.svg | 1 + apps/dmp/public/test.json | 12 + apps/dmp/public/uploadWorker.js | 27 + apps/dmp/public/wave.svg | 1 + apps/dmp/src/App.tsx | 16 + apps/dmp/src/components/Layout/Menu/index.tsx | 45 + .../Layout/Menu/roleMenu.config.tsx | 46 + apps/dmp/src/components/Layout/index.less | 16 + apps/dmp/src/components/Layout/index.tsx | 27 + apps/dmp/src/config/index.ts | 0 apps/dmp/src/constant.ts | 21 + apps/dmp/src/context/auth.tsx | 32 + apps/dmp/src/context/domainService.tsx | 29 + apps/dmp/src/hook/useAuth.tsx | 4 + apps/dmp/src/hook/useDomain.tsx | 10 + apps/dmp/src/main.tsx | 5 + .../src/modules/Admin/Dicom/List/index.tsx | 7 + .../Admin/Dicom/Upload/DicomTable/columns.tsx | 61 + .../Admin/Dicom/Upload/DicomTable/index.tsx | 76 + .../Dicom/Upload/DicomUploader/index.tsx | 60 + .../Admin/Dicom/Upload/DicomUploader/util.ts | 89 + .../src/modules/Admin/Dicom/Upload/index.tsx | 89 + apps/dmp/src/modules/Admin/index.tsx | 7 + apps/dmp/src/modules/Annotator/List/index.tsx | 7 + apps/dmp/src/modules/Annotator/index.tsx | 7 + apps/dmp/src/modules/Login/index.less | 7 + apps/dmp/src/modules/Login/index.tsx | 63 + apps/dmp/src/router/Guard.tsx | 30 + apps/dmp/src/router/baseRoutes.tsx | 14 + apps/dmp/src/router/index.tsx | 48 + apps/dmp/src/router/roleRoutes.tsx | 41 + apps/dmp/src/styles/app.less | 10 + apps/dmp/src/vite-env.d.ts | 1 + apps/dmp/tsconfig.json | 43 + apps/dmp/tsconfig.node.json | 10 + apps/dmp/vite.config.ts | 33 + apps/services/aorta/docker-compose.yml | 17 + apps/services/aorta/gateway/.env.dev | 8 + apps/services/aorta/gateway/.env.prod | 1 + apps/services/aorta/gateway/.eslintrc.js | 25 + apps/services/aorta/gateway/.gitignore | 35 + apps/services/aorta/gateway/.prettierrc | 4 + apps/services/aorta/gateway/Dockerfile | 7 + apps/services/aorta/gateway/nest-cli.json | 8 + apps/services/aorta/gateway/package.json | 51 + .../aorta/gateway/src/app.controller.ts | 4 + apps/services/aorta/gateway/src/app.module.ts | 61 + .../services/aorta/gateway/src/app.service.ts | 3 + .../aorta/gateway/src/auth/auth.controller.ts | 58 + .../aorta/gateway/src/auth/auth.dto.ts | 6 + .../aorta/gateway/src/auth/auth.module.ts | 23 + .../aorta/gateway/src/auth/auth.service.ts | 4 + apps/services/aorta/gateway/src/constant.ts | 0 .../aorta/gateway/src/db/db.module.ts | 8 + .../aorta/gateway/src/db/mysql.provider.ts | 23 + .../aorta/gateway/src/filter/forbid.filter.ts | 24 + .../aorta/gateway/src/guard/auth.guard.ts | 75 + apps/services/aorta/gateway/src/main.ts | 15 + .../aorta/gateway/src/nacos/nacos.config.ts | 12 + .../aorta/gateway/src/nacos/nacos.module.ts | 8 + .../aorta/gateway/src/nacos/nacos.service.ts | 102 + .../aorta/gateway/src/report/report.config.ts | 8 + .../gateway/src/report/report.controller.ts | 55 + .../aorta/gateway/src/report/report.module.ts | 7 + .../gateway/src/report/report.service.ts | 4 + .../aorta/gateway/src/report/report.util.ts | 18 + .../aorta/gateway/tsconfig.build.json | 4 + apps/services/aorta/gateway/tsconfig.json | 21 + apps/services/aorta/report/.env.dev | 1 + apps/services/aorta/report/.env.prod | 1 + apps/services/aorta/report/.eslintrc.js | 25 + apps/services/aorta/report/.gitignore | 35 + apps/services/aorta/report/.prettierrc | 4 + apps/services/aorta/report/README.md | 73 + apps/services/aorta/report/nest-cli.json | 8 + apps/services/aorta/report/package.json | 53 + apps/services/aorta/report/src/app.config.ts | 8 + .../aorta/report/src/app.controller.ts | 21 + apps/services/aorta/report/src/app.module.ts | 18 + apps/services/aorta/report/src/app.service.ts | 8 + apps/services/aorta/report/src/app.util.ts | 18 + apps/services/aorta/report/src/main.ts | 19 + .../aorta/report/src/nacos/nacos.config.ts | 12 + .../aorta/report/src/nacos/nacos.module.ts | 8 + .../aorta/report/src/nacos/nacos.service.ts | 102 + .../services/aorta/report/tsconfig.build.json | 4 + apps/services/aorta/report/tsconfig.json | 21 + apps/services/cert/authenticate/.env.dev | 21 + apps/services/cert/authenticate/.env.prod | 0 apps/services/cert/authenticate/.eslintrc.js | 25 + apps/services/cert/authenticate/.gitignore | 35 + apps/services/cert/authenticate/.prettierrc | 4 + apps/services/cert/authenticate/README.md | 73 + apps/services/cert/authenticate/nest-cli.json | 8 + apps/services/cert/authenticate/package.json | 50 + .../cert/authenticate/src/app.controller.ts | 65 + .../cert/authenticate/src/app.module.ts | 29 + apps/services/cert/authenticate/src/main.ts | 19 + .../authenticate/src/nacos/nacos.module.ts | 8 + .../authenticate/src/nacos/nacos.service.ts | 108 + .../authenticate/src/redis/redis.entity.ts | 14 + .../authenticate/src/redis/redis.module.ts | 20 + .../authenticate/src/redis/redis.service.ts | 49 + .../cert/authenticate/tsconfig.build.json | 4 + apps/services/cert/authenticate/tsconfig.json | 21 + apps/services/cert/authorize/.env.dev | 8 + apps/services/cert/authorize/.env.prod | 0 apps/services/cert/authorize/.eslintrc.js | 25 + apps/services/cert/authorize/.gitignore | 35 + apps/services/cert/authorize/.prettierrc | 4 + apps/services/cert/authorize/README.md | 73 + apps/services/cert/authorize/nest-cli.json | 8 + apps/services/cert/authorize/package.json | 52 + .../cert/authorize/src/app.controller.ts | 70 + .../services/cert/authorize/src/app.module.ts | 28 + .../cert/authorize/src/app.service.ts | 6 + .../authorize/src/bcrypt/bcrypt.service.ts | 16 + apps/services/cert/authorize/src/main.ts | 20 + .../cert/authorize/src/nacos/nacos.module.ts | 8 + .../cert/authorize/src/nacos/nacos.service.ts | 108 + .../src/rbac/entity/permission.entity.ts | 21 + .../authorize/src/rbac/entity/role.entity.ts | 48 + .../authorize/src/rbac/entity/user.entity.ts | 41 + .../cert/authorize/src/rbac/rbac.module.ts | 26 + .../cert/authorize/src/rbac/rbac.service.ts | 177 + .../authorize/src/user/user.controller.ts | 65 + .../cert/authorize/src/user/user.module.ts | 28 + .../cert/authorize/src/user/user.service.ts | 85 + .../cert/authorize/tsconfig.build.json | 4 + apps/services/cert/authorize/tsconfig.json | 21 + apps/services/cert/gateway/.env.dev | 8 + apps/services/cert/gateway/.env.prod | 1 + apps/services/cert/gateway/.eslintrc.js | 25 + apps/services/cert/gateway/.gitignore | 35 + apps/services/cert/gateway/.prettierrc | 4 + apps/services/cert/gateway/Dockerfile | 7 + apps/services/cert/gateway/README.md | 73 + apps/services/cert/gateway/nest-cli.json | 8 + apps/services/cert/gateway/package.json | 51 + .../gateway/src/admin/admin.controller.ts | 123 + .../cert/gateway/src/admin/admin.dto.ts | 60 + .../cert/gateway/src/admin/admin.module.ts | 23 + .../cert/gateway/src/admin/admin.service.ts | 4 + .../cert/gateway/src/app.controller.ts | 29 + apps/services/cert/gateway/src/app.module.ts | 49 + apps/services/cert/gateway/src/app.service.ts | 30 + .../gateway/src/filter/exceptions.filter.ts | 33 + apps/services/cert/gateway/src/main.ts | 28 + .../src/middleware/trace.middleware.ts | 14 + .../cert/gateway/src/nacos/nacos.module.ts | 8 + .../cert/gateway/src/nacos/nacos.service.ts | 108 + .../cert/gateway/src/resource.table.ts | 53 + .../services/cert/gateway/tsconfig.build.json | 4 + apps/services/cert/gateway/tsconfig.json | 21 + apps/services/dmp/gateway/.env.dev | 8 + apps/services/dmp/gateway/.env.prod | 1 + apps/services/dmp/gateway/.eslintrc.js | 25 + apps/services/dmp/gateway/.gitignore | 35 + apps/services/dmp/gateway/.prettierrc | 4 + apps/services/dmp/gateway/README.md | 73 + apps/services/dmp/gateway/nest-cli.json | 8 + apps/services/dmp/gateway/package.json | 52 + .../dmp/gateway/src/app.controller.ts | 12 + apps/services/dmp/gateway/src/app.module.ts | 49 + apps/services/dmp/gateway/src/app.service.ts | 8 + .../dmp/gateway/src/auth/auth.controller.ts | 53 + .../services/dmp/gateway/src/auth/auth.dto.ts | 4 + .../dmp/gateway/src/filter/forbid.filter.ts | 25 + .../dmp/gateway/src/guard/auth.guard.ts | 75 + apps/services/dmp/gateway/src/main.ts | 26 + .../dmp/gateway/src/user/user.controller.ts | 16 + .../dmp/gateway/src/user/user.module.ts | 22 + apps/services/dmp/gateway/tsconfig.build.json | 4 + apps/services/dmp/gateway/tsconfig.json | 21 + apps/services/logger/.env.dev | 8 + apps/services/logger/.env.prod | 0 apps/services/logger/.eslintrc.js | 25 + apps/services/logger/.gitignore | 35 + apps/services/logger/.prettierrc | 4 + apps/services/logger/README.md | 73 + apps/services/logger/nest-cli.json | 8 + apps/services/logger/package.json | 56 + apps/services/logger/src/app.controller.ts | 27 + apps/services/logger/src/app.module.ts | 20 + apps/services/logger/src/app.service.ts | 6 + apps/services/logger/src/app.util.ts | 21 + apps/services/logger/src/main.ts | 19 + .../services/logger/src/nacos/nacos.module.ts | 8 + .../logger/src/nacos/nacos.service.ts | 108 + apps/services/logger/tsconfig.build.json | 4 + apps/services/logger/tsconfig.json | 21 + apps/services/readme.md | 21 + construct.drawio | 194 + docker-compose.yml | 91 + orthancOHIF/.env | 22 + orthancOHIF/config/orthanc.json | 97 + orthancOHIF/docker-compose.yml | 53 + orthancOHIF/ohifv3/app-config.js | 141 + orthancOHIF/ohifv3/logo.png | Bin 0 -> 22335 bytes orthancOHIF/ohifv3/ohif.conf | 22 + package.json | 34 + packages/hook/package.json | 28 + packages/hook/rollup.config.js | 25 + packages/hook/src/index.ts | 1 + packages/hook/src/useAxios.tsx | 40 + packages/hook/tsconfig.json | 22 + packages/i18n/CHANGELOG.md | 32 + packages/i18n/package.json | 33 + packages/i18n/rollup.config.js | 24 + packages/i18n/src/index.ts | 48 + packages/i18n/tsconfig.json | 22 + packages/mock/package.json | 11 + packages/mock/public/report_patient.json | 3 + packages/oss/package.json | 23 + packages/oss/rollup.config.js | 24 + packages/oss/src/index.ts | 1 + packages/oss/src/minio/index.ts | 58 + packages/oss/tsconfig.json | 26 + packages/util/package.json | 34 + packages/util/rollup.config.js | 28 + packages/util/src/SymmetricCrypto.ts | 26 + packages/util/src/biz.code.ts | 8 + packages/util/src/dom2.ts | 102 + packages/util/src/finger.ts | 10 + packages/util/src/index.ts | 7 + packages/util/src/logger.ts | 40 + packages/util/src/regexp.ts | 8 + packages/util/tsconfig.json | 33 + pnpm-lock.yaml | 13830 ++++++++++++++++ pnpm-workspace.yaml | 7 + terminal.sh | 28 + 407 files changed, 27471 insertions(+) create mode 100644 .changeset/README.md create mode 100644 .changeset/config.json create mode 100644 .changeset/tame-phones-dress.md create mode 100644 .gitignore create mode 100644 .npmrc create mode 100644 README.md create mode 100644 apps/aorta/CHANGELOG.md create mode 100644 apps/aorta/babel.config.js create mode 100644 apps/aorta/core/application/readme.md create mode 100644 apps/aorta/core/domain/Base/emitter/index.ts create mode 100644 apps/aorta/core/domain/Tracker/TrackerRepository.ts create mode 100644 apps/aorta/core/domain/User/UserRepository.ts create mode 100644 apps/aorta/core/domain/User/UserService.ts create mode 100644 apps/aorta/core/domain/User/entities/User.ts create mode 100644 apps/aorta/core/domain/User/entities/UserInfo.ts create mode 100644 apps/aorta/core/domain/User/entities/UserLoginForm.ts create mode 100644 apps/aorta/core/domain/User/events/UserLoggedIn.ts create mode 100644 apps/aorta/core/domain/readme.md create mode 100644 apps/aorta/core/infra/api/Request.ts create mode 100644 apps/aorta/core/infra/api/index.ts create mode 100644 apps/aorta/core/infra/readme.md create mode 100644 apps/aorta/env/.env.development create mode 100644 apps/aorta/env/.env.production create mode 100644 apps/aorta/env/.env.test create mode 100644 apps/aorta/package.json create mode 100644 apps/aorta/public/favicon.svg create mode 100644 apps/aorta/public/img/login_1.webp create mode 100644 apps/aorta/public/img/login_mask.webp create mode 100644 apps/aorta/public/index.html create mode 100644 apps/aorta/public/locales/en-US/translation.json create mode 100644 apps/aorta/public/locales/en/translation.json create mode 100644 apps/aorta/public/locales/zh-CN/translation.json create mode 100644 apps/aorta/public/locales/zh/translation.json create mode 100644 apps/aorta/scripts/dev.proxy.ts create mode 100644 apps/aorta/scripts/loaders/babel.loader.ts create mode 100644 apps/aorta/scripts/loaders/fonts.loader.ts create mode 100644 apps/aorta/scripts/loaders/img.loader.ts create mode 100644 apps/aorta/scripts/loaders/json.loader.ts create mode 100644 apps/aorta/scripts/loaders/style.loader.ts create mode 100644 apps/aorta/scripts/util/openBrowser.js create mode 100644 apps/aorta/scripts/util/openChrome.applescript create mode 100644 apps/aorta/scripts/webpack.analyze.ts create mode 100644 apps/aorta/scripts/webpack.common.ts create mode 100644 apps/aorta/scripts/webpack.dev.ts create mode 100644 apps/aorta/scripts/webpack.prod.ts create mode 100644 apps/aorta/src/App.tsx create mode 100644 apps/aorta/src/components/LanguageSelect.tsx create mode 100644 apps/aorta/src/components/Layout/index.tsx create mode 100644 apps/aorta/src/components/Logo.tsx create mode 100644 apps/aorta/src/constant.tsx create mode 100644 apps/aorta/src/context/auth.tsx create mode 100644 apps/aorta/src/context/domainService.tsx create mode 100644 apps/aorta/src/hook/useAuth.tsx create mode 100644 apps/aorta/src/hook/useDomain.tsx create mode 100644 apps/aorta/src/hook/useTracker.tsx create mode 100644 apps/aorta/src/index.tsx create mode 100644 apps/aorta/src/modules/Dashboard/index.tsx create mode 100644 apps/aorta/src/modules/Login/LoginForm.tsx create mode 100644 apps/aorta/src/modules/Login/index.less create mode 100644 apps/aorta/src/modules/Login/index.tsx create mode 100644 apps/aorta/src/modules/PatientList/index.tsx create mode 100644 apps/aorta/src/modules/Peripheral/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/components/Heading/index.less create mode 100644 apps/aorta/src/modules/Report/Full/components/Heading/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/components/ImageItem/index.less create mode 100644 apps/aorta/src/modules/Report/Full/components/ImageItem/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/components/Paper/Foot/index.less create mode 100644 apps/aorta/src/modules/Report/Full/components/Paper/Foot/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/components/Paper/Head/index.less create mode 100644 apps/aorta/src/modules/Report/Full/components/Paper/Head/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/components/Paper/index.less create mode 100644 apps/aorta/src/modules/Report/Full/components/Paper/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/components/Paragraph/index.less create mode 100644 apps/aorta/src/modules/Report/Full/components/Paragraph/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/components/ProgressBar/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/components/Reference/index.less create mode 100644 apps/aorta/src/modules/Report/Full/components/Reference/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/components/Table/index.less create mode 100644 apps/aorta/src/modules/Report/Full/components/Table/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/index.less create mode 100644 apps/aorta/src/modules/Report/Full/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/Aorta/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/AortaValve/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/AscAorta/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/Calcify/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/Catalogue/index.less create mode 100644 apps/aorta/src/modules/Report/Full/pages/Catalogue/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/Catalogue/interface.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/Coronary/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/LVOT/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/LeftCoronarySinus/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/NoCoronarySinus/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/PatientProfile/index.less create mode 100644 apps/aorta/src/modules/Report/Full/pages/PatientProfile/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/ProjectionAngle-P2/index.less create mode 100644 apps/aorta/src/modules/Report/Full/pages/ProjectionAngle-P2/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/ProjectionAngle/index.less create mode 100644 apps/aorta/src/modules/Report/Full/pages/ProjectionAngle/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/RightCoronary/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/RightCoronarySinus/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/RingShape/index.less create mode 100644 apps/aorta/src/modules/Report/Full/pages/RingShape/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/SOV/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/STJ/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/Slice/index.less create mode 100644 apps/aorta/src/modules/Report/Full/pages/Slice/index.tsx create mode 100644 apps/aorta/src/modules/Report/Full/pages/SuicideLeft/index.tsx create mode 100644 apps/aorta/src/modules/Root/Viewer/Root/index.tsx create mode 100644 apps/aorta/src/modules/User/Profile/index.tsx create mode 100644 apps/aorta/src/modules/User/Setting/index.tsx create mode 100644 apps/aorta/src/readme.md create mode 100644 apps/aorta/src/router/AuthGuard.tsx create mode 100644 apps/aorta/src/router/index.tsx create mode 100644 apps/aorta/src/router/router.config.tsx create mode 100644 apps/aorta/src/styles/app.less create mode 100644 apps/aorta/tsconfig.json create mode 100644 apps/cert/.eslintrc.cjs create mode 100644 apps/cert/.gitignore create mode 100644 apps/cert/core/domain/Rbac/RbacRepository.ts create mode 100644 apps/cert/core/domain/Rbac/RbacService.ts create mode 100644 apps/cert/core/domain/Rbac/entities/Permission.ts create mode 100644 apps/cert/core/domain/Rbac/entities/Resource.ts create mode 100644 apps/cert/core/domain/Rbac/entities/Role.ts create mode 100644 apps/cert/core/domain/Rbac/entities/User.ts create mode 100644 apps/cert/core/infra/api/Request.ts create mode 100644 apps/cert/core/infra/api/index.ts create mode 100644 apps/cert/index.html create mode 100644 apps/cert/package.json create mode 100644 apps/cert/public/favico.svg create mode 100644 apps/cert/public/wave.svg create mode 100644 apps/cert/src/App.tsx create mode 100644 apps/cert/src/assets/react.svg create mode 100644 apps/cert/src/components/Layout/index.less create mode 100644 apps/cert/src/components/Layout/index.tsx create mode 100644 apps/cert/src/constants.ts create mode 100644 apps/cert/src/context/auth.tsx create mode 100644 apps/cert/src/context/domainService.tsx create mode 100644 apps/cert/src/hook/useAuth.tsx create mode 100644 apps/cert/src/hook/useDomain.tsx create mode 100644 apps/cert/src/main.tsx create mode 100644 apps/cert/src/modules/Configuration/Permission/index.tsx create mode 100644 apps/cert/src/modules/Configuration/Role/components/EditTab/RoleBaseInfo.tsx create mode 100644 apps/cert/src/modules/Configuration/Role/components/EditTab/RoleUsersTable.tsx create mode 100644 apps/cert/src/modules/Configuration/Role/components/EditTab/index.tsx create mode 100644 apps/cert/src/modules/Configuration/Role/components/RoleAddModal/index.tsx create mode 100644 apps/cert/src/modules/Configuration/Role/components/RoleList/index.tsx create mode 100644 apps/cert/src/modules/Configuration/Role/index.less create mode 100644 apps/cert/src/modules/Configuration/Role/index.tsx create mode 100644 apps/cert/src/modules/Login/index.less create mode 100644 apps/cert/src/modules/Login/index.tsx create mode 100644 apps/cert/src/modules/User/List/CreateUserForm.tsx create mode 100644 apps/cert/src/modules/User/List/UserEditModal.tsx create mode 100644 apps/cert/src/modules/User/List/UserTable.tsx create mode 100644 apps/cert/src/modules/User/List/index.tsx create mode 100644 apps/cert/src/modules/User/Logger/LogTable.tsx create mode 100644 apps/cert/src/modules/User/Logger/index.tsx create mode 100644 apps/cert/src/modules/User/Management/UserTable.tsx create mode 100644 apps/cert/src/router/AuthGuard.tsx create mode 100644 apps/cert/src/router/index.tsx create mode 100644 apps/cert/src/router/router.config.tsx create mode 100644 apps/cert/src/styles/app.less create mode 100644 apps/cert/src/vite-env.d.ts create mode 100644 apps/cert/tsconfig.json create mode 100644 apps/cert/tsconfig.node.json create mode 100644 apps/cert/vite.config.ts create mode 100644 apps/dmp/.eslintrc.cjs create mode 100644 apps/dmp/.gitignore create mode 100644 apps/dmp/core/domain/Dicom/DicomRepository.ts create mode 100644 apps/dmp/core/domain/Dicom/DicomService.ts create mode 100644 apps/dmp/core/domain/User/UserRepository.ts create mode 100644 apps/dmp/core/domain/User/UserService.ts create mode 100644 apps/dmp/core/domain/User/entities/User.ts create mode 100644 apps/dmp/core/infra/api/Request.ts create mode 100644 apps/dmp/core/infra/api/index.ts create mode 100644 apps/dmp/index.html create mode 100644 apps/dmp/package.json create mode 100644 apps/dmp/public/favicon.svg create mode 100644 apps/dmp/public/test.json create mode 100644 apps/dmp/public/uploadWorker.js create mode 100644 apps/dmp/public/wave.svg create mode 100644 apps/dmp/src/App.tsx create mode 100644 apps/dmp/src/components/Layout/Menu/index.tsx create mode 100644 apps/dmp/src/components/Layout/Menu/roleMenu.config.tsx create mode 100644 apps/dmp/src/components/Layout/index.less create mode 100644 apps/dmp/src/components/Layout/index.tsx create mode 100644 apps/dmp/src/config/index.ts create mode 100644 apps/dmp/src/constant.ts create mode 100644 apps/dmp/src/context/auth.tsx create mode 100644 apps/dmp/src/context/domainService.tsx create mode 100644 apps/dmp/src/hook/useAuth.tsx create mode 100644 apps/dmp/src/hook/useDomain.tsx create mode 100644 apps/dmp/src/main.tsx create mode 100644 apps/dmp/src/modules/Admin/Dicom/List/index.tsx create mode 100644 apps/dmp/src/modules/Admin/Dicom/Upload/DicomTable/columns.tsx create mode 100644 apps/dmp/src/modules/Admin/Dicom/Upload/DicomTable/index.tsx create mode 100644 apps/dmp/src/modules/Admin/Dicom/Upload/DicomUploader/index.tsx create mode 100644 apps/dmp/src/modules/Admin/Dicom/Upload/DicomUploader/util.ts create mode 100644 apps/dmp/src/modules/Admin/Dicom/Upload/index.tsx create mode 100644 apps/dmp/src/modules/Admin/index.tsx create mode 100644 apps/dmp/src/modules/Annotator/List/index.tsx create mode 100644 apps/dmp/src/modules/Annotator/index.tsx create mode 100644 apps/dmp/src/modules/Login/index.less create mode 100644 apps/dmp/src/modules/Login/index.tsx create mode 100644 apps/dmp/src/router/Guard.tsx create mode 100644 apps/dmp/src/router/baseRoutes.tsx create mode 100644 apps/dmp/src/router/index.tsx create mode 100644 apps/dmp/src/router/roleRoutes.tsx create mode 100644 apps/dmp/src/styles/app.less create mode 100644 apps/dmp/src/vite-env.d.ts create mode 100644 apps/dmp/tsconfig.json create mode 100644 apps/dmp/tsconfig.node.json create mode 100644 apps/dmp/vite.config.ts create mode 100644 apps/services/aorta/docker-compose.yml create mode 100644 apps/services/aorta/gateway/.env.dev create mode 100644 apps/services/aorta/gateway/.env.prod create mode 100644 apps/services/aorta/gateway/.eslintrc.js create mode 100644 apps/services/aorta/gateway/.gitignore create mode 100644 apps/services/aorta/gateway/.prettierrc create mode 100644 apps/services/aorta/gateway/Dockerfile create mode 100644 apps/services/aorta/gateway/nest-cli.json create mode 100644 apps/services/aorta/gateway/package.json create mode 100644 apps/services/aorta/gateway/src/app.controller.ts create mode 100644 apps/services/aorta/gateway/src/app.module.ts create mode 100644 apps/services/aorta/gateway/src/app.service.ts create mode 100644 apps/services/aorta/gateway/src/auth/auth.controller.ts create mode 100644 apps/services/aorta/gateway/src/auth/auth.dto.ts create mode 100644 apps/services/aorta/gateway/src/auth/auth.module.ts create mode 100644 apps/services/aorta/gateway/src/auth/auth.service.ts create mode 100644 apps/services/aorta/gateway/src/constant.ts create mode 100644 apps/services/aorta/gateway/src/db/db.module.ts create mode 100644 apps/services/aorta/gateway/src/db/mysql.provider.ts create mode 100644 apps/services/aorta/gateway/src/filter/forbid.filter.ts create mode 100644 apps/services/aorta/gateway/src/guard/auth.guard.ts create mode 100644 apps/services/aorta/gateway/src/main.ts create mode 100644 apps/services/aorta/gateway/src/nacos/nacos.config.ts create mode 100644 apps/services/aorta/gateway/src/nacos/nacos.module.ts create mode 100644 apps/services/aorta/gateway/src/nacos/nacos.service.ts create mode 100644 apps/services/aorta/gateway/src/report/report.config.ts create mode 100644 apps/services/aorta/gateway/src/report/report.controller.ts create mode 100644 apps/services/aorta/gateway/src/report/report.module.ts create mode 100644 apps/services/aorta/gateway/src/report/report.service.ts create mode 100644 apps/services/aorta/gateway/src/report/report.util.ts create mode 100644 apps/services/aorta/gateway/tsconfig.build.json create mode 100644 apps/services/aorta/gateway/tsconfig.json create mode 100644 apps/services/aorta/report/.env.dev create mode 100644 apps/services/aorta/report/.env.prod create mode 100644 apps/services/aorta/report/.eslintrc.js create mode 100644 apps/services/aorta/report/.gitignore create mode 100644 apps/services/aorta/report/.prettierrc create mode 100644 apps/services/aorta/report/README.md create mode 100644 apps/services/aorta/report/nest-cli.json create mode 100644 apps/services/aorta/report/package.json create mode 100644 apps/services/aorta/report/src/app.config.ts create mode 100644 apps/services/aorta/report/src/app.controller.ts create mode 100644 apps/services/aorta/report/src/app.module.ts create mode 100644 apps/services/aorta/report/src/app.service.ts create mode 100644 apps/services/aorta/report/src/app.util.ts create mode 100644 apps/services/aorta/report/src/main.ts create mode 100644 apps/services/aorta/report/src/nacos/nacos.config.ts create mode 100644 apps/services/aorta/report/src/nacos/nacos.module.ts create mode 100644 apps/services/aorta/report/src/nacos/nacos.service.ts create mode 100644 apps/services/aorta/report/tsconfig.build.json create mode 100644 apps/services/aorta/report/tsconfig.json create mode 100644 apps/services/cert/authenticate/.env.dev create mode 100644 apps/services/cert/authenticate/.env.prod create mode 100644 apps/services/cert/authenticate/.eslintrc.js create mode 100644 apps/services/cert/authenticate/.gitignore create mode 100644 apps/services/cert/authenticate/.prettierrc create mode 100644 apps/services/cert/authenticate/README.md create mode 100644 apps/services/cert/authenticate/nest-cli.json create mode 100644 apps/services/cert/authenticate/package.json create mode 100644 apps/services/cert/authenticate/src/app.controller.ts create mode 100644 apps/services/cert/authenticate/src/app.module.ts create mode 100644 apps/services/cert/authenticate/src/main.ts create mode 100644 apps/services/cert/authenticate/src/nacos/nacos.module.ts create mode 100644 apps/services/cert/authenticate/src/nacos/nacos.service.ts create mode 100644 apps/services/cert/authenticate/src/redis/redis.entity.ts create mode 100644 apps/services/cert/authenticate/src/redis/redis.module.ts create mode 100644 apps/services/cert/authenticate/src/redis/redis.service.ts create mode 100644 apps/services/cert/authenticate/tsconfig.build.json create mode 100644 apps/services/cert/authenticate/tsconfig.json create mode 100644 apps/services/cert/authorize/.env.dev create mode 100644 apps/services/cert/authorize/.env.prod create mode 100644 apps/services/cert/authorize/.eslintrc.js create mode 100644 apps/services/cert/authorize/.gitignore create mode 100644 apps/services/cert/authorize/.prettierrc create mode 100644 apps/services/cert/authorize/README.md create mode 100644 apps/services/cert/authorize/nest-cli.json create mode 100644 apps/services/cert/authorize/package.json create mode 100644 apps/services/cert/authorize/src/app.controller.ts create mode 100644 apps/services/cert/authorize/src/app.module.ts create mode 100644 apps/services/cert/authorize/src/app.service.ts create mode 100644 apps/services/cert/authorize/src/bcrypt/bcrypt.service.ts create mode 100644 apps/services/cert/authorize/src/main.ts create mode 100644 apps/services/cert/authorize/src/nacos/nacos.module.ts create mode 100644 apps/services/cert/authorize/src/nacos/nacos.service.ts create mode 100644 apps/services/cert/authorize/src/rbac/entity/permission.entity.ts create mode 100644 apps/services/cert/authorize/src/rbac/entity/role.entity.ts create mode 100644 apps/services/cert/authorize/src/rbac/entity/user.entity.ts create mode 100644 apps/services/cert/authorize/src/rbac/rbac.module.ts create mode 100644 apps/services/cert/authorize/src/rbac/rbac.service.ts create mode 100644 apps/services/cert/authorize/src/user/user.controller.ts create mode 100644 apps/services/cert/authorize/src/user/user.module.ts create mode 100644 apps/services/cert/authorize/src/user/user.service.ts create mode 100644 apps/services/cert/authorize/tsconfig.build.json create mode 100644 apps/services/cert/authorize/tsconfig.json create mode 100644 apps/services/cert/gateway/.env.dev create mode 100644 apps/services/cert/gateway/.env.prod create mode 100644 apps/services/cert/gateway/.eslintrc.js create mode 100644 apps/services/cert/gateway/.gitignore create mode 100644 apps/services/cert/gateway/.prettierrc create mode 100644 apps/services/cert/gateway/Dockerfile create mode 100644 apps/services/cert/gateway/README.md create mode 100644 apps/services/cert/gateway/nest-cli.json create mode 100644 apps/services/cert/gateway/package.json create mode 100644 apps/services/cert/gateway/src/admin/admin.controller.ts create mode 100644 apps/services/cert/gateway/src/admin/admin.dto.ts create mode 100644 apps/services/cert/gateway/src/admin/admin.module.ts create mode 100644 apps/services/cert/gateway/src/admin/admin.service.ts create mode 100644 apps/services/cert/gateway/src/app.controller.ts create mode 100644 apps/services/cert/gateway/src/app.module.ts create mode 100644 apps/services/cert/gateway/src/app.service.ts create mode 100644 apps/services/cert/gateway/src/filter/exceptions.filter.ts create mode 100644 apps/services/cert/gateway/src/main.ts create mode 100644 apps/services/cert/gateway/src/middleware/trace.middleware.ts create mode 100644 apps/services/cert/gateway/src/nacos/nacos.module.ts create mode 100644 apps/services/cert/gateway/src/nacos/nacos.service.ts create mode 100644 apps/services/cert/gateway/src/resource.table.ts create mode 100644 apps/services/cert/gateway/tsconfig.build.json create mode 100644 apps/services/cert/gateway/tsconfig.json create mode 100644 apps/services/dmp/gateway/.env.dev create mode 100644 apps/services/dmp/gateway/.env.prod create mode 100644 apps/services/dmp/gateway/.eslintrc.js create mode 100644 apps/services/dmp/gateway/.gitignore create mode 100644 apps/services/dmp/gateway/.prettierrc create mode 100644 apps/services/dmp/gateway/README.md create mode 100644 apps/services/dmp/gateway/nest-cli.json create mode 100644 apps/services/dmp/gateway/package.json create mode 100644 apps/services/dmp/gateway/src/app.controller.ts create mode 100644 apps/services/dmp/gateway/src/app.module.ts create mode 100644 apps/services/dmp/gateway/src/app.service.ts create mode 100644 apps/services/dmp/gateway/src/auth/auth.controller.ts create mode 100644 apps/services/dmp/gateway/src/auth/auth.dto.ts create mode 100644 apps/services/dmp/gateway/src/filter/forbid.filter.ts create mode 100644 apps/services/dmp/gateway/src/guard/auth.guard.ts create mode 100644 apps/services/dmp/gateway/src/main.ts create mode 100644 apps/services/dmp/gateway/src/user/user.controller.ts create mode 100644 apps/services/dmp/gateway/src/user/user.module.ts create mode 100644 apps/services/dmp/gateway/tsconfig.build.json create mode 100644 apps/services/dmp/gateway/tsconfig.json create mode 100644 apps/services/logger/.env.dev create mode 100644 apps/services/logger/.env.prod create mode 100644 apps/services/logger/.eslintrc.js create mode 100644 apps/services/logger/.gitignore create mode 100644 apps/services/logger/.prettierrc create mode 100644 apps/services/logger/README.md create mode 100644 apps/services/logger/nest-cli.json create mode 100644 apps/services/logger/package.json create mode 100644 apps/services/logger/src/app.controller.ts create mode 100644 apps/services/logger/src/app.module.ts create mode 100644 apps/services/logger/src/app.service.ts create mode 100644 apps/services/logger/src/app.util.ts create mode 100644 apps/services/logger/src/main.ts create mode 100644 apps/services/logger/src/nacos/nacos.module.ts create mode 100644 apps/services/logger/src/nacos/nacos.service.ts create mode 100644 apps/services/logger/tsconfig.build.json create mode 100644 apps/services/logger/tsconfig.json create mode 100644 apps/services/readme.md create mode 100644 construct.drawio create mode 100644 docker-compose.yml create mode 100644 orthancOHIF/.env create mode 100644 orthancOHIF/config/orthanc.json create mode 100644 orthancOHIF/docker-compose.yml create mode 100644 orthancOHIF/ohifv3/app-config.js create mode 100644 orthancOHIF/ohifv3/logo.png create mode 100644 orthancOHIF/ohifv3/ohif.conf create mode 100644 package.json create mode 100644 packages/hook/package.json create mode 100644 packages/hook/rollup.config.js create mode 100644 packages/hook/src/index.ts create mode 100644 packages/hook/src/useAxios.tsx create mode 100644 packages/hook/tsconfig.json create mode 100644 packages/i18n/CHANGELOG.md create mode 100644 packages/i18n/package.json create mode 100644 packages/i18n/rollup.config.js create mode 100644 packages/i18n/src/index.ts create mode 100644 packages/i18n/tsconfig.json create mode 100644 packages/mock/package.json create mode 100644 packages/mock/public/report_patient.json create mode 100644 packages/oss/package.json create mode 100644 packages/oss/rollup.config.js create mode 100644 packages/oss/src/index.ts create mode 100644 packages/oss/src/minio/index.ts create mode 100644 packages/oss/tsconfig.json create mode 100644 packages/util/package.json create mode 100644 packages/util/rollup.config.js create mode 100644 packages/util/src/SymmetricCrypto.ts create mode 100644 packages/util/src/biz.code.ts create mode 100644 packages/util/src/dom2.ts create mode 100644 packages/util/src/finger.ts create mode 100644 packages/util/src/index.ts create mode 100644 packages/util/src/logger.ts create mode 100644 packages/util/src/regexp.ts create mode 100644 packages/util/tsconfig.json create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml create mode 100755 terminal.sh diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 0000000..ac28fbc --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,26 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works +with multi-package repos, or single-package repos to help you version and publish your code. You can +find the full documentation for it [in our repository](https://github.com/changesets/changesets) + +We have a quick list of common questions to get you started engaging with this project in +[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) + + +## config.json + +- commit:类型为布尔值,默认值为false。当将此字段配置为true时,在执行change和bump命令时,将自动执行提交代码操作。 +- access:类型为restricted | public,默认值为restricted。用于配置当前包的发布形式,如果配置为restricted,则作为私有包发布,如果为public,则发布公共范围包。 +- baseBranch:类型为字符串,默认值为main。仓库主分支。该配置用于计算当前分支的变更包并进行分类。 +- ignore:类型为字符串数组,默认值为空数组。用于声明执行bump命令时忽略的包,与bump命令的–ignore参数用法一致,注意两者不能同时使用。 +- fixed:类型为字符串数组数组,默认值为空数组。用于在monorepo中对包进行分组,相同分组中的包版本号将进行绑定,每次执行bump命令时,同一分组中的包只要有一个升级版本号,其他会一起升级。支持使用正则匹配包名称。 +- linked:类型为字符串数组数组,默认值为空数组。与fixed类似,也是对monorepo中对包进行分组,但是每次执行bump命令时,只有和changeset声明的变更相关的包才会升级版本号,同一分组的变更包的版本号将保持一致。支持使用正则匹配包名称。 +- updateInternalDependencies:类型为patch | minor,默认值为patch。用于声明更新内部依赖的版本号规则。当执行bump命令升级版本号时,默认会自动更新仓库中使用该包的依赖声明。 +- changelog:类型为布尔值 | 字符串 | [字符串, unknow],默认值为@changesets/cli/changelog。生成Changelog规则。 + +## bump + +MAJOR(主要)版本:当你做出不兼容的 API 更改时,需要增加`主版本`号。 +MINOR(次要)版本:当你以向后兼容的方式引入新功能时,需要增加`次版本`号。 +PATCH(补丁)版本:当你进行向后兼容的错误修复时,需要增加补丁版本号。 diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 0000000..ab848d1 --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "fixed": [], + "linked": [], + "access": "restricted", + "baseBranch": "main", + "updateInternalDependencies": "patch", + "ignore": [] +} diff --git a/.changeset/tame-phones-dress.md b/.changeset/tame-phones-dress.md new file mode 100644 index 0000000..ee40011 --- /dev/null +++ b/.changeset/tame-phones-dress.md @@ -0,0 +1,5 @@ +--- +"@tavi/i18n": patch +--- + +publishi test diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d5948aa --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +**/node_modules +**/dist +**/.DS_Store +**/pg_data +**/orthanc_db \ No newline at end of file diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..b8ba0ab --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +@tavi:registry=https://npm.saint-medical.com/ +//npm.saint-medical.com/:_authToken=h/wqiL/6HeZCKtXpd72jTg== \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..ef13643 --- /dev/null +++ b/README.md @@ -0,0 +1,81 @@ +# 基础服务 + + +## NATS + +```bash +docker run -d --name nats -p 4222:4222 -p 6222:6222 -p 8222:8222 nats -m 5000 +``` + +# mysql + +```bash +docker run --name mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7 +``` + +## nacos + +`http://:8848/nacos` 来访问Nacos控制台。默认的用户名和密码都是 `nacos` + +```bash +# 单节点模式 +docker run -d -p 8848:8848 -e MODE=standalone nacos/nacos-server --name nacos +``` + +## redis + +``` +docker run --name redis -d -p 6379:6379 -e TZ=Asia/Shanghai redis:alpine --requirepass redis +``` + +## 普罗米修斯 + +``` +docker run -p 9090:9090 -v /path/to/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus +``` + + +## nestjs 相关 + + +providers 是一个数组,用于列出此模块中提供的服务。这些服务可以被该模块中的其他部分(例如控制器和其他服务)通过依赖注入(Dependency Injection)进行使用。一旦你将一个类列为模块的provider,NestJS就会负责在需要时创建和销毁这个类的实例。 + +imports 是一个数组,用于列出此模块依赖的其他模块。通过这种方式,一个模块可以访问另一个模块中的providers。简单来说,如果你想要在一个模块的服务中使用另一个模块的服务,你就需要将那个模块添加到imports数组中。 + +exports 是一个数组,用于列出此模块想要公开的providers,使得其他模块可以访问这些providers。如果你想让一个模块的服务可以被其他模块使用,你就需要将那个服务添加到exports数组中。 + +```ts +import { Module } from '@nestjs/common'; +import { CatsController } from './cats.controller'; +import { CatsService } from './cats.service'; +import { DatabaseModule } from '../database/database.module'; + +@Module({ + imports: [DatabaseModule], // 此模块依赖DatabaseModule + controllers: [CatsController], + providers: [CatsService], // 在此模块中定义CatsService + exports: [CatsService], // 允许其他模块访问CatsService +}) +export class CatsModule {} +``` + +# ohifv3 + +```bash +# docker run -d -p 3000:80/tcp --name LatestReleasedOHIF ohif/app:latest +docker run -d -p 3000:80/tcp -v /Users/mozzie/Desktop/tavi-universe/ohifv3/app-config.js:/usr/share/nginx/html/app-config.js -v /Users/mozzie/Desktop/tavi-universe/ohifv3/conf.d:/etc/nginx/conf.d --name ohifv3 ohif/app:latest +``` + + + +## Minio + +```bash +docker run -d --restart=always \ + -p 19000:9000 -p 19001:9001 \ + --name minio1 \ + -v /Users/mozzie/minio:/data \ + -e "MINIO_ROOT_USER=minio" \ + -e "MINIO_ROOT_PASSWORD=12345678" \ + minio/minio server /data --console-address ":9001" +``` \ No newline at end of file diff --git a/apps/aorta/CHANGELOG.md b/apps/aorta/CHANGELOG.md new file mode 100644 index 0000000..2f21f2c --- /dev/null +++ b/apps/aorta/CHANGELOG.md @@ -0,0 +1,25 @@ +# @tavi/aorta + +## 1.0.2 + +### Patch Changes + +- test3 +- Updated dependencies + - @tavi/i18n@1.5.0 + +## 1.0.1 + +### Patch Changes + +- update test +- Updated dependencies + - @tavi/i18n@1.4.0 + +## null + +### Patch Changes + +- Updated dependencies +- Updated dependencies + - @tavi/i18n@1.1.0 diff --git a/apps/aorta/babel.config.js b/apps/aorta/babel.config.js new file mode 100644 index 0000000..9170ac3 --- /dev/null +++ b/apps/aorta/babel.config.js @@ -0,0 +1,29 @@ +const isDEV = process.env.NODE_ENV === "development"; // 是否是开发模式 + +module.exports = { + // 执行顺序由右往左,所以先处理ts,再处理jsx,最后再试一下babel转换为低版本语法 + presets: [ + [ + "@babel/preset-env", + { + // 设置兼容目标浏览器版本,这里可以不写,babel-loader会自动寻找上面配置好的文件.browserslistrc + // "targets": { + // "chrome": 35, + // "ie": 9 + // }, + targets: { browsers: ["> 1%", "last 2 versions", "not ie <= 8"] }, + useBuiltIns: "usage", // 根据配置的浏览器兼容,以及代码中使用到的api进行引入polyfill按需添加 + corejs: 3, // 配置使用core-js使用的版本 + loose: true, + }, + ], + // 如果您使用的是 Babel 和 React 17,您可能需要将 "runtime": "automatic" 添加到配置中。 + // 否则可能会出现错误:Uncaught ReferenceError: React is not defined + ["@babel/preset-react", { runtime: "automatic" }], + "@babel/preset-typescript", + ], + plugins: [ + ["@babel/plugin-proposal-decorators", { legacy: true }], //装饰器语法 + isDEV && require.resolve("react-refresh/babel"), // 如果是开发模式,就启动react热更新插件 + ].filter(Boolean), // 过滤空值 +}; \ No newline at end of file diff --git a/apps/aorta/core/application/readme.md b/apps/aorta/core/application/readme.md new file mode 100644 index 0000000..e8cd9e7 --- /dev/null +++ b/apps/aorta/core/application/readme.md @@ -0,0 +1,11 @@ +应用层(application):这一层负责协调领域层和基础设施层,实现具体的用例逻辑。 + +协调领域服务:如果有一种业务用例需要多个领域对象或领域服务协作完成,UserApplicationService就可以负责调度它们,然后完成业务逻辑。比如,在创建一个新用户的时候,可能需要检查用户名是否已经存在,然后再创建新的用户实体,这就需要UserApplicationService协调不同的领域服务。 + +事务控制:UserApplicationService也可能负责控制数据库事务。虽然在前端的场景中,事务控制可能并不常见,但在后端服务中这是非常常见的。比如,创建一个新用户可能涉及到在几个数据库表中插入数据,这就需要在一个数据库事务中完成。 + +安全和授权:UserApplicationService可能需要检查当前用户是否有权限执行某项操作。比如,在更新用户信息的时候,可能需要检查当前用户是否有权限更新这个用户的信息。 + +适配领域层与接口层:UserApplicationService也可能负责转换数据格式,以便领域层和接口层之间的数据交换。例如,将领域实体转换为DTO(数据传输对象),或者将来自接口层的请求数据转换为领域服务可以处理的格式。 + +在设计UserApplicationService时,需要注意的是,业务逻辑应该尽量放在领域层处理,应用层更多地是做协调和编排的工作,而不是包含业务逻辑。这样可以保证业务逻辑的集中和一致性,也使得业务逻辑更易于测试和重用。 \ No newline at end of file diff --git a/apps/aorta/core/domain/Base/emitter/index.ts b/apps/aorta/core/domain/Base/emitter/index.ts new file mode 100644 index 0000000..0f43bf5 --- /dev/null +++ b/apps/aorta/core/domain/Base/emitter/index.ts @@ -0,0 +1,3 @@ +import mitt from "mitt"; + +export const emitter = mitt(); \ No newline at end of file diff --git a/apps/aorta/core/domain/Tracker/TrackerRepository.ts b/apps/aorta/core/domain/Tracker/TrackerRepository.ts new file mode 100644 index 0000000..fdf4e98 --- /dev/null +++ b/apps/aorta/core/domain/Tracker/TrackerRepository.ts @@ -0,0 +1,5 @@ +import { Apis } from "@@/infra/api"; + +export class TrackerRepository { + async report(msg: string) {} +} diff --git a/apps/aorta/core/domain/User/UserRepository.ts b/apps/aorta/core/domain/User/UserRepository.ts new file mode 100644 index 0000000..e051b3a --- /dev/null +++ b/apps/aorta/core/domain/User/UserRepository.ts @@ -0,0 +1,19 @@ +import { UserInfo } from "./entities/UserInfo"; +import { Apis } from "@@/infra/api"; +export class UserRepository { + /** + * 登录 + */ + async authLogin(user: UserInfo) { + const res = await Apis.signIn(user); + return res; + } + + async userAuth() { + return (await Apis.userAuth()) as { + data: { tokenValid: boolean }; + msg: string; + code: number; + }; + } +} diff --git a/apps/aorta/core/domain/User/UserService.ts b/apps/aorta/core/domain/User/UserService.ts new file mode 100644 index 0000000..687ea4e --- /dev/null +++ b/apps/aorta/core/domain/User/UserService.ts @@ -0,0 +1,49 @@ +import { makeAutoObservable } from "mobx"; +import { UserLoginForm } from "./entities/UserLoginForm"; +import { FormFields } from "@/modules/Login/LoginForm"; +import { UserRepository } from "./UserRepository"; +import { User } from "./entities/User"; + +export class UserService { + user: User; + loginForm: UserLoginForm; + + constructor(private userRepository: UserRepository) { + this.user = new User(); + this.loginForm = new UserLoginForm(); + makeAutoObservable(this); + } + + /** + * update User领域models中的loginForm对象 + */ + updateLoginForm(values: FormFields) { + this.loginForm = values; + } + + /** + * 登录事件 + */ + async handleLogin(values: FormFields) { + const { username, password } = values; + const { code, msg, data } = await this.userRepository.authLogin({ + username, + password, + }); + return { success: code === "ok", code, msg }; + } + + /** + * 获取用户信息 + */ + async userAuth() { + const { code, data, msg } = await this.userRepository.userAuth(); + if (code === 0 && data?.tokenValid) { + this.user.signIn(); + return { success: true, data }; + } else { + this.user.signOut(); + return { success: false, msg }; + } + } +} diff --git a/apps/aorta/core/domain/User/entities/User.ts b/apps/aorta/core/domain/User/entities/User.ts new file mode 100644 index 0000000..791b343 --- /dev/null +++ b/apps/aorta/core/domain/User/entities/User.ts @@ -0,0 +1,25 @@ +import { makeAutoObservable } from "mobx"; +import { UserInfo } from "./UserInfo"; + +type UserProps = { + userInfo: UserInfo; + isLoggedIn: boolean; +}; + +export class User { + userInfo: UserInfo; + isLoggedIn: boolean; + constructor(p?: UserProps) { + this.userInfo = p?.userInfo ?? {}; + this.isLoggedIn = false; + makeAutoObservable(this); + } + + signIn() { + this.isLoggedIn = true; + } + + signOut() { + this.isLoggedIn = false; + } +} diff --git a/apps/aorta/core/domain/User/entities/UserInfo.ts b/apps/aorta/core/domain/User/entities/UserInfo.ts new file mode 100644 index 0000000..4348d27 --- /dev/null +++ b/apps/aorta/core/domain/User/entities/UserInfo.ts @@ -0,0 +1,30 @@ +import { makeAutoObservable } from "mobx"; + +type UserInfoProps = { + id?: number; + username?: string; + /** + * 是否登录 + */ + isLoggedIn?: boolean; + phoneNumber?: string | number; + /** + * 创建时间 + */ + createTime?: number | string; + /** + * 部门 + */ + department?: string; + /** + * 联系人 + */ + contactPerson?: string; +}; + +export class UserInfo { + constructor(userInfo: UserInfoProps) { + Object.assign(this, userInfo); + makeAutoObservable(this); + } +} diff --git a/apps/aorta/core/domain/User/entities/UserLoginForm.ts b/apps/aorta/core/domain/User/entities/UserLoginForm.ts new file mode 100644 index 0000000..cea3d27 --- /dev/null +++ b/apps/aorta/core/domain/User/entities/UserLoginForm.ts @@ -0,0 +1,19 @@ +import { makeAutoObservable } from "mobx"; + +export type UserLoginFormType = { + username?: string; + password?: string; + phoneNumber?: string | number; + verifyCode?: string | number; +}; + +export class UserLoginForm { + username?: string = ""; + password?: string = ""; + phoneNumber?: string | number = ""; + verifyCode?: string | number = ""; + + constructor() { + makeAutoObservable(this); + } +} diff --git a/apps/aorta/core/domain/User/events/UserLoggedIn.ts b/apps/aorta/core/domain/User/events/UserLoggedIn.ts new file mode 100644 index 0000000..6374d90 --- /dev/null +++ b/apps/aorta/core/domain/User/events/UserLoggedIn.ts @@ -0,0 +1,16 @@ +import { makeAutoObservable } from "mobx"; + +type UserLoggedInProps = { + userId: number; + timestamp?: number; +}; + +export class UserLoggedIn { + userId: number; + timestamp: number; + + constructor({ userId, timestamp = Date.now() }: UserLoggedInProps) { + this.userId = userId; + this.timestamp = timestamp; + } +} diff --git a/apps/aorta/core/domain/readme.md b/apps/aorta/core/domain/readme.md new file mode 100644 index 0000000..469c81a --- /dev/null +++ b/apps/aorta/core/domain/readme.md @@ -0,0 +1,132 @@ +领域层(domain):这一层包含了业务领域的所有规则和逻辑。这里会定义 + - 实体(Entity): + - 领域服务(Domain Service + - 领域事件 (Event) : 领域事件是领域模型中发生的重要的业务事件,例如用户登录、订单提交等。它们通常表示了领域模型的状态变化,它通常表示了领域模型的状态变化,但它们并`不知道如何处理这些变化`。它们的职责是通知其他部分系统,某个重要的事情发生了。 + - 仓库接口(Repository Interface) + +更轻量级的领域设计,可以考虑以下策略: + - 实体(Entity) + - 领域服务(Domain Service) + - 领域事件 (Event) + + +## 领域事件(Domain Events)、领域模型(Domain Model)、UI 三者的关系 + +1. UI层接收用户输入:用户通过UI层进行操作,例如点击按钮或填写表单。 +2. 触发领域事件:根据用户的操作,UI层会触发相应的领域事件。例如,当用户填写表单并点击"登录"按钮时,UI层会触发一个"UserLoggedIn"事件。 +3. 更新领域模型:领域事件会导致领域模型的状态改变。例如,"UserLoggedIn"事件可能会使User模型的"isLoggedIn"状态变为true。 +4. UI层反映领域模型的状态:当领域模型的状态改变时,UI层会相应地更新,以反映新的状态。例如,如果User模型的"isLoggedIn"状态变为true,那么UI层可能会显示一个"欢迎回来"的消息,并隐藏"登录"按钮。 + +这种方式的好处是,它使得UI层和领域逻辑解耦,使得代码更易于理解和维护。当业务逻辑变化时,你只需要修改领域模型和领域事件,而不需要修改UI层。同样,当UI需求变化时,你只需要修改UI层,而不需要修改领域模型和领域事件。 + +## 基本的Demo + +```ts +class User { + id: string; + name: string; + isLoggedIn: boolean = false; + + login() { + this.isLoggedIn = true; + } +} + +``` + +接下来,我们定义用户登录的领域事件。这个事件将表示用户登录的动作: + +```ts +class UserLoggedIn { + constructor(public userId: string) {} +} +``` + +然后,我们需要定义一个领域服务,这个服务将负责处理用户登录的业务逻辑: + +```ts +class AuthenticationService { + constructor(private userRepository: UserRepository) {} + + async login(username: string, password: string) { + // 通常,你需要从后端服务验证用户名和密码,这里为了简单起见,我们假设验证总是成功 + const user = await this.userRepository.findByName(username); + user.login(); + // 通过发布订阅这种方式通知UI更新 + eventBus.emit('UserLoggedIn',new UserLoggedIn(user.id)); + } +} +``` + +## 某个方法 Should 充血到领域模型 Or 放到领域服务 + +1. 领域规则:如果方法代表了一个业务规则,那么它应该被放在领域模型中。领域模型负责封装业务规则,保证业务的一致性。例如,User模型可能有一个login方法,因为登录是用户的一个核心业务行为。 + +2. 状态变化:如果方法会改变模型的状态,那么它也应该被放在领域模型中。领域模型的状态应该被封装起来,只能通过模型的方法来改变。这样可以保证状态的一致性。 + +3. 复杂业务逻辑:如果方法包含了复杂的业务逻辑,那么它可能应该被放在一个领域服务中。领域服务是一种特殊的模型,它负责处理那些涉及多个模型的复杂业务逻辑。例如,一个订单服务(OrderService)可能有一个placeOrder方法,因为下订单涉及到用户、商品和订单等多个模型。 + + +## mobx与发布订阅 + +针对 f(领域模型状态)->ui组件,这个通常有如下几种做法: + - mobx: makeAutoObserve(this) + mobx-react-lite: + useDomain(Context) + - 领域服务发布领域事件 + 组件内部订阅最新的领域模型 + +ui层使用mobx的`observer()`来订阅反应模型、事件的更新,相比于发布订阅,省去了在组件内部显式的订阅和处理领域事件 + + +## 实例化的两种思量 + +构造函数的参数列表中使用了 `public` 关键字,这样 TypeScript 会自动为每个参数创建一个与之同名的类属性,并把构造函数收到的参数值赋给这些属性。 + +> 缺点是不能直接接受一个对象作为参数 + +```ts +export class UserInfo { + constructor( + public id?: number, + public username?: string, + public isLoggedIn?: boolean, + public phoneNumber?: string | number, + public createTime?: number | string, + public department?: string, + public contactPerson?: string + ) {} +} +``` +如果userInfo对象缺少一些UserInfo类有的属性,这些属性将保持其初始值 + +```ts +type UserInfoInterface = { + id?: number; + username?: string; + isLoggedIn?: boolean; + phoneNumber?: string | number; + createTime?: number | string; + department?: string; + contactPerson?: string; +}; + +export class UserInfo { + id?: number; + username?: string; + isLoggedIn?: boolean; + phoneNumber?: string | number; + createTime?: number | string; + department?: string; + contactPerson?: string; + + constructor(userInfo: UserInfoInterface) { + makeAutoObservable(this); + + // 使用 Object.assign 来分配属性 + Object.assign(this, userInfo); + } +} +``` + +## makeAutoObservable(this) + +1. 需要构造属性声明的最后面 +2. 实例化之后的属性注入,无法被追踪到 \ No newline at end of file diff --git a/apps/aorta/core/infra/api/Request.ts b/apps/aorta/core/infra/api/Request.ts new file mode 100644 index 0000000..5b83404 --- /dev/null +++ b/apps/aorta/core/infra/api/Request.ts @@ -0,0 +1,143 @@ +import { message } from "antd"; +import { getFingerprint, SymmetricCrypto } from "@tavi/util"; +import axios, { + AxiosError, + AxiosInstance, + AxiosRequestConfig, + AxiosResponse, + CancelTokenSource, + InternalAxiosRequestConfig, +} from "axios"; + +interface RequestConfig extends InternalAxiosRequestConfig { + onRequestSent?: RequestCallback; +} + +type RequestCallback = (token: string) => void; + +type ResponseException = { + msg: string; + path: string; + statusCode: number; + timestamp: string; +}; + +class AxiosRequestInstance { + private instance: AxiosInstance; + private cancelTokenMap: Map; + + constructor() { + this.instance = axios.create(); + this.cancelTokenMap = new Map(); + + // 请求拦截 + this.instance.interceptors.request.use(async (config: RequestConfig) => { + const token = this.generateToken(); + const source = axios.CancelToken.source(); + this.cancelTokenMap.set(token, source); + + // 生成 traceId 并加入请求头 + const traceId = this.generateTraceId(); + config.headers["x-trace-id"] = traceId; + config.headers["x-request-token"] = token; // 将token加入请求头 + config.cancelToken = source.token; + // 浏览器指纹 + config.headers["x-finger"] = await getFingerprint(); + // 浏览器指纹2 + config.headers["x-finger2"] = new SymmetricCrypto().encrypt({ + language: navigator.language, + userAgent: navigator.userAgent, + platform: navigator.platform, + screenResolution: `${window.screen.width} x ${window.screen.height}`, + }); + + if (config.onRequestSent) config.onRequestSent(token); + return config; + }); + + // 响应拦截 + this.instance.interceptors.response.use( + (response: AxiosResponse) => { + const token = response.headers["x-request-token"] as string; + this.cancelTokenMap.delete(token); // 完成后删除此token + return response; + }, + (error: AxiosError) => { + if (error.response && error.response.status === 403) { + const { msg } = error.response.data as ResponseException; + message.error(msg); + } + return Promise.reject(error); + } + ); + } + + // 生成token + private generateToken(): string { + return Math.random().toString(36).substring(2); + } + + // 生成traceId + private generateTraceId(): string { + // 使用你自己的 traceId 生成策略,这里是一个简单的示例 + return Math.random().toString(36).substring(2); + } + + // 取消请求 + public cancelRequest(token: string): void { + const source = this.cancelTokenMap.get(token); + if (source) { + source.cancel("Request canceled, token:" + token); + this.cancelTokenMap.delete(token); + } + } + + // 封装get、post等请求 + public async get( + url: string, + config?: AxiosRequestConfig & { onRequestSent?: RequestCallback } + ): Promise { + const response = await this.instance.get(url, config); + return response.data; + } + + public async post( + url: string, + data?: any, + config?: RequestConfig & { onRequestSent?: RequestCallback } + ): Promise { + const response = await this.instance.post(url, data, config); + return response.data; + } + + public async put( + url: string, + data?: any, + config?: RequestConfig & { onRequestSent?: RequestCallback } + ): Promise { + const response = await this.instance.put(url, data, config); + return response.data; + } + + public async delete( + url: string, + config?: RequestConfig & { onRequestSent?: RequestCallback } + ): Promise { + const response = await this.instance.delete(url, config); + return response.data; + } +} + +export const Request = new AxiosRequestInstance(); + +// 使用方法: +// 1. 发起请求并获取token +// let token: string; +// requestInstance.get("https://api.example.com/data", { +// onRequestSent: (requestToken) => { +// token = requestToken; +// }, +// }); + +// 2. 在需要取消请求的时候取消请求 +// requestInstance.cancelRequest(token); diff --git a/apps/aorta/core/infra/api/index.ts b/apps/aorta/core/infra/api/index.ts new file mode 100644 index 0000000..7d2cd46 --- /dev/null +++ b/apps/aorta/core/infra/api/index.ts @@ -0,0 +1,21 @@ +import { Request } from "./Request"; + +const PREFIX = "/api/aorta"; +const PREFIX_CERT = "/cert"; + +type ResponseType = Promise<{ + code?: number | string; + data?: unknown; + msg?: string; +}>; + +export const Apis = { + /** + * 用户登录 + */ + signIn: (p: any): ResponseType => Request.post(PREFIX + "/auth/signIn", p), + /** + * 用户认证 + */ + userAuth: (): ResponseType => Request.get(PREFIX_CERT + "/auth/user"), +}; diff --git a/apps/aorta/core/infra/readme.md b/apps/aorta/core/infra/readme.md new file mode 100644 index 0000000..0ea4e50 --- /dev/null +++ b/apps/aorta/core/infra/readme.md @@ -0,0 +1 @@ +基础设施层(infrastructure):这一层包含了所有的基础设施服务,例如数据持久化、网络请求等。 \ No newline at end of file diff --git a/apps/aorta/env/.env.development b/apps/aorta/env/.env.development new file mode 100644 index 0000000..1a4e4be --- /dev/null +++ b/apps/aorta/env/.env.development @@ -0,0 +1 @@ +REACT_APP_API_URL=https://api-dev.com diff --git a/apps/aorta/env/.env.production b/apps/aorta/env/.env.production new file mode 100644 index 0000000..f2e1f74 --- /dev/null +++ b/apps/aorta/env/.env.production @@ -0,0 +1 @@ +REACT_APP_API_URL=https://api-prod.com diff --git a/apps/aorta/env/.env.test b/apps/aorta/env/.env.test new file mode 100644 index 0000000..e69de29 diff --git a/apps/aorta/package.json b/apps/aorta/package.json new file mode 100644 index 0000000..6884092 --- /dev/null +++ b/apps/aorta/package.json @@ -0,0 +1,67 @@ +{ + "name": "@tavi/aorta", + "version": "1.0.2", + "description": "主动脉项目", + "scripts": { + "dev": "cross-env NODE_ENV=development BASE_ENV=development webpack serve -c scripts/webpack.dev.ts", + "build": "cross-env NODE_ENV=production BASE_ENV=production webpack -c scripts/webpack.prod.ts", + "build:analyze": "cross-env NODE_ENV=production BASE_ENV=production webpack -c scripts/webpack.analyze.ts" + }, + "dependencies": { + "react": "18.2.0", + "react-dom": "18.2.0", + "react-router": "6.14.1", + "react-router-dom": "6.14.1", + "axios": "1.3.6", + "antd": "5.6.4", + "mobx": "6.9.0", + "mobx-react-lite": "3.4.3", + "react-icons": "4.10.1", + "mitt": "3.0.1", + "@tavi/i18n": "^1.5.0", + "@tavi/util": "1.0.0", + "js-cookie": "3.0.5" + }, + "devDependencies": { + "@babel/core": "^7.21.8", + "@babel/plugin-proposal-decorators": "^7.21.0", + "@babel/preset-env": "^7.21.5", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.5", + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.10", + "@types/node": "18.16.3", + "@types/react": "^18.0.28", + "@types/react-dom": "^18.0.11", + "@types/react-router": "5.1.20", + "@types/react-router-dom": "5.3.3", + "babel-loader": "^9.1.2", + "compression-webpack-plugin": "^10.0.0", + "copy-webpack-plugin": "^11.0.0", + "core-js": "^3.30.1", + "cross-env": "^6.0.0", + "css-loader": "^6.7.3", + "css-minimizer-webpack-plugin": "^5.0.0", + "dotenv": "^16.0.3", + "friendly-errors-webpack-plugin": "^1.7.0", + "glob-all": "^3.3.1", + "html-webpack-plugin": "^5.5.1", + "less": "^4.1.3", + "less-loader": "^11.1.0", + "mini-css-extract-plugin": "^2.7.5", + "prettier": "^2.8.8", + "purgecss-webpack-plugin": "^5.0.0", + "react-refresh": "^0.14.0", + "speed-measure-webpack-plugin": "^1.5.0", + "style-loader": "^3.3.2", + "terser-webpack-plugin": "^5.3.7", + "ts-node": "^10.9.1", + "typescript": "^5.0.4", + "webpack": "5.75.0", + "webpack-bundle-analyzer": "^4.8.0", + "webpack-cli": "^5.0.2", + "webpack-dev-server": "^4.13.3", + "webpack-merge": "^5.8.0", + "webpackbar": "^5.0.2", + "@types/js-cookie": "3.0.3" + } +} \ No newline at end of file diff --git a/apps/aorta/public/favicon.svg b/apps/aorta/public/favicon.svg new file mode 100644 index 0000000..9e904f0 --- /dev/null +++ b/apps/aorta/public/favicon.svg @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/apps/aorta/public/img/login_1.webp b/apps/aorta/public/img/login_1.webp new file mode 100644 index 0000000000000000000000000000000000000000..03c1af6399efcd0bbd712cc6dda721ac10327a9a GIT binary patch literal 56810 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 literal 0 HcmV?d00001 diff --git a/apps/aorta/public/img/login_mask.webp b/apps/aorta/public/img/login_mask.webp new file mode 100644 index 0000000000000000000000000000000000000000..02e2777f4e5566a4ae0d331ef2674daaefa5a60e GIT binary patch literal 25330 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 literal 0 HcmV?d00001 diff --git a/apps/aorta/public/index.html b/apps/aorta/public/index.html new file mode 100644 index 0000000..a862a9a --- /dev/null +++ b/apps/aorta/public/index.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + + +
+ + + \ No newline at end of file diff --git a/apps/aorta/public/locales/en-US/translation.json b/apps/aorta/public/locales/en-US/translation.json new file mode 100644 index 0000000..04205d8 --- /dev/null +++ b/apps/aorta/public/locales/en-US/translation.json @@ -0,0 +1,11 @@ +{ + "LOGIN": { + "FORM_ITEM": { + "LABEL_1": "USERNAME", + "LABEL_2": "PASSWORD", + "LABEL_3": "PHONE NUMBER", + "LABEL_4": "VERIFY CODE", + "BUTTON_1": "LOGIN" + } + } +} \ No newline at end of file diff --git a/apps/aorta/public/locales/en/translation.json b/apps/aorta/public/locales/en/translation.json new file mode 100644 index 0000000..c0c4ed5 --- /dev/null +++ b/apps/aorta/public/locales/en/translation.json @@ -0,0 +1,16 @@ +{ + "LOGIN": { + "FORM_ITEM": { + "LABEL_1": "USERNAME", + "LABEL_2": "PASSWORD", + "LABEL_3": "PHONE NUMBER", + "LABEL_4": "VERIFY CODE", + "LABEL_5": "Please enter your username", + "LABEL_6": "Please enter the password", + "LABEL_7": "Please enter your mobile phone number", + "LABEL_8": "Please enter the verification code", + "BUTTON_1": "LOGIN" + }, + "FORGET_PASS": "Forgot the password" + } +} \ No newline at end of file diff --git a/apps/aorta/public/locales/zh-CN/translation.json b/apps/aorta/public/locales/zh-CN/translation.json new file mode 100644 index 0000000..ddfdb48 --- /dev/null +++ b/apps/aorta/public/locales/zh-CN/translation.json @@ -0,0 +1,16 @@ +{ + "LOGIN": { + "FORM_ITEM": { + "LABEL_1": "用户名", + "LABEL_2": "密码", + "LABEL_3": "手机号", + "LABEL_4": "验证码", + "LABEL_5": "请输入您的用户名", + "LABEL_6": "请输入密码", + "LABEL_7": "请输入您的手机号码", + "LABEL_8": "请输入验证码", + "BUTTON_1": "登录" + }, + "FORGET_PASS": "忘记密码" + } +} \ No newline at end of file diff --git a/apps/aorta/public/locales/zh/translation.json b/apps/aorta/public/locales/zh/translation.json new file mode 100644 index 0000000..ddfdb48 --- /dev/null +++ b/apps/aorta/public/locales/zh/translation.json @@ -0,0 +1,16 @@ +{ + "LOGIN": { + "FORM_ITEM": { + "LABEL_1": "用户名", + "LABEL_2": "密码", + "LABEL_3": "手机号", + "LABEL_4": "验证码", + "LABEL_5": "请输入您的用户名", + "LABEL_6": "请输入密码", + "LABEL_7": "请输入您的手机号码", + "LABEL_8": "请输入验证码", + "BUTTON_1": "登录" + }, + "FORGET_PASS": "忘记密码" + } +} \ No newline at end of file diff --git a/apps/aorta/scripts/dev.proxy.ts b/apps/aorta/scripts/dev.proxy.ts new file mode 100644 index 0000000..d41b02b --- /dev/null +++ b/apps/aorta/scripts/dev.proxy.ts @@ -0,0 +1,25 @@ +import WebpackDevServer from "webpack-dev-server"; + +type TProxyMap = + | WebpackDevServer.ProxyConfigMap + | WebpackDevServer.ProxyConfigArrayItem + | WebpackDevServer.ProxyConfigArray + | undefined; + +export const proxyMap: TProxyMap = { + "/dicom-web": { + target: "http://localhost:8042/dicom-web/", + changeOrigin: true, + pathRewrite: { "^/dicom-web": "" }, + }, + "/cert": { + target: "http://localhost:12144/", + changeOrigin: true, + pathRewrite: { "^/cert": "/cert" }, + }, + "/api": { + target: "http://localhost:9008/", + changeOrigin: true, + pathRewrite: { "^/api": "" }, + }, +}; diff --git a/apps/aorta/scripts/loaders/babel.loader.ts b/apps/aorta/scripts/loaders/babel.loader.ts new file mode 100644 index 0000000..3ca3d95 --- /dev/null +++ b/apps/aorta/scripts/loaders/babel.loader.ts @@ -0,0 +1,4 @@ +export default { + test: /.(ts|tsx)$/, // 匹配.ts, tsx文件 + use: "babel-loader" +} \ No newline at end of file diff --git a/apps/aorta/scripts/loaders/fonts.loader.ts b/apps/aorta/scripts/loaders/fonts.loader.ts new file mode 100644 index 0000000..3308af7 --- /dev/null +++ b/apps/aorta/scripts/loaders/fonts.loader.ts @@ -0,0 +1,12 @@ +export default { + test: /.(woff2?|eot|ttf|otf)$/, // 匹配字体图标文件 + type: "asset", // type选择asset + parser: { + dataUrlCondition: { + maxSize: 10 * 1024, // 小于10kb转base64 + } + }, + generator: { + filename: 'static/fonts/[name].[contenthash:8][ext]', // 文件输出目录和命名 + }, +} \ No newline at end of file diff --git a/apps/aorta/scripts/loaders/img.loader.ts b/apps/aorta/scripts/loaders/img.loader.ts new file mode 100644 index 0000000..03b5ffe --- /dev/null +++ b/apps/aorta/scripts/loaders/img.loader.ts @@ -0,0 +1,12 @@ +export default { + test: /\.(png|jpe?g|gif|svg)$/i, // 匹配图片文件 + type: "asset", // type选择asset + parser: { + dataUrlCondition: { + maxSize: 20 * 1024, // 小于10kb转base64 + } + }, + generator: { + filename: 'static/images/[name].[contenthash:8][ext]', // 文件输出目录和命名 + }, +} \ No newline at end of file diff --git a/apps/aorta/scripts/loaders/json.loader.ts b/apps/aorta/scripts/loaders/json.loader.ts new file mode 100644 index 0000000..333f2c8 --- /dev/null +++ b/apps/aorta/scripts/loaders/json.loader.ts @@ -0,0 +1,9 @@ +export default { + // 匹配json文件 + test: /\.json$/, + type: "asset/source", // 将json文件视为文件类型 + generator: { + // 这里专门针对json文件的处理 + filename: 'static/fonts/[name].[contenthash:8][ext]' + } +} \ No newline at end of file diff --git a/apps/aorta/scripts/loaders/style.loader.ts b/apps/aorta/scripts/loaders/style.loader.ts new file mode 100644 index 0000000..8646335 --- /dev/null +++ b/apps/aorta/scripts/loaders/style.loader.ts @@ -0,0 +1,30 @@ +const MiniCssExtractPlugin = require('mini-css-extract-plugin') +const isDev = process.env.NODE_ENV === 'development' // 是否是开发模式 + +const styleLoadersArray = [ + isDev ? 'style-loader' : MiniCssExtractPlugin.loader, // 开发环境使用style-looader,打包模式抽离css + { + loader: 'css-loader' + } +] + +export const cssLoader = { + test: /.css$/, //匹配 css 文件 + use: styleLoadersArray +} + +export const lessLoader = { + test: /\.less$/, + use: [ + ...styleLoadersArray, + { + loader: 'less-loader', + options: { + lessOptions: { + // 如果要在less中写类型js的语法,需要加这一个配置 + javascriptEnabled: true + } + } + } + ] +} diff --git a/apps/aorta/scripts/util/openBrowser.js b/apps/aorta/scripts/util/openBrowser.js new file mode 100644 index 0000000..6367fd3 --- /dev/null +++ b/apps/aorta/scripts/util/openBrowser.js @@ -0,0 +1,155 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +var chalk = require('chalk'); +var execSync = require('child_process').execSync; +var spawn = require('cross-spawn'); +var open = require('open'); + +// https://github.com/sindresorhus/open#app +var OSX_CHROME = 'google chrome'; + +const Actions = Object.freeze({ + NONE: 0, + BROWSER: 1, + SCRIPT: 2, +}); + +function getBrowserEnv() { + // Attempt to honor this environment variable. + // It is specific to the operating system. + // See https://github.com/sindresorhus/open#app for documentation. + const value = process.env.BROWSER; + const args = process.env.BROWSER_ARGS + ? process.env.BROWSER_ARGS.split(' ') + : []; + let action; + if (!value) { + // Default. + action = Actions.BROWSER; + } else if (value.toLowerCase().endsWith('.js')) { + action = Actions.SCRIPT; + } else if (value.toLowerCase() === 'none') { + action = Actions.NONE; + } else { + action = Actions.BROWSER; + } + return { action, value, args }; +} + +function executeNodeScript(scriptPath, url) { + const extraArgs = process.argv.slice(2); + const child = spawn(process.execPath, [scriptPath, ...extraArgs, url], { + stdio: 'inherit', + }); + child.on('close', code => { + if (code !== 0) { + console.log(); + console.log( + chalk.red( + 'The script specified as BROWSER environment variable failed.' + ) + ); + console.log(chalk.cyan(scriptPath) + ' exited with code ' + code + '.'); + console.log(); + return; + } + }); + return true; +} + +function startBrowserProcess(browser, url, args) { + // If we're on OS X, the user hasn't specifically + // requested a different browser, we can try opening + // Chrome with AppleScript. This lets us reuse an + // existing tab when possible instead of creating a new one. + const shouldTryOpenChromiumWithAppleScript = + process.platform === 'darwin' && + (typeof browser !== 'string' || browser === OSX_CHROME); + + if (shouldTryOpenChromiumWithAppleScript) { + // Will use the first open browser found from list + const supportedChromiumBrowsers = [ + 'Google Chrome Canary', + 'Google Chrome Dev', + 'Google Chrome Beta', + 'Google Chrome', + 'Microsoft Edge', + 'Brave Browser', + 'Vivaldi', + 'Chromium', + ]; + + for (let chromiumBrowser of supportedChromiumBrowsers) { + try { + // Try our best to reuse existing tab + // on OSX Chromium-based browser with AppleScript + execSync('ps cax | grep "' + chromiumBrowser + '"'); + execSync( + 'osascript openChrome.applescript "' + + encodeURI(url) + + '" "' + + chromiumBrowser + + '"', + { + cwd: __dirname, + stdio: 'ignore', + } + ); + return true; + } catch (err) { + // Ignore errors. + } + } + } + + // Another special case: on OS X, check if BROWSER has been set to "open". + // In this case, instead of passing `open` to `opn` (which won't work), + // just ignore it (thus ensuring the intended behavior, i.e. opening the system browser): + // https://github.com/facebook/create-react-app/pull/1690#issuecomment-283518768 + if (process.platform === 'darwin' && browser === 'open') { + browser = undefined; + } + + // If there are arguments, they must be passed as array with the browser + if (typeof browser === 'string' && args.length > 0) { + browser = [browser].concat(args); + } + + // Fallback to open + // (It will always open new tab) + try { + var options = { app: browser, wait: false, url: true }; + open(url, options).catch(() => {}); // Prevent `unhandledRejection` error. + return true; + } catch (err) { + return false; + } +} + +/** + * Reads the BROWSER environment variable and decides what to do with it. Returns + * true if it opened a browser or ran a node.js script, otherwise false. + */ +function openBrowser(url) { + const { action, value, args } = getBrowserEnv(); + switch (action) { + case Actions.NONE: + // Special case: BROWSER="none" will prevent opening completely. + return false; + case Actions.SCRIPT: + return executeNodeScript(value, url); + case Actions.BROWSER: + return startBrowserProcess(value, url, args); + default: + throw new Error('Not implemented.'); + } +} + +module.exports = openBrowser; \ No newline at end of file diff --git a/apps/aorta/scripts/util/openChrome.applescript b/apps/aorta/scripts/util/openChrome.applescript new file mode 100644 index 0000000..e6c2848 --- /dev/null +++ b/apps/aorta/scripts/util/openChrome.applescript @@ -0,0 +1,94 @@ +(* +Copyright (c) 2015-present, Facebook, Inc. + +This source code is licensed under the MIT license found in the +LICENSE file in the root directory of this source tree. +*) + +property targetTab: null +property targetTabIndex: -1 +property targetWindow: null +property theProgram: "Google Chrome" + +on run argv + set theURL to item 1 of argv + + -- Allow requested program to be optional, + -- default to Google Chrome + if (count of argv) > 1 then + set theProgram to item 2 of argv + end if + + using terms from application "Google Chrome" + tell application theProgram + + if (count every window) = 0 then + make new window + end if + + -- 1: Looking for tab running debugger + -- then, Reload debugging tab if found + -- then return + set found to my lookupTabWithUrl(theURL) + if found then + set targetWindow's active tab index to targetTabIndex + tell targetTab to reload + tell targetWindow to activate + set index of targetWindow to 1 + return + end if + + -- 2: Looking for Empty tab + -- In case debugging tab was not found + -- We try to find an empty tab instead + set found to my lookupTabWithUrl("chrome://newtab/") + if found then + set targetWindow's active tab index to targetTabIndex + set URL of targetTab to theURL + tell targetWindow to activate + return + end if + + -- 3: Create new tab + -- both debugging and empty tab were not found + -- make a new tab with url + tell window 1 + activate + make new tab with properties {URL:theURL} + end tell + end tell + end using terms from +end run + +-- Function: +-- Lookup tab with given url +-- if found, store tab, index, and window in properties +-- (properties were declared on top of file) +on lookupTabWithUrl(lookupUrl) + using terms from application "Google Chrome" + tell application theProgram + -- Find a tab with the given url + set found to false + set theTabIndex to -1 + repeat with theWindow in every window + set theTabIndex to 0 + repeat with theTab in every tab of theWindow + set theTabIndex to theTabIndex + 1 + if (theTab's URL as string) contains lookupUrl then + -- assign tab, tab index, and window to properties + set targetTab to theTab + set targetTabIndex to theTabIndex + set targetWindow to theWindow + set found to true + exit repeat + end if + end repeat + + if found then + exit repeat + end if + end repeat + end tell + end using terms from + return found +end lookupTabWithUrl \ No newline at end of file diff --git a/apps/aorta/scripts/webpack.analyze.ts b/apps/aorta/scripts/webpack.analyze.ts new file mode 100644 index 0000000..729bb78 --- /dev/null +++ b/apps/aorta/scripts/webpack.analyze.ts @@ -0,0 +1,18 @@ +import { Configuration } from "webpack"; +import { merge } from "webpack-merge"; +import prodConfig from "./webpack.prod"; + +const SpeedMeasurePlugin = require("speed-measure-webpack-plugin"); +const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); + +// 引入webpack打包速度分析插件 +const smp = new SpeedMeasurePlugin(); + +// 使用smp.wrap方法,把生产环境配置传进去,由于后面可能会加分析配置,所以先留出合并空位 +const analyConfig: Configuration = smp.wrap(merge(prodConfig, { + plugins: [ + new BundleAnalyzerPlugin() // 配置分析打包结果插件 + ] +})) + +export default analyConfig; \ No newline at end of file diff --git a/apps/aorta/scripts/webpack.common.ts b/apps/aorta/scripts/webpack.common.ts new file mode 100644 index 0000000..3f1e488 --- /dev/null +++ b/apps/aorta/scripts/webpack.common.ts @@ -0,0 +1,74 @@ +import { Configuration, DefinePlugin } from "webpack"; +import HtmlWebpackPlugin from "html-webpack-plugin"; +import path from "path"; +import * as dotenv from "dotenv"; +import fontsLoader from "./loaders/fonts.loader"; +import jsonLoader from "./loaders/json.loader"; +import imgLoader from "./loaders/img.loader"; +import babelLoader from "./loaders/babel.loader"; +import { cssLoader, lessLoader } from "./loaders/style.loader"; + +// 加载配置文件 +const envConfig = dotenv.config({ + path: path.resolve(__dirname, "../env/.env." + process.env.BASE_ENV), +}); + +const baseConfig: Configuration = { + entry: path.join(__dirname, "../src/index.tsx"), // 入口文件 + // 打包出口文件 + output: { + filename: "static/js/[name].[chunkhash:8].js", // 每个输出js的名称 + path: path.join(__dirname, "../dist"), // 打包结果输出路径 + clean: true, // webpack4需要配置clean-webpack-plugin来删除dist文件,webpack5内置了 + publicPath: "/", // 打包后文件的公共前缀路径 + }, + // loader 配置 + module: { + rules: [ + babelLoader, + cssLoader, + lessLoader, + jsonLoader, + imgLoader, + fontsLoader, + ], + }, + resolve: { + extensions: [".ts", ".tsx", ".js", ".jsx"], + // 别名需要配置两个地方,这里和 tsconfig.json + alias: { + "@": path.join(__dirname, "../src"), + "@@": path.join(__dirname, "../core"), + }, + // fallback: { + // crypto: require.resolve('crypto-browserify'), + // buffer: require.resolve("buffer/"), + // http: require.resolve("stream-http"), + // }, + }, + // plugins + plugins: [ + new HtmlWebpackPlugin({ + // 复制 'index.html' 文件,并自动引入打包输出的所有资源(js/css) + template: path.join(__dirname, "../public/index.html"), + inject: true, // 自动注入静态资源 + hash: true, + cache: false, + // 压缩html资源 + minify: { + removeAttributeQuotes: true, + collapseWhitespace: true, //去空格 + removeComments: true, // 去注释 + minifyJS: true, // 在脚本元素和事件属性中缩小JavaScript(使用UglifyJS) + minifyCSS: true, // 缩小CSS样式元素和样式属性 + }, + }), + new DefinePlugin({ + "process.env": JSON.stringify(envConfig.parsed), + "process.env.BASE_ENV": JSON.stringify(process.env.BASE_ENV), + "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV), + }), + ], +}; + +export default baseConfig; diff --git a/apps/aorta/scripts/webpack.dev.ts b/apps/aorta/scripts/webpack.dev.ts new file mode 100644 index 0000000..0255227 --- /dev/null +++ b/apps/aorta/scripts/webpack.dev.ts @@ -0,0 +1,66 @@ +import path from "path"; +import { merge } from "webpack-merge"; +import webpack, { Configuration as WebpackConfiguration } from "webpack"; +import WebpackDevServer from "webpack-dev-server"; +import { Configuration as WebpackDevServerConfiguration } from "webpack-dev-server"; +import baseConfig from "./webpack.common"; +import ReactRefreshWebpackPlugin from "@pmmmwh/react-refresh-webpack-plugin"; +const FriendlyErrorsWebpackPlugin = require("friendly-errors-webpack-plugin"); +import { proxyMap } from "./dev.proxy"; + +/** + * 运行命令的时候重启一次打开一个tab 页很烦,所以呢优化一下 + * 参考:create-react-app 的启动方式 + * https://github.com/facebook/create-react-app/blob/main/packages/react-dev-utils/openChrome.applescript + * 记得关闭webpack-dev-server的配置中的自动打开 open: false 或者注释 + */ +const openBrowser = require("./util/openBrowser"); + +interface Configuration extends WebpackConfiguration { + devServer?: WebpackDevServerConfiguration; +} + +const host = "127.0.0.1"; +const port = 9000; + +// 合并公共配置,并添加开发环境配置 +const devConfig: Configuration = merge(baseConfig, { + mode: "development", // 开发模式,打包更加快速,省了代码优化步骤 + /** + * 开发环境推荐:eval-cheap-module-source-map + * 本地开发首次打包慢点没关系,因为 eval 缓存的原因, 热更新会很快 + * 开发中,我们每行代码不会写的太长,只需要定位到行就行,所以加上 cheap + * 我们希望能够找到源代码的错误,而不是打包后的,所以需要加上 module + */ + devtool: "eval-cheap-module-source-map", + stats: "errors-only", + plugins: [ + new ReactRefreshWebpackPlugin(), // 添加热更新插件 + new FriendlyErrorsWebpackPlugin(), + ], +}); + +const devServer = new WebpackDevServer( + { + host, // 地址 + port, // 端口 + open: false, // 是否自动打开,关闭 + setupExitSignals: true, // 允许在 SIGINT 和 SIGTERM 信号时关闭开发服务器和退出进程。 + compress: false, // gzip压缩,开发环境不开启,提升热更新速度 + hot: true, // 开启热更新,后面会讲react模块热替换具体配置 + historyApiFallback: true, // 解决history路由404问题 + static: { + directory: path.join(__dirname, "../public"), // 托管静态资源public文件夹 + }, + headers: { "Access-Control-Allow-Origin": "*" }, + proxy: proxyMap, + }, + webpack(devConfig) +); + +devServer.start().then(() => { + // 启动界面 + openBrowser(`http://${host}:${port}`); +}); + +export default devConfig; diff --git a/apps/aorta/scripts/webpack.prod.ts b/apps/aorta/scripts/webpack.prod.ts new file mode 100644 index 0000000..b350f18 --- /dev/null +++ b/apps/aorta/scripts/webpack.prod.ts @@ -0,0 +1,103 @@ +import { Configuration } from "webpack"; +import { merge } from "webpack-merge"; +import baseConfig from "./webpack.common"; +const MiniCssExtractPlugin = require("mini-css-extract-plugin"); +import CssMinimizerPlugin from "css-minimizer-webpack-plugin"; +import TerserPlugin from "terser-webpack-plugin"; +import CompressionPlugin from "compression-webpack-plugin"; +const globAll = require("glob-all"); +const { PurgeCSSPlugin } = require("purgecss-webpack-plugin"); +import path from "path"; +import CopyWebpackPlugin from "copy-webpack-plugin"; + +const prodConfig: Configuration = merge(baseConfig, { + mode: "production", // 生产模式,会开启tree-shaking和压缩代码,以及其他优化 + optimization: { + minimize: true, + minimizer: [ + new CssMinimizerPlugin(), // 压缩css + // 压缩js + new TerserPlugin({ + parallel: true, // 开启多线程压缩 + terserOptions: { + compress: { + pure_funcs: ["console.log"], // 删除console.log + }, + }, + }), + ], + splitChunks: { + // 分隔代码 + cacheGroups: { + vendors: { + // 提取node_modules代码 + test: /node_modules/, // 只匹配node_modules里面的模块 + name: "vendors", // 提取文件命名为vendors,js后缀和chunkhash会自动加 + minChunks: 1, // 只要使用一次就提取出来 + chunks: "initial", // 只提取初始化就能获取到的模块,不管异步的 + minSize: 0, // 提取代码体积大于0就提取出来 + priority: 1, // 提取优先级为1 + }, + commons: { + // 提取页面公共代码 + name: "commons", // 提取文件命名为commons + minChunks: 2, // 只要使用两次就提取出来 + chunks: "initial", // 只提取初始化就能获取到的模块,不管异步的 + minSize: 0, // 提取代码体积大于0就提取出来 + }, + }, + }, + }, + performance: { + hints: false, + maxAssetSize: 4000000, // 整数类型(以字节为单位) + maxEntrypointSize: 5000000, // 整数类型(以字节为单位) + }, + plugins: [ + // 抽离css + new MiniCssExtractPlugin({ + filename: "static/css/[name].[contenthash:8].css", // 抽离css的输出目录和名称 + }), + // 清理无用css,检测src下所有tsx文件和public下index.html中使用的类名和id和标签名称 + // 只打包这些文件中用到的样式 + new PurgeCSSPlugin({ + paths: globAll.sync( + [ + `${path.join(__dirname, "../src")}/**/*`, + path.join(__dirname, "../public/index.html"), + ], + { + nodir: true, + } + ), + // 用 only 来指定 purgecss-webpack-plugin 的入口 + // https://github.com/FullHuman/purgecss/tree/main/packages/purgecss-webpack-plugin + only: ["dist"], + safelist: { + standard: [/^ant-/], // 过滤以ant-开头的类名,哪怕没用到也不删除 + }, + }), + // 打包时生成gzip文件,减少nginx的gzip实时压缩负载 + new CompressionPlugin({ + test: /\.(js|css)$/, // 只生成css,js压缩文件 + filename: "[path][base].gz", // 文件命名 + algorithm: "gzip", // 压缩格式,默认是gzip + threshold: 10240, // 只有大小大于该值的资源会被处理。默认值是 10k + minRatio: 0.8, // 压缩率,默认值是 0.8 + }), + new CopyWebpackPlugin({ + patterns: [ + { + from: path.join(__dirname, "../public/img"), + to: "./img", + }, + { + from: path.join(__dirname, "../public/favicon.svg"), + to: ".", + }, + ], + }), + ], +}); + +export default prodConfig; diff --git a/apps/aorta/src/App.tsx b/apps/aorta/src/App.tsx new file mode 100644 index 0000000..d722f6c --- /dev/null +++ b/apps/aorta/src/App.tsx @@ -0,0 +1,28 @@ +import { DomainServiceProvider } from "./context/domainService"; +import { defaultLang, theme } from "./constant"; +import { useTracker } from "./hook/useTracker"; +import { RouterElements } from "./router"; +import { ConfigProvider } from "antd"; +import { useI18n } from "@tavi/i18n"; +import "./styles/app.less"; + +/** + * 国际化 + */ +export const { i18n } = useI18n({ + loadPath: "/locales/{{lng}}/{{ns}}.json", + fallbackLng: defaultLang, + debug: false, +}); + +export const App = () => { + useTracker(); + + return ( + + + + + + ); +}; diff --git a/apps/aorta/src/components/LanguageSelect.tsx b/apps/aorta/src/components/LanguageSelect.tsx new file mode 100644 index 0000000..85b358e --- /dev/null +++ b/apps/aorta/src/components/LanguageSelect.tsx @@ -0,0 +1,54 @@ +import { AiOutlineGlobal } from "react-icons/ai"; +import { i18n } from "@/App"; +import { ConfigProvider, Select } from "antd"; +import { useEffect, useState } from "react"; +import { defaultLang } from "@/constant"; + +interface LanguageSelectProps { + children?: JSX.Element; +} + +const langOptions = [ + { value: "zh-CN", label: "中文(Chinese)" }, + { value: "en-US", label: "English" }, +]; + +export const LanguageSelect = (props: LanguageSelectProps) => { + const [language, setLanguage] = useState(); + + useEffect(() => setLanguage(i18n?.language ?? defaultLang), []); + + const onLanguageChange = (v: string) => { + i18n.changeLanguage(v); + setLanguage(v); + }; + + return ( + +
+ + } + placeholder={t("LOGIN.FORM_ITEM.LABEL_5") as string} + onPressEnter={handleLogin} + autoComplete="off" + /> + + + } + placeholder={t("LOGIN.FORM_ITEM.LABEL_6") as string} + onPressEnter={handleLogin} + autoComplete="off" + /> + + + } + placeholder={t("LOGIN.FORM_ITEM.LABEL_7") as string} + onPressEnter={handleLogin} + autoComplete="off" + /> + + + } + placeholder={t("LOGIN.FORM_ITEM.LABEL_8") as string} + onPressEnter={handleLogin} + autoComplete="off" + /> + + + + + + + + + ); +}; diff --git a/apps/aorta/src/modules/Login/index.less b/apps/aorta/src/modules/Login/index.less new file mode 100644 index 0000000..9750483 --- /dev/null +++ b/apps/aorta/src/modules/Login/index.less @@ -0,0 +1,52 @@ +.login-wrapper { + position: relative; + background: #1f2a34; + height: 100vh; + overflow: hidden; + + + .illustration { + position: absolute; + width: 100%; + height: 100%; + background-position: right bottom; + background-repeat: no-repeat; + background-size: 50% 80%; + + >aside { + padding: 5.71rem 4.29rem; + position: absolute; + background: #050407; + top: 0; + bottom: 0; + width: 34.29rem; + + .ant-form-item-label label { + color: #585963; + } + + >header { + display: flex; + align-items: center; + justify-content: space-between; + padding-bottom: 5rem; + + .lang-select-group { + display: flex; + align-items: center; + } + } + + >footer { + .forget-pass { + color: hsl(235, 6%, 37%); + cursor: pointer; + + &:hover { + color: hsl(235, 6%, 57%); + } + } + } + } + } +} \ No newline at end of file diff --git a/apps/aorta/src/modules/Login/index.tsx b/apps/aorta/src/modules/Login/index.tsx new file mode 100644 index 0000000..645463c --- /dev/null +++ b/apps/aorta/src/modules/Login/index.tsx @@ -0,0 +1,71 @@ +import { LanguageSelect } from "@/components/LanguageSelect"; +import { Logo } from "@/components/Logo"; +import { FormFields, LoginForm } from "./LoginForm"; +import "./index.less"; +import { useDomain } from "@/hook/useDomain"; +import { useTranslation } from "@tavi/i18n"; +import { Observer, observer } from "mobx-react-lite"; +import { UserService } from "@@/domain/User/UserService"; +import { useNavigate } from "react-router"; +import { message } from "antd"; + +interface LoginProps { + children?: JSX.Element; +} + +// const TestComponent: React.FC<{ domainService: UserService }> = observer( +// ({ domainService }) => ( +//
+//

name: {domainService.user.isLoggedIn ? "登录" : "未登录"}

+//
+// ) +// ); + +export const Login = (props: LoginProps) => { + const { t } = useTranslation(); + const navigate = useNavigate(); + const [messageApi, contextHolder] = message.useMessage(); + const { userDomainService } = useDomain(); + + /** + * 登录 + */ + const onLogin = async (v: FormFields) => { + const { success, msg } = await userDomainService.handleLogin(v); + if (success) { + messageApi.success(msg); + navigate("/"); + } else { + messageApi.error(msg); + } + }; + + return ( +
+
+ +
+
+ ); +}; diff --git a/apps/aorta/src/modules/PatientList/index.tsx b/apps/aorta/src/modules/PatientList/index.tsx new file mode 100644 index 0000000..9ebf36b --- /dev/null +++ b/apps/aorta/src/modules/PatientList/index.tsx @@ -0,0 +1,7 @@ +interface PatientListProps { + children?: JSX.Element; +} + +export const PatientList = (props: PatientListProps) => { + return
PatientList
; +}; diff --git a/apps/aorta/src/modules/Peripheral/index.tsx b/apps/aorta/src/modules/Peripheral/index.tsx new file mode 100644 index 0000000..1c7ebf7 --- /dev/null +++ b/apps/aorta/src/modules/Peripheral/index.tsx @@ -0,0 +1,7 @@ +interface PeripheralViewerProps { + children?: JSX.Element; +} + +export const PeripheralViewer = (props: PeripheralViewerProps) => { + return
PeripheralViewer
; +}; diff --git a/apps/aorta/src/modules/Report/Full/components/Heading/index.less b/apps/aorta/src/modules/Report/Full/components/Heading/index.less new file mode 100644 index 0000000..e6e12dd --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/components/Heading/index.less @@ -0,0 +1,31 @@ +.heading { + &.l2 { + padding-left: .29rem; + font-size: 1.14rem; + font-weight: bold; + line-height: 1; + color: var(--color-bg-primary); + border-left: .29rem solid var(--color-bg-primary); + margin-bottom: 1.14rem; + + span { + font-size: 0.85rem; + } + } + + &.l1 { + position: relative; + font-size: 1.7rem; + font-weight: bold; + color: var(--color-primary); + + &::before { + position: absolute; + content: ''; + bottom: -.5rem; + width: 3.36rem; + height: 0.21rem; + background: var(--color-primary); + } + } +} \ No newline at end of file diff --git a/apps/aorta/src/modules/Report/Full/components/Heading/index.tsx b/apps/aorta/src/modules/Report/Full/components/Heading/index.tsx new file mode 100644 index 0000000..43650b9 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/components/Heading/index.tsx @@ -0,0 +1,27 @@ +import './index.less' + +interface HeadingProps { + title: string + forRef?: boolean + style?: React.CSSProperties + children?: JSX.Element + level?: 1 | 2 +} + +export const Heading = (props: HeadingProps) => { + const levelMapping = { + 1: ( +
+ {props.title} +
+ ), + 2: ( +
+ {props.title} + {props.forRef && (仅供参考)} +
+ ) + } + + return levelMapping[props.level ?? 2] +} diff --git a/apps/aorta/src/modules/Report/Full/components/ImageItem/index.less b/apps/aorta/src/modules/Report/Full/components/ImageItem/index.less new file mode 100644 index 0000000..c5b4b2f --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/components/ImageItem/index.less @@ -0,0 +1,33 @@ +.image-card { + + p { + margin: 0; + height: 1.71rem; + line-height: 1.71rem; + background: #F5F5F5; + border: 0.07rem solid #8A8A8A; + text-align: center; + margin-bottom: .5rem; + } + + .img { + position: relative; + background-size: cover; + background-position: center center; + min-height: 6rem; + cursor: pointer; + + &.active { + &::after { + position: absolute; + content: ''; + left: 0; + right: 0; + top: 0; + bottom: 0; + border: 2px dashed var(--color-bg-primary); + } + } + } + +} \ No newline at end of file diff --git a/apps/aorta/src/modules/Report/Full/components/ImageItem/index.tsx b/apps/aorta/src/modules/Report/Full/components/ImageItem/index.tsx new file mode 100644 index 0000000..a6bed15 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/components/ImageItem/index.tsx @@ -0,0 +1,84 @@ +import { useEffect, useRef, useState } from "react"; +import "./index.less"; +import axios from "axios"; + +interface ImageItemProps { + children?: JSX.Element; + src?: string; + imgStyle?: React.CSSProperties; + title?: string; +} + +export const ImageItem = (props: ImageItemProps) => { + const [actionVisible, setActionVisible] = useState(false); + const imgRef = useRef(null); + const actionRef = useRef(null); + const fileInputRef = useRef(null); + const [imgSrc, setImgSrc] = useState(props.src); + + useEffect(() => { + const handleClickOutside = (e: any) => { + if (actionRef.current?.contains(e.target)) return e.preventDefault(); + if (imgRef.current && !imgRef.current.contains(e.target)) + setActionVisible(false); + }; + document.addEventListener("mousedown", handleClickOutside); + return () => document.addEventListener("mousedown", handleClickOutside); + }, [imgRef]); + + /** + * 删除图片 + */ + const onDelete = () => { + setImgSrc(""); + fileInputRef.current?.setAttribute("value", ""); + }; + 3; + const onInsert = () => fileInputRef.current?.click(); + + const handleFileChange = (event: any) => { + if (event.target.files && event.target.files[0]) { + const fd = new FormData(); + fd.append("file", event.target.files[0]); + axios + .post("/api/report/upload", fd, { + headers: { "Content-Type": "multipart/form-data" }, + }) + .then((res) => { + const { objectName } = res.data; + setImgSrc(`/api/report/img/${objectName}`); + }); + //TODO API接口上传,THEN + setImgSrc(event.target.result); + } + }; + + return ( +
+

{props.title}

+ {!imgSrc ? ( +
+ ) : ( +
setActionVisible(true)} + className={`img ${actionVisible ? "active" : ""}`} + ref={imgRef} + style={{ ...props.imgStyle, backgroundImage: `url(${imgSrc})` }} + >
+ )} + {actionVisible && ( +
+ + {!!imgSrc && } + +
+ )} +
+ ); +}; diff --git a/apps/aorta/src/modules/Report/Full/components/Paper/Foot/index.less b/apps/aorta/src/modules/Report/Full/components/Paper/Foot/index.less new file mode 100644 index 0000000..dab7af2 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/components/Paper/Foot/index.less @@ -0,0 +1,15 @@ +.page-foot { + position: absolute; + left: 0; + right: 0; + bottom: 0; + display: flex; + border-top: 0.07rem solid var(--color-bg-primary); + padding-top: 0.57rem; + align-items: center; + justify-content: space-between; + + div { + line-height: 1; + } +} \ No newline at end of file diff --git a/apps/aorta/src/modules/Report/Full/components/Paper/Foot/index.tsx b/apps/aorta/src/modules/Report/Full/components/Paper/Foot/index.tsx new file mode 100644 index 0000000..a5acede --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/components/Paper/Foot/index.tsx @@ -0,0 +1,35 @@ +import "./index.less"; + +export interface PaperFootProps { + children?: JSX.Element; + date?: string; + /** + * 页码 + */ + pageNum?: number; + /** + * 全部页码 + */ + totalPageNum?: number; +} + +export const PaperFoot = (props: PaperFootProps) => { + return ( +
+
+ {props.date && ( + <> + 报告日期: {props.date} + + )} +
+
+ {props.pageNum && props.totalPageNum && ( + <> + 第{props.pageNum}页/共{props.totalPageNum}页 + + )} +
+
+ ); +}; diff --git a/apps/aorta/src/modules/Report/Full/components/Paper/Head/index.less b/apps/aorta/src/modules/Report/Full/components/Paper/Head/index.less new file mode 100644 index 0000000..98ed7d8 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/components/Paper/Head/index.less @@ -0,0 +1,13 @@ +.page-head { + text-align: right; + line-height: 1; + padding-bottom: 0.57rem; + border-bottom: 0.07rem solid var(--color-bg-primary); + margin-bottom: 2rem; + + .logo-group { + display: inline-flex; + align-items: center; + } + +} \ No newline at end of file diff --git a/apps/aorta/src/modules/Report/Full/components/Paper/Head/index.tsx b/apps/aorta/src/modules/Report/Full/components/Paper/Head/index.tsx new file mode 100644 index 0000000..7cfc5e5 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/components/Paper/Head/index.tsx @@ -0,0 +1,33 @@ +import "./index.less"; + +interface PaperHeadProps { + children?: JSX.Element; +} + +export const PaperHead = (props: PaperHeadProps) => { + return ( +
+
+ + + + + + + +
+
+ ); +}; diff --git a/apps/aorta/src/modules/Report/Full/components/Paper/index.less b/apps/aorta/src/modules/Report/Full/components/Paper/index.less new file mode 100644 index 0000000..ab92ae3 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/components/Paper/index.less @@ -0,0 +1,15 @@ +.paper { + margin: 0 auto 1rem auto; + background: #fff; + + &.a4 { + padding: 4rem; + width: 794px; + height: 1123px; + } + + >main { + position: relative; + height: 100%; + } +} \ No newline at end of file diff --git a/apps/aorta/src/modules/Report/Full/components/Paper/index.tsx b/apps/aorta/src/modules/Report/Full/components/Paper/index.tsx new file mode 100644 index 0000000..c38c88f --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/components/Paper/index.tsx @@ -0,0 +1,31 @@ +import "./index.less"; +import { PaperHead } from "./Head"; +import { PaperFoot, PaperFootProps } from "./Foot"; + +interface PaperProps { + children?: JSX.Element | any; + hiddenHeadFoot?: boolean; +} + +type PaperFootPageProps = Pick< + PaperFootProps, + "date" | "pageNum" | "totalPageNum" +>; + +export const Paper = (props: PaperProps & PaperFootPageProps) => { + return ( +
+
+ {!props.hiddenHeadFoot && } + {props.children} + {!props.hiddenHeadFoot && ( + + )} +
+
+ ); +}; diff --git a/apps/aorta/src/modules/Report/Full/components/Paragraph/index.less b/apps/aorta/src/modules/Report/Full/components/Paragraph/index.less new file mode 100644 index 0000000..1d6cc62 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/components/Paragraph/index.less @@ -0,0 +1,6 @@ +p { + margin: 0; + line-height: 1.29rem; + font-weight: 400; + text-align: justify; +} \ No newline at end of file diff --git a/apps/aorta/src/modules/Report/Full/components/Paragraph/index.tsx b/apps/aorta/src/modules/Report/Full/components/Paragraph/index.tsx new file mode 100644 index 0000000..d74cf12 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/components/Paragraph/index.tsx @@ -0,0 +1,11 @@ +import './index.less' + +interface ParagraphProps { + text: string + children?: JSX.Element + style?: React.CSSProperties +} + +export const Paragraph = (props: ParagraphProps) => { + return

{props.text}

+} diff --git a/apps/aorta/src/modules/Report/Full/components/ProgressBar/index.tsx b/apps/aorta/src/modules/Report/Full/components/ProgressBar/index.tsx new file mode 100644 index 0000000..792e93a --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/components/ProgressBar/index.tsx @@ -0,0 +1,42 @@ +interface ProgressBarProps { + children?: JSX.Element; + color?: string; + bgColor?: string; + completed: number; +} + +export const ProgressBar = (props: ProgressBarProps) => { + const fixed = props.completed * 100; + + const containerStyles: React.CSSProperties = { + position: "fixed", + height: 5, + left: 0, + top: 0, + right: 0, + backgroundColor: "#e0e0de", + }; + + const fillerStyles: React.CSSProperties = { + height: "100%", + width: `${props.completed * 100}%`, + backgroundColor: props?.bgColor ?? "red", + borderRadius: "inherit", + textAlign: "right", + }; + + const labelStyles: React.CSSProperties = { + display: "inline-block", + transform: "translateY(2px)", + fontSize: "12px", + color: props.color ?? "red", + }; + + return ( +
+
+ {`${fixed.toFixed(2)}%`} +
+
+ ); +}; diff --git a/apps/aorta/src/modules/Report/Full/components/Reference/index.less b/apps/aorta/src/modules/Report/Full/components/Reference/index.less new file mode 100644 index 0000000..4031591 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/components/Reference/index.less @@ -0,0 +1,18 @@ +.ref-literature { + h4 { + margin: 0; + padding-bottom: 0.43rem; + color: var(--color-primary); + font-size: bold; + } + + p { + margin: 0; + text-align: left; + padding-bottom: 0.27rem; + + &:last-of-type { + padding-bottom: 0; + } + } +} \ No newline at end of file diff --git a/apps/aorta/src/modules/Report/Full/components/Reference/index.tsx b/apps/aorta/src/modules/Report/Full/components/Reference/index.tsx new file mode 100644 index 0000000..0f83cc4 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/components/Reference/index.tsx @@ -0,0 +1,20 @@ +import "./index.less"; + +interface ReferenceProps { + children?: JSX.Element; + literature: string[]; + style?: React.CSSProperties; + titleVisible?: boolean; +} + +export const Reference = (props: ReferenceProps) => { + const { titleVisible = false } = props; + return ( +
+ {titleVisible &&

参考文献:

} + {props.literature.map((t, i) => ( +

{t}

+ ))} +
+ ); +}; diff --git a/apps/aorta/src/modules/Report/Full/components/Table/index.less b/apps/aorta/src/modules/Report/Full/components/Table/index.less new file mode 100644 index 0000000..a483af3 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/components/Table/index.less @@ -0,0 +1,43 @@ +.table-cell { + border-collapse: collapse; + width: 100%; + + &.border-outer { + border: 1px solid var(--color-table-border); + } + + tbody { + tr { + padding: 0 2rem; + + &:nth-of-type(2n+1) { + background: var(--color-bg-primary-2); + } + + td { + padding-left: 2rem; + height: 1.29rem; + + &.border-vertical { + border-right: 1px solid var(--color-table-border); + + &:first-of-type { + border-left: 1px solid var(--color-table-border); + } + } + + &.border-horizon { + border-bottom: 1px solid var(--color-table-border); + + &:first-of-type { + border-top: 1px solid var(--color-table-border); + } + } + } + + .highlight { + color: red; + } + } + } +} \ No newline at end of file diff --git a/apps/aorta/src/modules/Report/Full/components/Table/index.tsx b/apps/aorta/src/modules/Report/Full/components/Table/index.tsx new file mode 100644 index 0000000..2a2b495 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/components/Table/index.tsx @@ -0,0 +1,58 @@ +import './index.less' + +export type TableDataCell = { + prop: string + content: string + colSpan?: number + highlight?: boolean +} + +export type TableData = TableDataCell[][] + +interface TableProps { + children?: JSX.Element + data: TableData + style?: React.CSSProperties + border?: { vertical?: boolean; horizon?: boolean; outer?: boolean } +} + +export const Table = (props: TableProps) => { + return ( + + + {props.data.map((row, rowIndex) => ( + + {row.map((cell, cellIndex: number) => { + if (typeof cell === 'object') { + return ( + + ) + } + return + })} + + ))} + +
+ {cell.prop}: + + {cell.content} + + {cell}
+ ) +} diff --git a/apps/aorta/src/modules/Report/Full/index.less b/apps/aorta/src/modules/Report/Full/index.less new file mode 100644 index 0000000..74fffbd --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/index.less @@ -0,0 +1,48 @@ +.report-full-preview { + padding: 24px 0; + background: #f1f1f1; + --color-primary: #2A5DC0; + --color-bg-primary-2: #e9eff4; + --color-bg-primary: #2E97D1; + --color-table-border: #AAC4D8; + --color-danger: #F33939; + + + .action-bar { + padding: 10px; + position: fixed; + width: 100px; + background: #fff; + border: 3px; + top: 50%; + transform: translateY(-50%); + right: calc((100% - 794px) / 2 - 100px - 10px); + } + + .risk-module { + section { + h2 { + margin: 0; + color: var(--color-danger); + } + } + + section { + h3 { + margin: 0; + color: var(--color-bg-primary); + padding-bottom: 0.86rem; + + span { + font-size: 0.85rem; + } + } + + p { + font-size: 0.85rem; + margin-top: 0; + margin-bottom: 2.86rem; + } + } + } +} \ No newline at end of file diff --git a/apps/aorta/src/modules/Report/Full/index.tsx b/apps/aorta/src/modules/Report/Full/index.tsx new file mode 100644 index 0000000..9b9b809 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/index.tsx @@ -0,0 +1,132 @@ +import { useEffect, useState } from "react"; +import { Paper } from "./components/Paper"; +import { Aorta } from "./pages/Aorta"; +import { Catalogue } from "./pages/Catalogue"; +import { PatientProfile } from "./pages/PatientProfile"; +import { ProjectionAngle } from "./pages/ProjectionAngle"; +import { dom2PDF } from "@tavi/util"; +import { LVOT } from "./pages/LVOT"; +import { SOV } from "./pages/SOV"; +import { STJ } from "./pages/STJ"; +import { AscAorta } from "./pages/AscAorta"; +import { AortaValve } from "./pages/AortaValve"; +import { Calcify } from "./pages/Calcify"; +import { Slice } from "./pages/Slice"; +import { RingShape } from "./pages/RingShape"; +import { Coronary } from "./pages/Coronary"; +import { RightCoronary } from "./pages/RightCoronary"; +import { LeftCoronarySinus } from "./pages/LeftCoronarySinus"; +import { RightCoronarySinus } from "./pages/RightCoronarySinus"; +import { NoCoronarySinus } from "./pages/NoCoronarySinus"; +import { ProjectionAngleP2 } from "./pages/ProjectionAngle-P2"; +import { SuicideLeft } from "./pages/SuicideLeft"; +import "./index.less"; +import { ProgressBar } from "./components/ProgressBar"; +import axios from "axios"; + +axios.defaults.withCredentials = true; + +interface DoctorProps { + children?: JSX.Element; +} + +export const ReportFullVersion = (props: DoctorProps) => { + const [date, totalPageNum] = ["2023-06-14", 21]; + const [completed, setCompleted] = useState(0); + + useEffect(() => { + axios.get("/api/aorta/report/root").then((res) => { + console.log(res); + }); + }, []); + + /** + * 下载pdf + */ + const downloadHandler = () => { + const elements = Array.from( + document.querySelectorAll(".a4") + ) as HTMLElement[]; + dom2PDF({ + elements, + scale: 3, + onProgress: (currentPage, totalPage) => { + setCompleted(currentPage / totalPage); + }, + }).then((pdf) => pdf.save("test.pdf")); + }; + + return ( +
+ {completed > 0 && ( + + )} +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/Aorta/index.tsx b/apps/aorta/src/modules/Report/Full/pages/Aorta/index.tsx new file mode 100644 index 0000000..75772c8 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/Aorta/index.tsx @@ -0,0 +1,46 @@ +import { Heading } from "../../components/Heading"; +import { ImageItem } from "../../components/ImageItem"; +import { Table } from "../../components/Table"; + +interface AortaProps { + children?: JSX.Element; +} + +const data = [ + [ + { prop: "周长", content: "1mm" }, + { prop: "周长导出径", content: "1mm" }, + ], + [ + { prop: "面积", content: "1mm²" }, + { prop: "面积导出径", content: "1mm" }, + ], + [ + { prop: "长径", content: "1mm" }, + { prop: "短径", content: "1mm" }, + ], + [{ prop: "平均径", content: "1mm", colSpan: 1 }], +]; + + +const src = + "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png"; + +export const Aorta = (props: AortaProps) => { + return ( +
+ + + + + + ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/AortaValve/index.tsx b/apps/aorta/src/modules/Report/Full/pages/AortaValve/index.tsx new file mode 100644 index 0000000..ae8a0d1 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/AortaValve/index.tsx @@ -0,0 +1,24 @@ +import { Heading } from "../../components/Heading"; +import { ImageItem } from "../../components/ImageItem"; + +interface AortaValveProps { + children?: JSX.Element; +} + +const src = + "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png"; + +export const AortaValve = (props: AortaValveProps) => { + return ( +
+ + +

三叶瓣

+ +
+ ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/AscAorta/index.tsx b/apps/aorta/src/modules/Report/Full/pages/AscAorta/index.tsx new file mode 100644 index 0000000..7fbb497 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/AscAorta/index.tsx @@ -0,0 +1,46 @@ +import { Heading } from "../../components/Heading"; +import { ImageItem } from "../../components/ImageItem"; +import { Table } from "../../components/Table"; + +interface AscAortaProps { + children?: JSX.Element; +} + +const data = [ + [ + { prop: "周长", content: "1mm" }, + { prop: "周长导出径", content: "1mm" }, + ], + [ + { prop: "面积", content: "1mm²" }, + { prop: "面积导出径", content: "1mm" }, + ], + [ + { prop: "长径", content: "1mm" }, + { prop: "短径", content: "1mm" }, + ], + [ + { prop: "平均径", content: "1mm" }, + { prop: "窦管交界平面高度", content: "22.50mm" }, + ], +]; + +const src = + "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png"; + +export const AscAorta = (props: AscAortaProps) => { + return ( +
+ +
+ + + ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/Calcify/index.tsx b/apps/aorta/src/modules/Report/Full/pages/Calcify/index.tsx new file mode 100644 index 0000000..be43005 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/Calcify/index.tsx @@ -0,0 +1,56 @@ +/** + * 钙化形态 + * PageNumber = 9 + */ + +import { Heading } from "../../components/Heading"; +import { ImageItem } from "../../components/ImageItem"; +import { Table } from "../../components/Table"; +import { Reference } from "../../components/Reference"; + +interface CalcifyProps { + children?: JSX.Element; +} + +const data = [ + [ + { prop: "疑似钙化区域体积", content: "1351.53mmm³", highlight: true }, + { prop: "Hu850", content: "72.00mm³" }, + ], +]; + +const src = + "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png"; + +export const Calcify = (props: CalcifyProps) => { + return ( +
+ +
+
+
+

冠脉阻塞风险程度:重度

+ +
+
+

+ 冠脉阻塞风险定义(可见参考文献) +

+

{"钙化积分8001500以上重度。"}

+
+
+ + + + ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/Catalogue/index.less b/apps/aorta/src/modules/Report/Full/pages/Catalogue/index.less new file mode 100644 index 0000000..13c6777 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/Catalogue/index.less @@ -0,0 +1,91 @@ +.catalogue { + >div { + color: var(--color-primary); + + span { + display: inline-block; + padding-bottom: 0.5rem; + font-weight: bold; + font-size: 1.71rem; + border-bottom: 3px solid var(--color-primary); + } + } + + ul { + margin: 0; + padding-top: 2rem; + padding-left: 0; + + li { + list-style: none; + + header { + display: flex; + align-items: center; + background: var(--color-bg-primary-2); + border-right: 0.29rem solid var(--color-bg-primary); + + span { + display: inline-flex; + align-items: center; + justify-content: center; + height: 1.89rem; + width: 1.89rem; + background: var(--color-bg-primary); + color: #fff; + } + + p { + padding-left: 0.89rem; + margin: 0; + color: var(--color-primary); + font-weight: bold; + } + } + + ol { + padding: 1.14rem 0 1.14rem 2.89rem; + + li { + display: grid; + align-items: center; + grid-template-columns: 2.5rem 1fr auto; + padding-bottom: 0.7rem; + + &:last-of-type { + padding-bottom: 0; + } + + >div { + margin: 0; + display: grid; + grid-template-columns: auto 1fr; + + >span b { + font-weight: 400; + font-size: 0.85rem; + } + + >div { + padding: 0 0.86rem; + display: flex; + align-items: center; + + em { + display: inline-block; + border-bottom: 2px dotted #000; + width: 100%; + } + } + } + + .page-number { + display: inline-block; + padding-right: 0.29rem; + text-align: right; + } + } + } + } + } +} \ No newline at end of file diff --git a/apps/aorta/src/modules/Report/Full/pages/Catalogue/index.tsx b/apps/aorta/src/modules/Report/Full/pages/Catalogue/index.tsx new file mode 100644 index 0000000..32bc2f8 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/Catalogue/index.tsx @@ -0,0 +1,136 @@ +import { Heading } from "../../components/Heading"; +import "./index.less"; +import { Section } from "./interface"; + +interface CatalogueProps { + dataSource?: []; +} + +const mockData: Section[] = [ + { + title: "主动脉根部的大小和形态", + subsections: [ + { + title: "主动脉瓣环 Annulus", + pageNumber: 2, + }, + { + title: "左室流出道 LVOT", + pageNumber: 3, + }, + { + title: "瓦氏窦 SOV", + pageNumber: 4, + }, + { + title: "窦管交界 STJ", + pageNumber: 5, + }, + { + title: "升主动脉 Ascending Aorta", + pageNumber: 6, + }, + ], + }, + { + title: "主动脉瓣的形态和功能", + subsections: [ + { + title: "瓣叶类型", + pageNumber: 7, + }, + { + title: "钙化形态", + pageNumber: 8, + }, + { + title: "分割形态", + pageNumber: 9, + }, + { + title: "环上形态", + pageNumber: 10, + }, + ], + }, + { + title: "冠状动脉和临近结构", + subsections: [ + { + title: "左冠开口高度", + pageNumber: 11, + }, + { + title: "右冠开口高度", + pageNumber: 12, + }, + { + title: "左冠窦瓣叶长度", + forRef: true, + pageNumber: 13, + }, + { + title: "右冠窦瓣叶长度", + forRef: true, + pageNumber: 14, + }, + { + title: "无冠窦瓣叶长度", + forRef: true, + pageNumber: 15, + }, + ], + }, + { + title: "投照角度", + subsections: [ + { + title: "建议投照角度", + pageNumber: 16, + }, + { + title: "三维重建效果", + pageNumber: 17, + }, + ], + }, +]; + +export const Catalogue = (props: CatalogueProps) => { + return ( +
+ +
    + {mockData.map((section, i) => { + return ( +
  • +
    + {i + 1} +

    {section.title}

    +
    +
      + {section.subsections?.map((sub, i_sub) => ( +
    1. + + {i + 1}-{i_sub + 1} + +
      + + {sub.title} + {sub.forRef && (仅供参考)} + +
      + +
      +
      + {sub.pageNumber} +
    2. + ))} +
    +
  • + ); + })} +
+
+ ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/Catalogue/interface.tsx b/apps/aorta/src/modules/Report/Full/pages/Catalogue/interface.tsx new file mode 100644 index 0000000..713e296 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/Catalogue/interface.tsx @@ -0,0 +1,20 @@ +export interface Section { + title: string; + subsections?: Subsection[]; +} + +export interface Subsection { + title: string; + /** + * 是否在title后面加上仅供参考小字 + */ + forRef?: boolean; + /** + * 页码 + */ + pageNumber: number; +} + +export interface Contents { + sections: Section[]; +} diff --git a/apps/aorta/src/modules/Report/Full/pages/Coronary/index.tsx b/apps/aorta/src/modules/Report/Full/pages/Coronary/index.tsx new file mode 100644 index 0000000..808e0aa --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/Coronary/index.tsx @@ -0,0 +1,55 @@ +import { Heading } from "../../components/Heading"; +import { ImageItem } from "../../components/ImageItem"; +import { Reference } from "../../components/Reference"; +import { Table } from "../../components/Table"; + +interface CoronaryProps { + children?: JSX.Element; +} + +const data = [ + [{ prop: "左冠开口高度", content: "9.67mm", colSpan: 2, highlight: true }], +]; + +const src = + "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png"; + +export const Coronary = (props: CoronaryProps) => { + return ( +
+ + +
+
+
+

冠脉阻塞风险程度:重度

+ +
+
+

+ 冠脉阻塞风险定义(可见参考文献) +

+

+ 窦高30mm以下轻度,窦高30mm以下(开口高度12以下)中度,窦高30mm以下(开口高度12以下、瓣叶长度12以上)重度。 +

+
+
+ + + + ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/LVOT/index.tsx b/apps/aorta/src/modules/Report/Full/pages/LVOT/index.tsx new file mode 100644 index 0000000..c8dd863 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/LVOT/index.tsx @@ -0,0 +1,40 @@ +import { Heading } from "../../components/Heading"; +import { ImageItem } from "../../components/ImageItem"; +import { Table } from "../../components/Table"; + +interface LVOTProps { + children?: JSX.Element; +} + +const data = [ + [ + { prop: "周长", content: "1mm" }, + { prop: "周长导出径", content: "1mm" }, + ], + [ + { prop: "面积", content: "1mm²" }, + { prop: "面积导出径", content: "1mm" }, + ], + [ + { prop: "长径", content: "1mm" }, + { prop: "短径", content: "1mm" }, + ], + [{ prop: "平均径", content: "1mm", colSpan: 1 }], +]; + +const src = + "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png"; + +export const LVOT = (props: LVOTProps) => { + return ( +
+ +
+ + + ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/LeftCoronarySinus/index.tsx b/apps/aorta/src/modules/Report/Full/pages/LeftCoronarySinus/index.tsx new file mode 100644 index 0000000..b465334 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/LeftCoronarySinus/index.tsx @@ -0,0 +1,63 @@ +/** + * 左冠窦瓣叶长度 + */ + +import { Heading } from "../../components/Heading"; +import { ImageItem } from "../../components/ImageItem"; +import { Reference } from "../../components/Reference"; +import { Table } from "../../components/Table"; + +interface LeftCoronarySinusProps { + children?: JSX.Element; +} + +const src = + "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png"; + +const data = [ + [{ prop: "左冠开口高度", content: "9.67mm", colSpan: 2, highlight: true }], +]; + +export const LeftCoronarySinus = (props: LeftCoronarySinusProps) => { + return ( +
+ +
+
+
+

冠脉阻塞风险程度:重度

+ +
+
+

+ 冠脉阻塞风险定义(可见参考文献) +

+

+ 窦高30mm以下轻度,窦高30mm以下(开口高度12以下)中度,窦高30mm以下(开口高度12以下、瓣叶长度12以上)重度。 +

+
+
+ + + + ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/NoCoronarySinus/index.tsx b/apps/aorta/src/modules/Report/Full/pages/NoCoronarySinus/index.tsx new file mode 100644 index 0000000..3d4db5a --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/NoCoronarySinus/index.tsx @@ -0,0 +1,38 @@ +/** + * 左冠窦瓣叶长度 + */ + +import { Heading } from "../../components/Heading"; +import { ImageItem } from "../../components/ImageItem"; +import { Table } from "../../components/Table"; + +interface NoCoronarySinusProps { + children?: JSX.Element; +} + +const src = + "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png"; + +const data = [[{ prop: "无冠窦瓣叶长度", content: "9.67mm", colSpan: 2 }]]; + +export const NoCoronarySinus = (props: NoCoronarySinusProps) => { + return ( +
+ +
+ + + ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/PatientProfile/index.less b/apps/aorta/src/modules/Report/Full/pages/PatientProfile/index.less new file mode 100644 index 0000000..7abc166 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/PatientProfile/index.less @@ -0,0 +1,70 @@ +.patient-info { + + .table { + display: grid; + grid-template-columns: repeat(2, 1fr); + border: 1px solid #AAC4D8; + + .item { + padding: 10px; + + &.full-width { + grid-column-start: 1; + grid-column-end: 3; + } + + em { + display: inline-block; + font-style: normal; + font-weight: bold; + min-width: 4.6rem; + } + + &:nth-of-type(1), + &:nth-of-type(2), + &:nth-of-type(5), + &:nth-of-type(6) { + background: #E9EFF4; + } + } + } + + .guide-list { + margin: 0; + padding-left: 0; + padding-bottom: 4.43rem; + + li { + list-style: none; + padding-left: 0; + margin-bottom: 1.43rem; + + h3 { + position: relative; + padding-left: 1rem; + margin: 0; + font-size: 1rem; + font-weight: bold; + + &::before { + position: absolute; + content: ''; + width: 0.7rem; + height: 0.7rem; + left: 0; + top: 50%; + transform: translateY(-50%); + background: var(--color-bg-primary); + border-radius: 50%; + } + } + + p { + margin: 0; + font-size: 1rem; + padding-top: 1rem; + padding-left: 1rem; + } + } + } +} \ No newline at end of file diff --git a/apps/aorta/src/modules/Report/Full/pages/PatientProfile/index.tsx b/apps/aorta/src/modules/Report/Full/pages/PatientProfile/index.tsx new file mode 100644 index 0000000..cc85cb2 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/PatientProfile/index.tsx @@ -0,0 +1,102 @@ +import { Heading } from "../../components/Heading"; +import { Paragraph } from "../../components/Paragraph"; +import { Reference } from "../../components/Reference"; +import "./index.less"; + +interface PatientProfileProps { + children?: JSX.Element; +} + +const tableData = [ + { + prop: "姓名", + value: "刘伟", + }, + { + prop: "性别", + value: "男", + }, + { + prop: "年龄", + value: "68", + }, + { + prop: "医院", + value: "阜外医院", + }, + { + prop: "报告日期", + value: "2023-06-14", + }, + { + prop: "扫描日期", + value: "2023-06-14", + }, + { + prop: "序列名称", + value: "DS_CorCTA 0.75 I26f 3BestSyst 47 %", + block: true, + }, +]; + +const guideData = [ + { + title: "主动脉根部的大小和形态", + content: "对冠状动脉解剖结构,以及TAVI和其他经导管手术的适用性进行评估诊断", + }, + { + title: "主动脉瓣的形态和功能", + content: + "对主动脉瓣膜、瓣叶、钙化,以及先天性畸形而导致瓣叶无法正常开启进行评估诊断", + }, + { + title: "冠状动脉和临近结构", + content: "对TAVR手术后可能产生的并发症进行风险评估", + }, + { + title: "投照角度", + content: "对主动脉根部进行三维模型重建,并对手术过程进行模拟", + }, +]; + +export const PatientProfile = (props: PatientProfileProps) => { + return ( +
+ + + +
+ {tableData.map((item, i) => ( +
+ {item.prop} + {item.value} +
+ ))} +
+ +
    + {guideData.map((guide, i) => ( +
  • +

    {guide.title}

    +

    {guide.content}

    +
  • + ))} +
+ +
+ ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/ProjectionAngle-P2/index.less b/apps/aorta/src/modules/Report/Full/pages/ProjectionAngle-P2/index.less new file mode 100644 index 0000000..f6dd96b --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/ProjectionAngle-P2/index.less @@ -0,0 +1,7 @@ +.project-angle-p2 { + .image-group { + display: grid; + grid-template-columns: 1fr 1fr; + column-gap: 2.43rem; + } +} \ No newline at end of file diff --git a/apps/aorta/src/modules/Report/Full/pages/ProjectionAngle-P2/index.tsx b/apps/aorta/src/modules/Report/Full/pages/ProjectionAngle-P2/index.tsx new file mode 100644 index 0000000..608f1a9 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/ProjectionAngle-P2/index.tsx @@ -0,0 +1,29 @@ +import { ImageItem } from "../../components/ImageItem"; +import "./index.less"; +import { Reference } from "../../components/Reference"; + +interface ProjectionAngleP2Props { + children?: JSX.Element; +} + +const src = + "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png"; + +export const ProjectionAngleP2 = (props: ProjectionAngleP2Props) => { + return ( +
+
+ + +
+ +
+ ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/ProjectionAngle/index.less b/apps/aorta/src/modules/Report/Full/pages/ProjectionAngle/index.less new file mode 100644 index 0000000..7d90aad --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/ProjectionAngle/index.less @@ -0,0 +1,36 @@ +.project-angle { + .annotation { + padding-top: 0.57rem; + color: var(--color-bg-primary); + } + + .dots { + display: flex; + padding-left: 0; + + li { + list-style: none; + margin-right: 2rem; + display: flex; + align-items: center; + + >em { + display: inline-block; + width: 0.57rem; + height: 0.57rem; + border-radius: 50%; + } + + span { + padding-left: 0.29rem; + color: var(--color-bg-primary); + } + } + } + + .image-group { + display: grid; + grid-template-columns: 1fr 1fr; + column-gap: 2.43rem; + } +} \ No newline at end of file diff --git a/apps/aorta/src/modules/Report/Full/pages/ProjectionAngle/index.tsx b/apps/aorta/src/modules/Report/Full/pages/ProjectionAngle/index.tsx new file mode 100644 index 0000000..353c072 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/ProjectionAngle/index.tsx @@ -0,0 +1,95 @@ +import { Heading } from "../../components/Heading"; +import { Table, TableData } from "../../components/Table"; +import "./index.less"; +import { ImageItem } from "../../components/ImageItem"; +interface ProjectionAngleProps { + children?: JSX.Element; +} + +const src = + "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png"; + +const tableData: TableData = [ + [ + { + prop: "瓣环平面与水平面夹角", + content: "66deg", + highlight: true, + colSpan: 5, + }, + ], + [ + { prop: "右窦居中", content: "" }, + { prop: "LAO", content: "15deg" }, + { prop: "CAU", content: "25deg" }, + ], + [ + { prop: "左右窦重合(Cusp-Overlap)", content: "" }, + { prop: "LAO", content: "15deg" }, + { prop: "CAU", content: "25deg" }, + ], + [ + { prop: "无冠窦平行法", content: "" }, + { prop: "LAO", content: "15deg" }, + { prop: "CAU", content: "25deg" }, + ], + [ + { prop: "右无重合", content: "" }, + { prop: "LAO", content: "15deg" }, + { prop: "CAU", content: "25deg" }, + ], +]; + +const dots = [ + { + color: "#BA503D", + alias: "左冠窦窦底", + }, + { + color: "#E7B551", + alias: "右冠窦窦底", + }, + { + color: "#4B9979", + alias: "无冠窦窦底", + }, +]; + +export const ProjectionAngle = (props: ProjectionAngleProps) => { + return ( +
+ + +
+

+ 注:deg即Degree的缩写,表示角度制。例:15deg=15° +

+
+
+

心脏横位风险程度:中度

+ +
+
+

+ 心脏横位风险定义(可见参考文献) +

+

+ 瓣环平面与水平面夹角,48deg-58deg轻度、59deg-70deg中度,70deg以上重度。 +

+
+
+
    + {dots.map((i, index) => ( +
  • + + {i.alias} +
  • + ))} +
+
+ + +
+ + ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/RightCoronary/index.tsx b/apps/aorta/src/modules/Report/Full/pages/RightCoronary/index.tsx new file mode 100644 index 0000000..76845ce --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/RightCoronary/index.tsx @@ -0,0 +1,26 @@ +import { Heading } from "../../components/Heading"; +import { ImageItem } from "../../components/ImageItem"; +import { Table } from "../../components/Table"; + +interface RightCoronaryProps { + children?: JSX.Element; +} + +const data = [[{ prop: "右冠开口高度", content: "1mm", colSpan: 2 }]]; + +const src = + "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png"; + +export const RightCoronary = (props: RightCoronaryProps) => { + return ( +
+ +
+ + + ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/RightCoronarySinus/index.tsx b/apps/aorta/src/modules/Report/Full/pages/RightCoronarySinus/index.tsx new file mode 100644 index 0000000..55fbf6d --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/RightCoronarySinus/index.tsx @@ -0,0 +1,39 @@ +/** + * 左冠窦瓣叶长度 + */ + +import { Heading } from "../../components/Heading"; +import { ImageItem } from "../../components/ImageItem"; +import { Reference } from "../../components/Reference"; +import { Table } from "../../components/Table"; + +interface RightCoronarySinusProps { + children?: JSX.Element; +} + +const src = + "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png"; + +const data = [[{ prop: "右冠开口高度", content: "9.67mm", colSpan: 2 }]]; + +export const RightCoronarySinus = (props: RightCoronarySinusProps) => { + return ( +
+ +
+ + + ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/RingShape/index.less b/apps/aorta/src/modules/Report/Full/pages/RingShape/index.less new file mode 100644 index 0000000..e4251b4 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/RingShape/index.less @@ -0,0 +1,6 @@ +.ring-shape { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + row-gap: 2.86rem; + column-gap: 1rem; +} \ No newline at end of file diff --git a/apps/aorta/src/modules/Report/Full/pages/RingShape/index.tsx b/apps/aorta/src/modules/Report/Full/pages/RingShape/index.tsx new file mode 100644 index 0000000..5d6c661 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/RingShape/index.tsx @@ -0,0 +1,59 @@ +import { Heading } from "../../components/Heading"; +import { ImageItem } from "../../components/ImageItem"; +import "./index.less"; + +interface RingShapeProps { + children?: JSX.Element; +} + +const data = [ + { + alias: "左室流出道", + src: "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png", + }, + { + alias: "瓣环下:2mm", + src: "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png", + }, + { + alias: "瓣环平面", + src: "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png", + }, + { + alias: "瓣环上:2mm", + src: "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png", + }, + { + alias: "瓣环上:4mm", + src: "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png", + }, + { + alias: "瓣环上:6mm", + src: "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png", + }, + { + alias: "瓣环上:8mm", + src: "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png", + }, + { + alias: "瓣环上:10mm", + src: "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png", + }, + { + alias: "瓣环上:12mm", + src: "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png", + }, +]; + +export const RingShape = (props: RingShapeProps) => { + return ( +
+ +
+ {data.map((i, index) => ( + + ))} +
+
+ ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/SOV/index.tsx b/apps/aorta/src/modules/Report/Full/pages/SOV/index.tsx new file mode 100644 index 0000000..cc6d624 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/SOV/index.tsx @@ -0,0 +1,32 @@ +import { Heading } from "../../components/Heading"; +import { ImageItem } from "../../components/ImageItem"; +import { Table } from "../../components/Table"; + +interface SOVProps { + children?: JSX.Element; +} + +const data = [ + [ + { prop: "SOV-L:", content: "36.40mm" }, + { prop: "SOV-R:", content: "36.69mm" }, + ], + [{ prop: "SOV-N:", content: "37.07mm" }], +]; + +const src = + "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png"; + +export const SOV = (props: SOVProps) => { + return ( +
+ +
+ + + ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/STJ/index.tsx b/apps/aorta/src/modules/Report/Full/pages/STJ/index.tsx new file mode 100644 index 0000000..2ea73be --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/STJ/index.tsx @@ -0,0 +1,66 @@ +import { Heading } from "../../components/Heading"; +import { ImageItem } from "../../components/ImageItem"; +import { Table } from "../../components/Table"; +import { Reference } from "../../components/Reference"; + +interface STJProps { + children?: JSX.Element; +} + +const data = [ + [ + { prop: "周长", content: "1mm" }, + { prop: "周长导出径", content: "1mm" }, + ], + [ + { prop: "面积", content: "1mm²" }, + { prop: "面积导出径", content: "1mm" }, + ], + [ + { prop: "长径", content: "1mm" }, + { prop: "短径", content: "1mm" }, + ], + [ + { prop: "平均径", content: "1mm" }, + { prop: "窦管交界平面高度", content: "22.50mm" }, + ], +]; + +const src = + "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png"; + +export const STJ = (props: STJProps) => { + return ( +
+ +
+
+
+

冠脉阻塞风险程度:重度

+ +
+
+

+ 冠脉阻塞风险定义(可见参考文献) +

+

+ 窦高30mm以下轻度,窦高30mm以下(开口高度12以下)中度,窦高30mm以下(开口高度12以下、瓣叶长度12以上)重度。 +

+
+
+ + + + ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/Slice/index.less b/apps/aorta/src/modules/Report/Full/pages/Slice/index.less new file mode 100644 index 0000000..fef10c2 --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/Slice/index.less @@ -0,0 +1,22 @@ +.slice { + >p { + margin-top: 0; + margin-bottom: 2.86rem; + + span { + display: inline-block; + margin-right: 1.43rem; + + &:last-of-type { + margin-right: 0; + } + } + } + + .slice-image { + display: grid; + grid-template-columns: 1fr 1fr; + row-gap: 2.86rem; + column-gap: 3.93rem; + } +} \ No newline at end of file diff --git a/apps/aorta/src/modules/Report/Full/pages/Slice/index.tsx b/apps/aorta/src/modules/Report/Full/pages/Slice/index.tsx new file mode 100644 index 0000000..538d34f --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/Slice/index.tsx @@ -0,0 +1,44 @@ +/** + * 分隔形态 + */ + +import { Heading } from "../../components/Heading"; +import "./index.less"; +import { ImageItem } from "../../components/ImageItem"; + +interface SliceProps { + children?: JSX.Element; +} + +const data = [ + { + alias: "左冠瓣", + src: "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png", + }, + { + alias: "右冠瓣", + src: "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png", + }, + { + alias: "无冠瓣", + src: "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png", + }, +]; + +export const Slice = (props: SliceProps) => { + return ( +
+ +

+ {data.map((i, index) => ( + {i.alias} + ))} +

+
+ {data.map((i, index) => ( + + ))} +
+
+ ); +}; diff --git a/apps/aorta/src/modules/Report/Full/pages/SuicideLeft/index.tsx b/apps/aorta/src/modules/Report/Full/pages/SuicideLeft/index.tsx new file mode 100644 index 0000000..f778bce --- /dev/null +++ b/apps/aorta/src/modules/Report/Full/pages/SuicideLeft/index.tsx @@ -0,0 +1,52 @@ +import { Heading } from "../../components/Heading"; +import { ImageItem } from "../../components/ImageItem"; +import { Reference } from "../../components/Reference"; +import { Table } from "../../components/Table"; + +interface SuicideLeftProps { + children?: JSX.Element; +} + +const tableData = [ + [ + { + prop: "左室心腔容积", + content: "66deg", + }, + { + prop: "左室心肌体积", + content: "66deg", + }, + ], +]; + +const src = + "https://1500021350.vod2.myqcloud.com/cbafb25avodsh1500021350/e7f802d33270835009150070462/hgdT5ulA9RwA.png"; + +export const SuicideLeft = (props: SuicideLeftProps) => { + return ( +
+ +
+

+ 自杀性左心室风险定义 +

+

+ a.左室心腔容积≤15ml;b.左室心腔体积/(左室心腔体积+左室心肌体积)<25% + 满足a条件为轻度,满足b条件中度,同时满足ab条件重度 +

+ + + + ); +}; diff --git a/apps/aorta/src/modules/Root/Viewer/Root/index.tsx b/apps/aorta/src/modules/Root/Viewer/Root/index.tsx new file mode 100644 index 0000000..a134be0 --- /dev/null +++ b/apps/aorta/src/modules/Root/Viewer/Root/index.tsx @@ -0,0 +1,7 @@ +interface RootViewerProps { + children?: JSX.Element; +} + +export const RootViewer = (props: RootViewerProps) => { + return
RootViewer
; +}; diff --git a/apps/aorta/src/modules/User/Profile/index.tsx b/apps/aorta/src/modules/User/Profile/index.tsx new file mode 100644 index 0000000..aa374bf --- /dev/null +++ b/apps/aorta/src/modules/User/Profile/index.tsx @@ -0,0 +1,7 @@ +interface UserProfileProps { + children?: JSX.Element; +} + +export const UserProfile = (props: UserProfileProps) => { + return
UserProfile
; +}; diff --git a/apps/aorta/src/modules/User/Setting/index.tsx b/apps/aorta/src/modules/User/Setting/index.tsx new file mode 100644 index 0000000..b3b0942 --- /dev/null +++ b/apps/aorta/src/modules/User/Setting/index.tsx @@ -0,0 +1,7 @@ +interface UserSettingProps { + children?: JSX.Element; +} + +export const UserSetting = (props: UserSettingProps) => { + return
UserSetting
; +}; diff --git a/apps/aorta/src/readme.md b/apps/aorta/src/readme.md new file mode 100644 index 0000000..6de1771 --- /dev/null +++ b/apps/aorta/src/readme.md @@ -0,0 +1 @@ +用户界面层(interfaces):这一层包含了所有的用户界面和展示逻辑,通常由React组件来实现。 \ No newline at end of file diff --git a/apps/aorta/src/router/AuthGuard.tsx b/apps/aorta/src/router/AuthGuard.tsx new file mode 100644 index 0000000..a4fc2c0 --- /dev/null +++ b/apps/aorta/src/router/AuthGuard.tsx @@ -0,0 +1,47 @@ +import { AuthFailedReplacePath } from "@/constant"; +import { useLocation, useNavigate } from "react-router-dom"; +import { useEffect } from "react"; +import { useDomain } from "@/hook/useDomain"; +import { message } from "antd"; + +interface GuardProps { + element: JSX.Element; + auth?: boolean; + title?: string; +} + +/** + * 守卫 + */ +export const Guard = (props: GuardProps) => { + const location = useLocation(); + const navigate = useNavigate(); + const { userDomainService } = useDomain(); + const [messageApi, contextHolder] = message.useMessage(); + const { isLoggedIn } = userDomainService.user; + + useEffect(() => { + if (props.auth && !isLoggedIn) { + userDomainService.userAuth().then((result: any) => { + const { success, msg } = result; + if (!success) { + messageApi.error(msg); + navigate(AuthFailedReplacePath); + } + }); + } + return () => {}; + }, [navigate]); + + useEffect(() => { + if (props?.title) document.title = props?.title; + return () => {}; + }, [location.pathname]); + + return ( + <> + {contextHolder} + {props.element} + + ); +}; diff --git a/apps/aorta/src/router/index.tsx b/apps/aorta/src/router/index.tsx new file mode 100644 index 0000000..bcec807 --- /dev/null +++ b/apps/aorta/src/router/index.tsx @@ -0,0 +1,4 @@ +import { routesConfig } from "./router.config"; +import { useRoutes } from "react-router"; + +export const RouterElements = () => useRoutes(routesConfig); diff --git a/apps/aorta/src/router/router.config.tsx b/apps/aorta/src/router/router.config.tsx new file mode 100644 index 0000000..30ae1bb --- /dev/null +++ b/apps/aorta/src/router/router.config.tsx @@ -0,0 +1,50 @@ +import { Navigate, RouteObject } from "react-router"; +import { Login } from "../modules/Login"; +import { PatientList } from "../modules/PatientList"; +import { RootViewer } from "../modules/Root/Viewer/Root"; +import { PeripheralViewer } from "../modules/Peripheral"; +import { Dashboard } from "@/modules/Dashboard"; +import { ReportFullVersion } from "@/modules/Report/Full"; +import { Guard } from "./AuthGuard"; +import { Layout } from "@/components/Layout"; + +export const routesConfig: RouteObject[] = [ + { + path: "login", + element: } title="CVPILOT Viewer" />, + }, + { + path: "/", + element: } auth />, + children: [ + { + path: "/", + element: , + }, + { + path: "dash", + element: } title="仪表盘" />, + }, + { + path: "list", + element: } title="患者列表" />, + }, + { + path: "root/viewer", + element: } title="根部分析" />, + }, + { + path: "root/report/full", + element: } title="完整报告" />, + }, + { + path: "peripheral/viewer", + element: } title="外周分析" />, + }, + ], + }, + { + path: "*", + element: 404, + }, +]; diff --git a/apps/aorta/src/styles/app.less b/apps/aorta/src/styles/app.less new file mode 100644 index 0000000..14dab9e --- /dev/null +++ b/apps/aorta/src/styles/app.less @@ -0,0 +1,10 @@ +* { + box-sizing: border-box; +} + +html, +body { + margin: 0; + padding: 0; + font-size: 14px; +} \ No newline at end of file diff --git a/apps/aorta/tsconfig.json b/apps/aorta/tsconfig.json new file mode 100644 index 0000000..4d6c0f8 --- /dev/null +++ b/apps/aorta/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": [ + "src/*" + ], + "@@/*": [ + "core/*" + ] + }, + "target": "es2016", + "esModuleInterop": true, + "module": "commonjs", + "experimentalDecorators": true, + "resolveJsonModule": true, // 引入json + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "typeRoots": [ + "./typings/*.d.ts", + "node_modules/@types" + ], + "jsx": "react-jsx" // 这里改成react-jsx,就不需要在tsx文件中手动引入React了 + }, + "include": [ + "./src", + "./core", + "./scripts", + "./typings/*.d.ts", + "interfaces", + "index.tsx" + ] +} \ No newline at end of file diff --git a/apps/cert/.eslintrc.cjs b/apps/cert/.eslintrc.cjs new file mode 100644 index 0000000..4e8a085 --- /dev/null +++ b/apps/cert/.eslintrc.cjs @@ -0,0 +1,29 @@ +/* eslint-env node */ + +module.exports = { + root: true, + env: { browser: true, es2020: true }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:@typescript-eslint/recommended-requiring-type-checking', + 'plugin:react-hooks/recommended', + ], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + project: true, + tsconfigRootDir: __dirname, + }, + plugins: ['react-refresh'], + rules: { + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + '@typescript-eslint/no-non-null-assertion': 'off', + "@typescript-eslint/no-floating-promises": "off", + "@typescript-eslint/no-misused-promises": "off" + }, +} diff --git a/apps/cert/.gitignore b/apps/cert/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/apps/cert/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/apps/cert/core/domain/Rbac/RbacRepository.ts b/apps/cert/core/domain/Rbac/RbacRepository.ts new file mode 100644 index 0000000..f6030c1 --- /dev/null +++ b/apps/cert/core/domain/Rbac/RbacRepository.ts @@ -0,0 +1,59 @@ +import { Apis } from "@@/infra/api"; +import { Role } from "./entities/Role"; +import { Permission } from "./entities/Permission"; +import { User } from "./entities/User"; + +export class RbacRepository { + async saveRole(role: Role) { + const { code } = await Apis.saveRole(role); + return code === "ok"; + } + + async updateRole(role: Role) { + const { code } = await Apis.updateRole(role); + return code === "ok"; + } + + async removeRole(role: Role) { + const { code } = await Apis.removeRole(role); + return code === "ok"; + } + + async findAllRoleWithPermissions() { + const { code, data } = await Apis.findAllRoleWithPermissions(); + return data as { + allPermissions: Permission[]; + roleWithPermissions: Role[]; + }; + } + + async findRolePermissions(id: number) { + const { code, data } = await Apis.findRolePermissions(id); + return data; + } + + async saveRolePermissions(permissionIds: string[], roleId: number) { + const { code } = await Apis.saveRolePermissions(permissionIds, roleId); + return code === "ok"; + } + + async findAllUser() { + const { code, data } = await Apis.findAllUser(); + return data as User[]; + } + + async saveUser(user: User) { + const { code } = await Apis.saveUser(user); + return code === "ok"; + } + + async updateUser(user: Omit & { roles: number[] }) { + const { code } = await Apis.updateUser(user); + return code === "ok"; + } + + async deleteUser(userIds: number[]) { + const { code } = await Apis.deleteUser(userIds); + return code === "ok"; + } +} diff --git a/apps/cert/core/domain/Rbac/RbacService.ts b/apps/cert/core/domain/Rbac/RbacService.ts new file mode 100644 index 0000000..99e0a94 --- /dev/null +++ b/apps/cert/core/domain/Rbac/RbacService.ts @@ -0,0 +1,151 @@ +import { CreateUserFormFields } from "@/modules/User/List/CreateUserForm"; +import { Permission } from "./entities/Permission"; +import { RbacRepository } from "./RbacRepository"; +import { makeAutoObservable } from "mobx"; +import { Role } from "./entities/Role"; +import { User } from "./entities/User"; + +export class RbacService { + roleList: Role[]; + allPermissions: Permission[]; + allRoles: Role[]; + activeRole: Role | undefined; + userList: User[]; + activeUser: User | undefined; + constructor(private rbacRepository: RbacRepository) { + this.roleList = []; + this.allPermissions = []; + this.allRoles = []; + this.userList = []; + makeAutoObservable(this); + } + + /** + * 查询全部用户 + */ + async findAllRoleWithPermissions() { + const { allPermissions, roleWithPermissions } = + await this.rbacRepository.findAllRoleWithPermissions(); + this.allPermissions = allPermissions; + this.roleList = roleWithPermissions; + this.activeRole = roleWithPermissions[0]; + this.allRoles = roleWithPermissions; + return roleWithPermissions; + } + + /** + * 添加角色 + */ + async addRole(role: Role) { + this.roleList = [ + ...this.roleList, + { ...role, isEnabled: true, permissions: [] }, + ]; + return await this.rbacRepository.saveRole(role); + } + + /** + * 删除角色 + */ + async removeRole(role: Role) { + this.roleList = this.roleList.filter((r) => r.id !== role.id); + return await this.rbacRepository.removeRole(role); + } + + /** + * 编辑角色 + */ + async updateRole(role: Role) { + const success = await this.rbacRepository.updateRole(role); + if (success) + this.roleList = this.roleList.map((r) => (r.id === role.id ? role : r)); + return success; + } + + /** + * 查询角色拥有的权限 + * 返回:全部权限、已有权限 + */ + async findRolePermissions(id: number) { + return await this.rbacRepository.findRolePermissions(id); + } + + /** + * 更新某个角色的权限 + * @param {string[]} permissionIds 权限id字符串数组 + * @param {number} roleId 角色id + */ + async updateRolePermissions(permissionIds: string[], roleId: number) { + await this.rbacRepository.saveRolePermissions(permissionIds, roleId); + } + + /** + * 设置当前选中的角色 + */ + setActiveRole(role: Role) { + this.activeRole = this.roleList.find((r) => r.id === role.id); + } + + /** + * 查询全部用户 + */ + async findAllUser() { + const users = await this.rbacRepository.findAllUser(); + this.userList = users; + return users; + } + + /** + * 创建用户 + */ + async saveUser(fields: CreateUserFormFields) { + const { roleIds, username, password, phoneNumber } = fields; + const roleMapping = this.allRoles.map((r) => ({ + alias: r.alias, + description: r.description, + id: r.id, + isEnabled: r.isEnabled, + name: r.name, + })); + const user = { + id: Math.max(...this.userList.map((u) => u.id!)), + roles: roleMapping.filter((r) => roleIds?.includes(r.id!)), + isEnabled: true, + username, + phoneNumber, + createTime: new Date().toLocaleString(), + }; + this.userList = [...this.userList, user]; + return await this.rbacRepository.saveUser({ ...user, password }); + } + + /** + * 修改用户角色、手机号、密码、启用/封禁 + */ + async updateUser(user: User, roleIds: number[]) { + const { password, phoneNumber, isEnabled, roles, id, username } = user; + const success = await this.rbacRepository.updateUser({ + password, + phoneNumber, + isEnabled, + roles: roleIds, + id, + username, + }); + this.userList = this.userList.map((u) => { + if (u.id === id) { + u.phoneNumber = phoneNumber; + u.isEnabled = isEnabled; + u.roles = roles; + } + return u; + }); + return success; + } + + async deleteUser(userIds: number[]) { + const success = await this.rbacRepository.deleteUser(userIds); + this.userList = this.userList.filter((u) => !userIds.includes(u.id!)); + return success; + } +} diff --git a/apps/cert/core/domain/Rbac/entities/Permission.ts b/apps/cert/core/domain/Rbac/entities/Permission.ts new file mode 100644 index 0000000..452a5d0 --- /dev/null +++ b/apps/cert/core/domain/Rbac/entities/Permission.ts @@ -0,0 +1,20 @@ +type PermissionArgs = { + id: number; + name: string; + resources: string[]; + description: string; +}; + +export class Permission { + id: number; + name: string; + resources: string[]; + description: string; + + constructor({ id, name, resources, description }: PermissionArgs) { + this.id = id; + this.name = name; + this.resources = resources; + this.description = description; + } +} diff --git a/apps/cert/core/domain/Rbac/entities/Resource.ts b/apps/cert/core/domain/Rbac/entities/Resource.ts new file mode 100644 index 0000000..69b28c4 --- /dev/null +++ b/apps/cert/core/domain/Rbac/entities/Resource.ts @@ -0,0 +1,6 @@ +import { makeAutoObservable } from "mobx"; +export class Resource { + constructor() { + makeAutoObservable(this); + } +} diff --git a/apps/cert/core/domain/Rbac/entities/Role.ts b/apps/cert/core/domain/Rbac/entities/Role.ts new file mode 100644 index 0000000..1ecb65b --- /dev/null +++ b/apps/cert/core/domain/Rbac/entities/Role.ts @@ -0,0 +1,38 @@ +import { Permission } from "./Permission"; +import { User } from "./User"; + +export class Role { + id?: number; + name: string; + alias: string; + isEnabled?: boolean; + description?: string; + permissions?: Permission[]; + users?: User[]; + + constructor({ + id, + name, + alias, + isEnabled = true, + description, + permissions = [], + users = [], + }: { + id: number; + name: string; + alias: string; + isEnabled: boolean; + description: string; + permissions: Permission[]; + users: User[]; + }) { + this.id = id; + this.name = name; + this.alias = alias; + this.isEnabled = isEnabled; + this.description = description; + this.permissions = permissions; + this.users = users; + } +} diff --git a/apps/cert/core/domain/Rbac/entities/User.ts b/apps/cert/core/domain/Rbac/entities/User.ts new file mode 100644 index 0000000..43d14d1 --- /dev/null +++ b/apps/cert/core/domain/Rbac/entities/User.ts @@ -0,0 +1,32 @@ +import { Role } from "./Role"; + +export class User { + id?: number; + username?: string; + password?: string; + phoneNumber?: string; + createTime?: string; + updateTime?: string; + isEnabled?: boolean; + roles?: Role[]; + + constructor({ + id, + username, + password, + phoneNumber = "", + createTime = "", + updateTime = "", + isEnabled = true, + roles = [], + }: Partial) { + this.id = id!; + this.username = username!; + this.password = password!; + this.phoneNumber = phoneNumber; + this.createTime = createTime; + this.updateTime = updateTime; + this.isEnabled = isEnabled; + this.roles = roles; + } +} diff --git a/apps/cert/core/infra/api/Request.ts b/apps/cert/core/infra/api/Request.ts new file mode 100644 index 0000000..1ff6df4 --- /dev/null +++ b/apps/cert/core/infra/api/Request.ts @@ -0,0 +1,115 @@ +import axios, { + AxiosInstance, + AxiosRequestConfig, + AxiosResponse, + CancelTokenSource, + InternalAxiosRequestConfig, +} from "axios"; + +interface RequestConfig extends InternalAxiosRequestConfig { + onRequestSent?: RequestCallback; +} + +type RequestCallback = (token: string) => void; + +class AxiosRequestInstance { + private instance: AxiosInstance; + private cancelTokenMap: Map; + + constructor() { + this.instance = axios.create(); + this.cancelTokenMap = new Map(); + + // 请求拦截 + this.instance.interceptors.request.use((config: RequestConfig) => { + const token = this.generateToken(); + const source = axios.CancelToken.source(); + this.cancelTokenMap.set(token, source); + + // 生成 traceId 并加入请求头 + const traceId = this.generateTraceId(); + config.headers["x-trace-id"] = traceId; + config.headers["x-request-token"] = token; // 将token加入请求头 + config.cancelToken = source.token; + + if (config.onRequestSent) config.onRequestSent(token); + return config; + }); + + // 响应拦截 + this.instance.interceptors.response.use((response: AxiosResponse) => { + const token = response.headers["x-request-token"]; + this.cancelTokenMap.delete(token); // 完成后删除此token + return response; + }); + } + + // 生成token + private generateToken(): string { + return Math.random().toString(36).substring(2); + } + + // 生成traceId + private generateTraceId(): string { + // 使用你自己的 traceId 生成策略,这里是一个简单的示例 + return Math.random().toString(36).substring(2); + } + + // 取消请求 + public cancelRequest(token: string): void { + const source = this.cancelTokenMap.get(token); + if (source) { + source.cancel("Request canceled, token:" + token); + this.cancelTokenMap.delete(token); + } + } + + // 封装get、post等请求 + public async get( + url: string, + config?: AxiosRequestConfig & { onRequestSent?: RequestCallback } + ): Promise { + const response = await this.instance.get(url, config); + return response.data; + } + + public async post( + url: string, + data?: any, + config?: RequestConfig & { onRequestSent?: RequestCallback } + ): Promise { + const response = await this.instance.post(url, data, config); + return response.data; + } + + public async put( + url: string, + data?: any, + config?: RequestConfig & { onRequestSent?: RequestCallback } + ): Promise { + const response = await this.instance.put(url, data, config); + return response.data; + } + + public async delete( + url: string, + config?: RequestConfig & { onRequestSent?: RequestCallback } + ): Promise { + const response = await this.instance.delete(url, config); + return response.data; + } +} + +export const Request = new AxiosRequestInstance(); + +// 使用方法: +// 1. 发起请求并获取token +// let token: string; +// requestInstance.get("https://api.example.com/data", { +// onRequestSent: (requestToken) => { +// token = requestToken; +// }, +// }); + +// 2. 在需要取消请求的时候取消请求 +// requestInstance.cancelRequest(token); diff --git a/apps/cert/core/infra/api/index.ts b/apps/cert/core/infra/api/index.ts new file mode 100644 index 0000000..e7a9ada --- /dev/null +++ b/apps/cert/core/infra/api/index.ts @@ -0,0 +1,82 @@ +import { Role } from "@@/domain/Rbac/entities/Role"; +import { Request } from "./Request"; +import { User } from "@@/domain/Rbac/entities/User"; + +const PREFIX = "/cert"; + +type ResponseType = Promise<{ + code?: number | string; + data?: unknown; + msg?: string; +}>; + +export const Apis = { + /** + * 创建新角色 + * @param {Role} p + */ + saveRole: (p: Role): ResponseType => + Request.post(PREFIX + "/admin/role/create", p), + + /** + * 编辑角色 + * @param {Role} p + */ + updateRole: (p: Role): ResponseType => + Request.post(PREFIX + "/admin/role/update", p), + + /** + * 删除角色 + */ + removeRole: (p: Role): ResponseType => + Request.post(PREFIX + "/admin/role/remove", p), + + /** + * 获取全部角色权限 + */ + findAllRoleWithPermissions: (): ResponseType => + Request.get(PREFIX + "/admin/find/role/all"), + + /** + * 根据id查询全部的permissions信息 + * @param {number} id 角色Role的id + */ + findRolePermissions: (id: number): ResponseType => + Request.post(PREFIX + "/admin/role/permissions/find", { id }), + + /** + * 更新某个角色的权限 + * @param {string[]} permissionIds 权限id字符串数组 + * @param {number} roleId 角色id + */ + saveRolePermissions: ( + permissionIds: string[], + roleId: number + ): ResponseType => + Request.post(PREFIX + "/admin/role/permissions/update", { + permissionIds, + roleId, + }), + /** + * 查询全部用户 + */ + findAllUser: (): ResponseType => Request.get(PREFIX + "/admin/user/find/all"), + + /** + * 创建用户 + */ + saveUser: (user: User): ResponseType => + Request.post(PREFIX + "/admin/user/create", user), + /** + * 修改用户 + */ + updateUser: (user: Omit & { roles: number[] }): ResponseType => + Request.post(PREFIX + "/admin/user/update", user), + + /** + * 删除用户 + * @param {number[]} userIds 用户id数组 + */ + deleteUser: (userIds: number[]): ResponseType => + Request.post(PREFIX + "/admin/user/delete", userIds), +}; diff --git a/apps/cert/index.html b/apps/cert/index.html new file mode 100644 index 0000000..267c692 --- /dev/null +++ b/apps/cert/index.html @@ -0,0 +1,13 @@ + + + + + + + 认证中心 + + +
+ + + diff --git a/apps/cert/package.json b/apps/cert/package.json new file mode 100644 index 0000000..37b0804 --- /dev/null +++ b/apps/cert/package.json @@ -0,0 +1,38 @@ +{ + "name": "@tavi/cert-web", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router": "6.14.2", + "react-router-dom": "6.14.2", + "antd": "5.8.2", + "axios": "1.4.0", + "react-icons": "4.10.1", + "mobx": "6.9.0", + "mobx-react-lite": "3.4.3", + "@ant-design/icons": "5.2.5" + }, + "devDependencies": { + "@types/react": "^18.2.14", + "@types/react-dom": "^18.2.6", + "@types/react-router": "5.1.20", + "@types/react-router-dom": "5.3.3", + "@typescript-eslint/eslint-plugin": "^5.61.0", + "@typescript-eslint/parser": "^5.61.0", + "@vitejs/plugin-react": "^4.0.1", + "eslint": "^8.44.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.1", + "typescript": "^5.0.2", + "vite": "^4.4.0" + } +} \ No newline at end of file diff --git a/apps/cert/public/favico.svg b/apps/cert/public/favico.svg new file mode 100644 index 0000000..28c9f3f --- /dev/null +++ b/apps/cert/public/favico.svg @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/apps/cert/public/wave.svg b/apps/cert/public/wave.svg new file mode 100644 index 0000000..4352944 --- /dev/null +++ b/apps/cert/public/wave.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/cert/src/App.tsx b/apps/cert/src/App.tsx new file mode 100644 index 0000000..6390f45 --- /dev/null +++ b/apps/cert/src/App.tsx @@ -0,0 +1,17 @@ +import { BrowserRouter } from "react-router-dom"; +import { AuthProvider } from "./context/auth"; +import { RouterElements } from "./router"; +import { ConfigProvider } from "antd"; +import { theme } from "./constants"; + +export const App = () => { + return ( + + + + + + + + ); +}; diff --git a/apps/cert/src/assets/react.svg b/apps/cert/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/apps/cert/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/cert/src/components/Layout/index.less b/apps/cert/src/components/Layout/index.less new file mode 100644 index 0000000..2db41be --- /dev/null +++ b/apps/cert/src/components/Layout/index.less @@ -0,0 +1,16 @@ +.layout-container { + >header { + position: relative; + z-index: 10; + max-width: 100%; + background: #ffffff; + height: 60px; + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.03), 0 1px 6px -1px rgba(0, 0, 0, 0.02), 0 2px 4px 0 rgba(0, 0, 0, 0.02); + } + + >div { + display: grid; + grid-template-columns: 1fr 6fr; + height: calc(100vh - 60px); + } +} \ No newline at end of file diff --git a/apps/cert/src/components/Layout/index.tsx b/apps/cert/src/components/Layout/index.tsx new file mode 100644 index 0000000..9152f6f --- /dev/null +++ b/apps/cert/src/components/Layout/index.tsx @@ -0,0 +1,84 @@ +import { Menu, MenuProps } from "antd"; +import { Outlet, useLocation, useNavigate } from "react-router"; +import { + AiFillSetting, + AiOutlineApartment, + AiOutlineApi, + AiOutlineNodeIndex, + AiOutlineUser, +} from "react-icons/ai"; +import "./index.less"; +import { useEffect, useState } from "react"; + +interface LayoutProps { + children?: JSX.Element; +} + +type MenuItem = Required["items"][number]; + +function getItem( + label: React.ReactNode, + key: React.Key, + icon?: React.ReactNode, + children?: MenuItem[], + type?: "group" +): MenuItem { + return { + key, + icon, + children, + label, + type, + } as MenuItem; +} + +const items: MenuItem[] = [ + getItem("配置", "configuration", , [ + getItem( + "基本", + "g1", + null, + [ + getItem("角色", "/configuration/role", ), + getItem("资源权限", "/configuration/permission", ), + ], + "group" + ), + getItem( + "用户", + "g2", + null, + [getItem("账户管理", "/user/management", )], + "group" + ), + ]), +]; + +export const Layout = (props: LayoutProps) => { + const navigate = useNavigate(); + const location = useLocation(); + const [selectedKeys, setSelectedKeys] = useState([location.pathname]); + + useEffect(() => setSelectedKeys([location.pathname]), [location.pathname]); + + return ( +
+
{location.pathname}
+
+ +
+ +
+
+
+ ); +}; diff --git a/apps/cert/src/constants.ts b/apps/cert/src/constants.ts new file mode 100644 index 0000000..1439c6b --- /dev/null +++ b/apps/cert/src/constants.ts @@ -0,0 +1,15 @@ +import { ThemeConfig } from "antd"; + +export const defaultDocumentTitle = "认证中心"; + +export const AuthFailedReplacePath = "/login"; + +/** + * token优先级低于局部ConfigProvider + */ +export const theme: ThemeConfig = { + token: { + // colorPrimary: "#2e97d1", + borderRadius: 2, + }, +}; diff --git a/apps/cert/src/context/auth.tsx b/apps/cert/src/context/auth.tsx new file mode 100644 index 0000000..6d8d1c2 --- /dev/null +++ b/apps/cert/src/context/auth.tsx @@ -0,0 +1,32 @@ +import { createContext, useState } from "react"; + +type Auth = { + isLoggedIn: boolean; +}; + +type AuthContextType = { + auth: Auth; + setAuth: React.Dispatch>; +}; + +const defaultAuth: AuthContextType["auth"] = { isLoggedIn: false }; +const defaultSetAuth: AuthContextType["setAuth"] = () => {}; + +export const AuthContext = createContext({ + auth: defaultAuth, + setAuth: defaultSetAuth, +}); + +interface AuthProviderProps { + children?: JSX.Element; +} + +export const AuthProvider = (props: AuthProviderProps) => { + const [auth, setAuth] = useState({ isLoggedIn: false }); + + return ( + + {props.children} + + ); +}; diff --git a/apps/cert/src/context/domainService.tsx b/apps/cert/src/context/domainService.tsx new file mode 100644 index 0000000..54f073e --- /dev/null +++ b/apps/cert/src/context/domainService.tsx @@ -0,0 +1,25 @@ +import { RbacRepository } from "@@/domain/Rbac/RbacRepository"; +import { RbacService } from "@@/domain/Rbac/RbacService"; +import { createContext } from "react"; + +export type Services = { + rbacDomainService: RbacService; +}; + +const defaultServiceMap = { + rbacDomainService: new RbacService(new RbacRepository()), +}; + +export const DomainServiceContext = createContext(defaultServiceMap); + +interface DomainServiceProviderProps { + children?: JSX.Element; +} + +export const DomainServiceProvider = (props: DomainServiceProviderProps) => { + return ( + + {props.children} + + ); +}; diff --git a/apps/cert/src/hook/useAuth.tsx b/apps/cert/src/hook/useAuth.tsx new file mode 100644 index 0000000..1ba2569 --- /dev/null +++ b/apps/cert/src/hook/useAuth.tsx @@ -0,0 +1,4 @@ +import { useContext } from "react"; +import { AuthContext } from "../context/auth"; + +export const useAuth = () => useContext(AuthContext); diff --git a/apps/cert/src/hook/useDomain.tsx b/apps/cert/src/hook/useDomain.tsx new file mode 100644 index 0000000..a3ed4ae --- /dev/null +++ b/apps/cert/src/hook/useDomain.tsx @@ -0,0 +1,10 @@ +import { DomainServiceContext, Services } from "@/context/domainService"; +import { useContext } from "react"; + +export const useDomain = (): Services => { + const context = useContext(DomainServiceContext); + if (context === null) { + throw new Error("useDomain ctx丢失,必须在domainService上下文中使用"); + } + return context; +}; diff --git a/apps/cert/src/main.tsx b/apps/cert/src/main.tsx new file mode 100644 index 0000000..7f0238e --- /dev/null +++ b/apps/cert/src/main.tsx @@ -0,0 +1,5 @@ +import ReactDOM from "react-dom/client"; +import { App } from "./App"; +import "@/styles/app.less"; + +ReactDOM.createRoot(document.getElementById("root")!).render(); diff --git a/apps/cert/src/modules/Configuration/Permission/index.tsx b/apps/cert/src/modules/Configuration/Permission/index.tsx new file mode 100644 index 0000000..d6b52af --- /dev/null +++ b/apps/cert/src/modules/Configuration/Permission/index.tsx @@ -0,0 +1,113 @@ +import { + App, + Button, + Card, + Form, + Input, + Modal, + Select, + Space, + Table, + TableColumnsType, + Typography, +} from "antd"; +import { ColumnsType } from "antd/es/table"; +import axios from "axios"; +import { useEffect, useState } from "react"; +const { Text } = Typography; + +interface PermissionProps { + children?: JSX.Element; +} + +interface PermissionItem { + id: string; + name: string; + description?: string; + resources: string[]; +} + +interface RbacConfigurationItem { + moduleName: string; + updateTime?: string; + permissions: PermissionItem[]; +} + +export const Permission = (props: PermissionProps) => { + const [dataSource, setDatasource] = useState([]); + + useEffect(() => { + axios.get("/cert/admin/find/permission/resource").then((res) => { + setDatasource(res.data.data); + }); + }, []); + + const columnsOuter: ColumnsType = [ + { + title: "模块", + dataIndex: "moduleName", + key: "moduleName", + }, + { + title: "更新时间", + dataIndex: "updateTime", + key: "updateTime", + }, + ]; + + const expandedRowRender = (record: any) => { + const columnsInner: TableColumnsType = [ + { + title: "标识", + dataIndex: "id", + key: "id", + }, + { + title: "权限", + dataIndex: "name", + key: "name", + }, + { + title: "映射资源", + dataIndex: "resources", + key: "resources", + render: (_, record) => ( + + {record.resources.map((i) => ( + + {i} + + ))} + + ), + }, + { + title: "描述", + dataIndex: "description", + key: "description", + render: (_, record) => ( + {record.description} + ), + }, + ]; + return ( +
r.id} + dataSource={record.permissions} + pagination={false} + /> + ); + }; + + return ( +
+
r.moduleName} + dataSource={dataSource} + expandable={{ expandedRowRender, expandRowByClick: true }} + /> + + ); +}; diff --git a/apps/cert/src/modules/Configuration/Role/components/EditTab/RoleBaseInfo.tsx b/apps/cert/src/modules/Configuration/Role/components/EditTab/RoleBaseInfo.tsx new file mode 100644 index 0000000..3ba8bdc --- /dev/null +++ b/apps/cert/src/modules/Configuration/Role/components/EditTab/RoleBaseInfo.tsx @@ -0,0 +1,138 @@ +import { + Button, + Divider, + Form, + Input, + Modal, + Popconfirm, + Space, + Typography, +} from "antd"; +import { + StopOutlined, + DeleteOutlined, + CheckOutlined, + EditOutlined, +} from "@ant-design/icons"; +import { useDomain } from "@/hook/useDomain"; +import { observer } from "mobx-react-lite"; +import { useState } from "react"; +const { Text } = Typography; + +export const RoleBaseInfo = observer(() => { + const { rbacDomainService } = useDomain(); + const { activeRole } = rbacDomainService; + const [isModalOpen, setIsModalOpen] = useState(false); + const [form] = Form.useForm(); + + const onUpdateRole = (isEnabled: boolean) => { + const { activeRole } = rbacDomainService; + if (activeRole) { + activeRole.isEnabled = isEnabled; + rbacDomainService.updateRole(activeRole); + } + }; + + const onRoleDelete = () => { + const { activeRole } = rbacDomainService; + if (activeRole) rbacDomainService.removeRole(activeRole); + }; + + const onEditRoleName = async () => { + try { + await form.validateFields(); + const { alias } = (await form.getFieldsValue()) as { alias: string }; + if (activeRole) { + activeRole.alias = alias; + rbacDomainService.updateRole(activeRole); + setIsModalOpen(false); + } + } catch (error) { + console.log(error); + } + }; + + return ( + activeRole && ( +
+ + {activeRole.alias} + + {activeRole.isEnabled ? ( + + onUpdateRole(false)} + okText="确定" + cancelText="取消" + > + + + + ) : ( + onUpdateRole(true)} + okText="确定" + cancelText="取消" + > + + + )} + + setIsModalOpen(false)} + cancelText="取消" + okText="确认" + > +
+ + + + +
+ onRoleDelete()} + okText="确定" + cancelText="取消" + > + + +
+

+ + {activeRole.description} + +

+
+ ) + ); +}); diff --git a/apps/cert/src/modules/Configuration/Role/components/EditTab/RoleUsersTable.tsx b/apps/cert/src/modules/Configuration/Role/components/EditTab/RoleUsersTable.tsx new file mode 100644 index 0000000..6bc304e --- /dev/null +++ b/apps/cert/src/modules/Configuration/Role/components/EditTab/RoleUsersTable.tsx @@ -0,0 +1,44 @@ +import { CheckOutlined, StopOutlined } from "@ant-design/icons"; +import { RbacService } from "@@/domain/Rbac/RbacService"; +import { User } from "@@/domain/Rbac/entities/User"; +import { observer } from "mobx-react-lite"; +import { Table } from "antd"; + +const columns = [ + { + title: "#", + dataIndex: "id", + key: "id", + }, + { + title: "用户名", + dataIndex: "username", + key: "username", + }, + { + title: "手机号", + dataIndex: "phoneNumber", + key: "username", + }, + { + title: "状态", + dataIndex: "isEnabled", + key: "isEnabled", + render: (_: unknown, record: User) => + record.isEnabled ? ( + + ) : ( + + ), + } +]; + +export const RoleUsersTable: React.FC<{ domainService: RbacService }> = + observer(({ domainService }) => { + const { activeRole } = domainService; + return ( + activeRole?.users && ( +
+ ) + ); + }); diff --git a/apps/cert/src/modules/Configuration/Role/components/EditTab/index.tsx b/apps/cert/src/modules/Configuration/Role/components/EditTab/index.tsx new file mode 100644 index 0000000..9ad79d2 --- /dev/null +++ b/apps/cert/src/modules/Configuration/Role/components/EditTab/index.tsx @@ -0,0 +1,44 @@ +import { CheckboxValueType } from "antd/es/checkbox/Group"; +import { RbacService } from "@@/domain/Rbac/RbacService"; +import { Checkbox, Tabs, TabsProps } from "antd"; +import { useDomain } from "@/hook/useDomain"; +import { observer } from "mobx-react-lite"; +import { RoleUsersTable } from "./RoleUsersTable"; + +export const EditTab = () => { + const { rbacDomainService } = useDomain(); + + const CheckOptionsComponent: React.FC<{ domainService: RbacService }> = + observer(({ domainService }) => { + const { allPermissions, activeRole } = domainService; + return ( + p.name)} + value={activeRole?.permissions?.map((p) => p.name) ?? []} + onChange={(list: CheckboxValueType[]) => { + if (activeRole) { + activeRole.permissions = allPermissions.filter((p) => + list.includes(p.name) + ); + domainService.updateRole(activeRole); + } + }} + /> + ); + }); + + const items: TabsProps["items"] = [ + { + key: "1", + label: "成员", + children: , + }, + { + key: "2", + label: "角色权限", + children: , + }, + ]; + + return ; +}; diff --git a/apps/cert/src/modules/Configuration/Role/components/RoleAddModal/index.tsx b/apps/cert/src/modules/Configuration/Role/components/RoleAddModal/index.tsx new file mode 100644 index 0000000..2ff5795 --- /dev/null +++ b/apps/cert/src/modules/Configuration/Role/components/RoleAddModal/index.tsx @@ -0,0 +1,83 @@ +import { Form, Input, Modal, message } from "antd"; +import { useState } from "react"; + +export type fieldsType = { + name: string; + alias: string; + description?: string; +}; + +interface RoleAddModalProps { + onOk?: (fields: fieldsType) => Promise | void; +} + +export const useRoleAddModal = () => { + const [form] = Form.useForm(); + const [messageApi, contextHolder] = message.useMessage(); + const [modalVisible, setModalVisible] = useState(false); + + const RoleAddModal = (props: RoleAddModalProps) => { + /** + * 确认 + */ + const onOkHandler = async () => { + try { + await form.validateFields(); + const fields = form.getFieldsValue() as fieldsType; + props.onOk?.(fields); + } catch (error) { + console.log(error); + } + }; + + return ( + onOkHandler()} + cancelText="取消" + onCancel={() => setModalVisible(false)} + title="新增角色" + > +
+ + + + + + + + + + +
+ ); + }; + + return { setModalVisible, messageApi, contextHolder, RoleAddModal }; +}; diff --git a/apps/cert/src/modules/Configuration/Role/components/RoleList/index.tsx b/apps/cert/src/modules/Configuration/Role/components/RoleList/index.tsx new file mode 100644 index 0000000..313f420 --- /dev/null +++ b/apps/cert/src/modules/Configuration/Role/components/RoleList/index.tsx @@ -0,0 +1,47 @@ +import { CheckOutlined, StopOutlined } from "@ant-design/icons"; +import { Menu, MenuProps } from "antd"; + +export interface RoleItem { + id: number; + name: string; + alias: string; + isEnabled: boolean; + description: string; + active: boolean; +} + +interface RoleListProps { + children?: JSX.Element; + dataSource: RoleItem[]; + onClick?: (item: RoleItem) => void; +} + +type MenuItem = Required["items"][number]; + +export const RoleList = (props: RoleListProps) => { + const { dataSource } = props; + const onClickRoleItem = ({ key }: { key: string }) => { + const item = dataSource.find((i) => i.id === Number(key)) as RoleItem; + props.onClick?.(item); + }; + + const items: MenuItem[] = dataSource.map((item: RoleItem) => ({ + label: item.alias, + key: item.id, + icon: item.isEnabled ? ( + + ) : ( + + ), + })); + + return ( + + ); +}; diff --git a/apps/cert/src/modules/Configuration/Role/index.less b/apps/cert/src/modules/Configuration/Role/index.less new file mode 100644 index 0000000..d44efb1 --- /dev/null +++ b/apps/cert/src/modules/Configuration/Role/index.less @@ -0,0 +1,28 @@ +.role-container { + display: grid; + grid-template-columns: 1fr 4fr; + height: 100%; + + aside { + padding: 20px 20px 0 20px; + border-right: 1px solid rgba(5, 5, 5, 0.06); + + ul { + list-style: none; + margin: 0; + padding: 0; + + li { + margin-bottom: 10px; + + a { + cursor: pointer; + } + } + } + } + + >main { + padding: 20px 20px 0 20px; + } +} \ No newline at end of file diff --git a/apps/cert/src/modules/Configuration/Role/index.tsx b/apps/cert/src/modules/Configuration/Role/index.tsx new file mode 100644 index 0000000..c503fdd --- /dev/null +++ b/apps/cert/src/modules/Configuration/Role/index.tsx @@ -0,0 +1,71 @@ +import { fieldsType, useRoleAddModal } from "./components/RoleAddModal"; +import { RoleBaseInfo } from "./components/EditTab/RoleBaseInfo"; +import { RoleItem, RoleList } from "./components/RoleList"; +import { RbacService } from "@@/domain/Rbac/RbacService"; +import { EditTab } from "./components/EditTab"; +import { useDomain } from "@/hook/useDomain"; +import { observer } from "mobx-react-lite"; +import { Button, Divider } from "antd"; +import { useEffect } from "react"; +import "./index.less"; +interface RoleProps { + children?: JSX.Element; +} + +export const Role = (props: RoleProps) => { + const { rbacDomainService } = useDomain(); + const { RoleAddModal, setModalVisible, messageApi, contextHolder } = + useRoleAddModal(); + + useEffect(() => { + rbacDomainService.findAllRoleWithPermissions(); + }, [rbacDomainService]); + + const clickRoleItemHandler = (role: RoleItem) => + rbacDomainService.setActiveRole(role); + + const onModalConfirm = async (fields: fieldsType) => { + setModalVisible(false); + const ok = await rbacDomainService.addRole({ ...fields }); + messageApi.info(ok ? "ok" : "failed"); + }; + + const RoleListComponent: React.FC<{ domainService: RbacService }> = observer( + ({ domainService }) => { + const { activeRole } = domainService; + const dataSource = domainService.roleList.map((r) => ({ + ...r, + active: r.id === activeRole?.id, + })) as RoleItem[]; + return ( + + ); + } + ); + + return ( +
+ +
+ + +
+
+ ); +}; diff --git a/apps/cert/src/modules/Login/index.less b/apps/cert/src/modules/Login/index.less new file mode 100644 index 0000000..67b8dab --- /dev/null +++ b/apps/cert/src/modules/Login/index.less @@ -0,0 +1,7 @@ +.login-container { + display: flex; + justify-content: center; + align-items: center; + background-size: cover; + height: 100vh; +} \ No newline at end of file diff --git a/apps/cert/src/modules/Login/index.tsx b/apps/cert/src/modules/Login/index.tsx new file mode 100644 index 0000000..435a8a0 --- /dev/null +++ b/apps/cert/src/modules/Login/index.tsx @@ -0,0 +1,57 @@ +import { Button, Checkbox, Form, Input } from "antd"; +import "./index.less"; +import axios from "axios"; + +interface LoginProps { + children?: JSX.Element; +} + +export const Login = (props: LoginProps) => { + const onFinish = (values: any) => { + const { remember, ...rest } = values; + console.log("Success:", rest); + axios.post("/cert/admin/sign", rest); + }; + + const onFinishFailed = (errorInfo: any) => { + console.log("Failed:", errorInfo); + }; + + return ( +
+
+ + + + + + + + + + + + +
+ ); +}; diff --git a/apps/cert/src/modules/User/List/CreateUserForm.tsx b/apps/cert/src/modules/User/List/CreateUserForm.tsx new file mode 100644 index 0000000..3694a1b --- /dev/null +++ b/apps/cert/src/modules/User/List/CreateUserForm.tsx @@ -0,0 +1,73 @@ +import { Button, Form, Input, Select, message } from "antd"; +import { useDomain } from "@/hook/useDomain"; +import { Observer } from "mobx-react-lite"; +import { useEffect } from "react"; + +export interface CreateUserFormFields { + roleIds: number[]; + username: string; + password: string; + phoneNumber: string; +} + +interface CreateUserFormProps { + children?: JSX.Element; +} + +export const CreateUserForm = (props: CreateUserFormProps) => { + const [form] = Form.useForm(); + const { rbacDomainService } = useDomain(); + const [messageApi, contextHolder] = message.useMessage(); + + useEffect(() => { + rbacDomainService.findAllRoleWithPermissions(); + }, [rbacDomainService]); + + const onConfirmCreateUser = async (fields: CreateUserFormFields) => { + const { roleIds, username, password, phoneNumber } = fields; + const success = await rbacDomainService.saveUser({ + roleIds, + username, + password, + phoneNumber, + }); + if (success) messageApi.success(`用户: ${username} 创建成功`); + }; + + return ( +
+ {contextHolder} + + {() => ( +
+ + + + + + + + + + + + + + + + +
r.id!} + rowSelection={rowSelection} + dataSource={domainService.userList} + columns={columns} + /> + + ); + } +); diff --git a/apps/cert/src/modules/User/List/index.tsx b/apps/cert/src/modules/User/List/index.tsx new file mode 100644 index 0000000..a56eb66 --- /dev/null +++ b/apps/cert/src/modules/User/List/index.tsx @@ -0,0 +1,85 @@ +import { UserEditForm, useUserEditModal } from "./UserEditModal"; +import { User } from "@@/domain/Rbac/entities/User"; +import { CreateUserForm } from "./CreateUserForm"; +import { useEffect, useState } from "react"; +import { UserTableList } from "./UserTable"; +import { useDomain } from "@/hook/useDomain"; +import { message } from "antd"; +import { useNavigate } from "react-router"; + +interface UserManagementProps { + children?: JSX.Element; +} + +export const UserManagement = (props: UserManagementProps) => { + const { UserEditModal, setModalVisible } = useUserEditModal(); + const [messageApi, contextHolder] = message.useMessage(); + const navigate = useNavigate(); + + const [editUser, setEditUser] = useState(); + const { rbacDomainService } = useDomain(); + const { allRoles } = rbacDomainService; + const rolesForSelectOptions = allRoles.map((r) => ({ + value: r.id!, + label: r.alias, + })); + + useEffect(() => { + rbacDomainService.findAllUser(); + }, [rbacDomainService]); + + const onClickUserEditHandler = (user: User) => { + setEditUser(user); + setModalVisible(true); + }; + + const onUserEditConfirmHandler = async (form: UserEditForm) => { + const { roleIds, password, phoneNumber, isEnabled } = form; + const roles = allRoles.filter((r) => roleIds.includes(r.id!)); + const { id, username } = editUser!; + const user = { + password, + phoneNumber, + isEnabled, + roles, + id, + username, + }; + await rbacDomainService.updateUser(user, roleIds); + setModalVisible(false); + setEditUser(undefined); + }; + + const onClickUserDeleteHandler = async (userIds: React.Key[]) => { + const ids = userIds.map((id) => Number(id)); + const success = await rbacDomainService.deleteUser(ids); + if (success) messageApi.success(`共删除${userIds.length}个用户`); + }; + + const onClickLogViewHandler = (user: User) => { + const { id, username, roles } = user; + const hasRoles = roles?.map((r) => r.alias); + const state = { id, username, hasRoles }; + navigate("/user/audit", { state }); + }; + + return ( +
+ {contextHolder} + + + {editUser && ( + + )} +
+ ); +}; diff --git a/apps/cert/src/modules/User/Logger/LogTable.tsx b/apps/cert/src/modules/User/Logger/LogTable.tsx new file mode 100644 index 0000000..c7e3782 --- /dev/null +++ b/apps/cert/src/modules/User/Logger/LogTable.tsx @@ -0,0 +1,7 @@ +interface LogoTableProps { + children?: JSX.Element; +} + +export const LogoTable = (props: LogoTableProps) => { + return
LogoTable
; +}; diff --git a/apps/cert/src/modules/User/Logger/index.tsx b/apps/cert/src/modules/User/Logger/index.tsx new file mode 100644 index 0000000..118dfa6 --- /dev/null +++ b/apps/cert/src/modules/User/Logger/index.tsx @@ -0,0 +1,24 @@ +import { useLocation } from "react-router"; +import { LogoTable } from "./LogTable"; + +interface LoggerProps { + children?: JSX.Element; +} +interface StateType { + id: string; + username: string; + hasRoles: string[]; +} + +export const Logger = (props: LoggerProps) => { + const location = useLocation(); + const { id, username, hasRoles } = location.state as StateType; + return ( +
+

+ {id},{username},{hasRoles} +

+ +
+ ); +}; diff --git a/apps/cert/src/modules/User/Management/UserTable.tsx b/apps/cert/src/modules/User/Management/UserTable.tsx new file mode 100644 index 0000000..0f6c276 --- /dev/null +++ b/apps/cert/src/modules/User/Management/UserTable.tsx @@ -0,0 +1,117 @@ +import { CheckOutlined, EditOutlined, StopOutlined } from "@ant-design/icons"; +import { User } from "@@/domain/Rbac/entities/User"; +import { Button, Popconfirm, Space, Table, Tag } from "antd"; +import { ColumnsType } from "antd/es/table"; +import { observer } from "mobx-react-lite"; +import { RbacService } from "@@/domain/Rbac/RbacService"; +import { useState } from "react"; + +interface UserTableProps { + domainService: RbacService; + onClickEdit?: (record: any) => void; + onDelete?: (rowKeys: React.Key[]) => void; +} + +export const UserTableList: React.FC = observer( + ({ domainService, onClickEdit, onDelete }) => { + const columns: ColumnsType = [ + { + key: "id", + dataIndex: "id", + title: "#", + }, + { + key: "isEnabled", + title: "可用", + render: (_, record: User) => { + return record.isEnabled ? ( + + ) : ( + + ); + }, + }, + { + key: "username", + dataIndex: "username", + title: "用户名", + }, + { + key: "role", + title: "角色", + render: (_, record: User) => { + return record.roles?.map((i) => {i.alias}); + }, + }, + { + key: "phoneNumber", + dataIndex: "phoneNumber", + title: "手机号", + }, + { + key: "createTime", + dataIndex: "createTime", + title: "创建时间", + render: (_, record) => { + const formateDate = new Date( + record.createTime ?? "" + ).toLocaleString(); + return {formateDate}; + }, + defaultSortOrder: "descend", + }, + { + key: "editUser", + title: "编辑用户", + render: (_, record) => { + return ( + + + + )} + + +
r.id!} + rowSelection={rowSelection} + dataSource={domainService.userList} + columns={columns} + /> + + ); + } +); diff --git a/apps/cert/src/router/AuthGuard.tsx b/apps/cert/src/router/AuthGuard.tsx new file mode 100644 index 0000000..3114437 --- /dev/null +++ b/apps/cert/src/router/AuthGuard.tsx @@ -0,0 +1,32 @@ +import { AuthFailedReplacePath, defaultDocumentTitle } from "@/constants"; +import { Navigate, useLocation } from "react-router-dom"; +import { useAuth } from "../hook/useAuth"; +import { useEffect } from "react"; + +interface GuardProps { + element: JSX.Element; + auth?: boolean; + title?: string; +} + +/** + * 守卫 + */ +export const Guard = (props: GuardProps) => { + const { auth } = useAuth(); + const location = useLocation(); + + useEffect(() => { + document.title = props?.title ?? defaultDocumentTitle; + }, [location.pathname]); + + return props.auth ? ( + auth.isLoggedIn ? ( + props.element + ) : ( + + ) + ) : ( + props.element + ); +}; diff --git a/apps/cert/src/router/index.tsx b/apps/cert/src/router/index.tsx new file mode 100644 index 0000000..cf43e0e --- /dev/null +++ b/apps/cert/src/router/index.tsx @@ -0,0 +1,4 @@ +import { useRoutes } from "react-router"; +import { routesConfig } from "./router.config"; + +export const RouterElements = () => useRoutes(routesConfig); diff --git a/apps/cert/src/router/router.config.tsx b/apps/cert/src/router/router.config.tsx new file mode 100644 index 0000000..708fe5a --- /dev/null +++ b/apps/cert/src/router/router.config.tsx @@ -0,0 +1,58 @@ +import { Layout } from "@/components/Layout"; +import { Login } from "@/modules/Login"; +import { Navigate, RouteObject } from "react-router"; +import { Guard } from "./AuthGuard"; +import { Permission } from "@/modules/Configuration/Permission"; +import { Role } from "@/modules/Configuration/Role"; +import { UserManagement } from "@/modules/User/List"; +import { Logger } from "@/modules/User/Logger"; + +export const routesConfig: RouteObject[] = [ + { + path: "login", + element: } title="登录" />, + }, + { + path: "/", + element: , + children: [ + { path: "/", element: }, + // { + // path: "aorta", + // element: } title="aorta" />, + // }, + // { + // path: "dmp/:id", + // element: } title="dmp" auth />, + // }, + { + path: "configuration", + children: [ + { + path: "role", + element: } title="角色 - 认证中心" />, + }, + { + path: "permission", + element: } title="权限 - 认证中心" />, + }, + ], + }, + { + path: "user", + children: [ + { + path: "management", + element: ( + } title="用户管理 - 认证中心" /> + ), + }, + { + path: "audit", + element: } title="用户日志 - 认证中心" />, + }, + ], + }, + ], + }, +]; diff --git a/apps/cert/src/styles/app.less b/apps/cert/src/styles/app.less new file mode 100644 index 0000000..14dab9e --- /dev/null +++ b/apps/cert/src/styles/app.less @@ -0,0 +1,10 @@ +* { + box-sizing: border-box; +} + +html, +body { + margin: 0; + padding: 0; + font-size: 14px; +} \ No newline at end of file diff --git a/apps/cert/src/vite-env.d.ts b/apps/cert/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/apps/cert/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/apps/cert/tsconfig.json b/apps/cert/tsconfig.json new file mode 100644 index 0000000..492be18 --- /dev/null +++ b/apps/cert/tsconfig.json @@ -0,0 +1,43 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": [ + "src/*" + ], + "@@/*": [ + "core/*" + ] + }, + "target": "ES2020", + "useDefineForClassFields": true, + "lib": [ + "ES2020", + "DOM", + "DOM.Iterable" + ], + "module": "ESNext", + "skipLibCheck": true, + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": [ + "src", + "./core", + ], + "references": [ + { + "path": "./tsconfig.node.json" + } + ] +} \ No newline at end of file diff --git a/apps/cert/tsconfig.node.json b/apps/cert/tsconfig.node.json new file mode 100644 index 0000000..42872c5 --- /dev/null +++ b/apps/cert/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/apps/cert/vite.config.ts b/apps/cert/vite.config.ts new file mode 100644 index 0000000..9d5d7f5 --- /dev/null +++ b/apps/cert/vite.config.ts @@ -0,0 +1,23 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; +import { resolve } from "path"; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + "@": resolve(__dirname, "src"), + "@@": resolve(__dirname, "core"), + }, + }, + server: { + port: 5173, + proxy: { + "/cert": { + target: "http://localhost:12144", + changeOrigin: true, + }, + }, + }, +}); diff --git a/apps/dmp/.eslintrc.cjs b/apps/dmp/.eslintrc.cjs new file mode 100644 index 0000000..4e8a085 --- /dev/null +++ b/apps/dmp/.eslintrc.cjs @@ -0,0 +1,29 @@ +/* eslint-env node */ + +module.exports = { + root: true, + env: { browser: true, es2020: true }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:@typescript-eslint/recommended-requiring-type-checking', + 'plugin:react-hooks/recommended', + ], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + project: true, + tsconfigRootDir: __dirname, + }, + plugins: ['react-refresh'], + rules: { + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + '@typescript-eslint/no-non-null-assertion': 'off', + "@typescript-eslint/no-floating-promises": "off", + "@typescript-eslint/no-misused-promises": "off" + }, +} diff --git a/apps/dmp/.gitignore b/apps/dmp/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/apps/dmp/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/apps/dmp/core/domain/Dicom/DicomRepository.ts b/apps/dmp/core/domain/Dicom/DicomRepository.ts new file mode 100644 index 0000000..2af6036 --- /dev/null +++ b/apps/dmp/core/domain/Dicom/DicomRepository.ts @@ -0,0 +1,13 @@ +import { Apis, ExistInPacsDTO } from "@@/infra/api"; + +export class DicomRepository { + async upload2Pacs(dcmFile: File) { + const formdata = new FormData(); + formdata.append("file", dcmFile); + return Apis.upload2Pacs(formdata); + } + + async existInPacs(p: ExistInPacsDTO) { + return Apis.existInPacs(p); + } +} diff --git a/apps/dmp/core/domain/Dicom/DicomService.ts b/apps/dmp/core/domain/Dicom/DicomService.ts new file mode 100644 index 0000000..7dd5de8 --- /dev/null +++ b/apps/dmp/core/domain/Dicom/DicomService.ts @@ -0,0 +1,14 @@ +import { ExistInPacsDTO } from "@@/infra/api"; +import { DicomRepository } from "./DicomRepository"; + +export class DicomService { + constructor(private dicomRepository: DicomRepository) {} + + async upload2Pacs(dcmFile: File) { + return await this.dicomRepository.upload2Pacs(dcmFile); + } + + async existInPacs(p: ExistInPacsDTO) { + return await this.dicomRepository.existInPacs(p); + } +} diff --git a/apps/dmp/core/domain/User/UserRepository.ts b/apps/dmp/core/domain/User/UserRepository.ts new file mode 100644 index 0000000..1ffd98d --- /dev/null +++ b/apps/dmp/core/domain/User/UserRepository.ts @@ -0,0 +1,23 @@ +import { Apis } from "@@/infra/api"; +import { User } from "./entities/User"; + +export class UserRepository { + async authLogin(user: Pick) { + return await Apis.signIn(user); + } + + async userAuth() { + return (await Apis.userAuth()) as { + data: { + payload: any; + tokenValid: boolean; + }; + msg: string; + code: number; + }; + } + + async getDmpAnnotators() { + return await Apis.getDmpAnnotators(); + } +} diff --git a/apps/dmp/core/domain/User/UserService.ts b/apps/dmp/core/domain/User/UserService.ts new file mode 100644 index 0000000..4efaa08 --- /dev/null +++ b/apps/dmp/core/domain/User/UserService.ts @@ -0,0 +1,50 @@ +import { makeAutoObservable } from "mobx"; +import { UserRepository } from "./UserRepository"; +import { User } from "./entities/User"; +import { RouteObject } from "react-router"; + +export class UserService { + user: User; + isLoggedIn: boolean; + roleRoutes: RouteObject[]; + constructor(private userRepository: UserRepository) { + this.user = new User(); + this.isLoggedIn = false; + this.roleRoutes = []; + makeAutoObservable(this); + } + + async signIn(user: Pick) { + const { code, data, msg } = await this.userRepository.authLogin(user); + this.user.signIn(data as User); + return { success: code === 0, msg, data: data as User }; + } + + /** + * 设置角色路由 + */ + setRoleRoutes(routeObjects: RouteObject[]) { + this.roleRoutes = routeObjects; + } + + /** + * 获取用户信息 + */ + async userAuth() { + const { code, data, msg } = await this.userRepository.userAuth(); + if (code === 0 && data?.tokenValid) { + this.user.signIn(data.payload as User); + return { success: true, data }; + } else { + this.user.signOut(); + return { success: false, msg }; + } + } + + /** + * 获取标注人员信息 + */ + async getDmpAnnotators() { + return await this.userRepository.getDmpAnnotators(); + } +} diff --git a/apps/dmp/core/domain/User/entities/User.ts b/apps/dmp/core/domain/User/entities/User.ts new file mode 100644 index 0000000..120db0d --- /dev/null +++ b/apps/dmp/core/domain/User/entities/User.ts @@ -0,0 +1,43 @@ +import { makeAutoObservable } from "mobx"; + +interface UserProps { + id?: number | string; + username?: string; + password?: string; + isEnabled?: boolean; + isLoggedIn?: boolean; +} + +export class User { + id?: number | string; + username?: string; + password?: string; + isEnabled?: boolean; + isLoggedIn?: boolean; + roles: any[] | undefined; + + constructor(props: UserProps = {}) { + this.id = props.id; + this.username = props.username; + this.password = props.password; + this.isEnabled = props.isEnabled; + this.isLoggedIn = false; + makeAutoObservable(this); + } + + signIn(user: User) { + this.isLoggedIn = true; + this.roles = user.roles; + } + + signOut() { + this.isLoggedIn = false; + } + + /** + * 获取角色菜单 + */ + getRolesName() { + return this.roles?.map((r: { name: string }) => r.name); + } +} diff --git a/apps/dmp/core/infra/api/Request.ts b/apps/dmp/core/infra/api/Request.ts new file mode 100644 index 0000000..5b83404 --- /dev/null +++ b/apps/dmp/core/infra/api/Request.ts @@ -0,0 +1,143 @@ +import { message } from "antd"; +import { getFingerprint, SymmetricCrypto } from "@tavi/util"; +import axios, { + AxiosError, + AxiosInstance, + AxiosRequestConfig, + AxiosResponse, + CancelTokenSource, + InternalAxiosRequestConfig, +} from "axios"; + +interface RequestConfig extends InternalAxiosRequestConfig { + onRequestSent?: RequestCallback; +} + +type RequestCallback = (token: string) => void; + +type ResponseException = { + msg: string; + path: string; + statusCode: number; + timestamp: string; +}; + +class AxiosRequestInstance { + private instance: AxiosInstance; + private cancelTokenMap: Map; + + constructor() { + this.instance = axios.create(); + this.cancelTokenMap = new Map(); + + // 请求拦截 + this.instance.interceptors.request.use(async (config: RequestConfig) => { + const token = this.generateToken(); + const source = axios.CancelToken.source(); + this.cancelTokenMap.set(token, source); + + // 生成 traceId 并加入请求头 + const traceId = this.generateTraceId(); + config.headers["x-trace-id"] = traceId; + config.headers["x-request-token"] = token; // 将token加入请求头 + config.cancelToken = source.token; + // 浏览器指纹 + config.headers["x-finger"] = await getFingerprint(); + // 浏览器指纹2 + config.headers["x-finger2"] = new SymmetricCrypto().encrypt({ + language: navigator.language, + userAgent: navigator.userAgent, + platform: navigator.platform, + screenResolution: `${window.screen.width} x ${window.screen.height}`, + }); + + if (config.onRequestSent) config.onRequestSent(token); + return config; + }); + + // 响应拦截 + this.instance.interceptors.response.use( + (response: AxiosResponse) => { + const token = response.headers["x-request-token"] as string; + this.cancelTokenMap.delete(token); // 完成后删除此token + return response; + }, + (error: AxiosError) => { + if (error.response && error.response.status === 403) { + const { msg } = error.response.data as ResponseException; + message.error(msg); + } + return Promise.reject(error); + } + ); + } + + // 生成token + private generateToken(): string { + return Math.random().toString(36).substring(2); + } + + // 生成traceId + private generateTraceId(): string { + // 使用你自己的 traceId 生成策略,这里是一个简单的示例 + return Math.random().toString(36).substring(2); + } + + // 取消请求 + public cancelRequest(token: string): void { + const source = this.cancelTokenMap.get(token); + if (source) { + source.cancel("Request canceled, token:" + token); + this.cancelTokenMap.delete(token); + } + } + + // 封装get、post等请求 + public async get( + url: string, + config?: AxiosRequestConfig & { onRequestSent?: RequestCallback } + ): Promise { + const response = await this.instance.get(url, config); + return response.data; + } + + public async post( + url: string, + data?: any, + config?: RequestConfig & { onRequestSent?: RequestCallback } + ): Promise { + const response = await this.instance.post(url, data, config); + return response.data; + } + + public async put( + url: string, + data?: any, + config?: RequestConfig & { onRequestSent?: RequestCallback } + ): Promise { + const response = await this.instance.put(url, data, config); + return response.data; + } + + public async delete( + url: string, + config?: RequestConfig & { onRequestSent?: RequestCallback } + ): Promise { + const response = await this.instance.delete(url, config); + return response.data; + } +} + +export const Request = new AxiosRequestInstance(); + +// 使用方法: +// 1. 发起请求并获取token +// let token: string; +// requestInstance.get("https://api.example.com/data", { +// onRequestSent: (requestToken) => { +// token = requestToken; +// }, +// }); + +// 2. 在需要取消请求的时候取消请求 +// requestInstance.cancelRequest(token); diff --git a/apps/dmp/core/infra/api/index.ts b/apps/dmp/core/infra/api/index.ts new file mode 100644 index 0000000..3ed7736 --- /dev/null +++ b/apps/dmp/core/infra/api/index.ts @@ -0,0 +1,63 @@ +import { User } from "@@/domain/User/entities/User"; +import { Request } from "./Request"; + +const PREFIX = "/api/dmp"; +const PREFIX_CERT = "/cert"; +const PREFIX_PACS = "/dicom-web"; + +type ResponseType = Promise<{ + code?: number | string; + data?: unknown; + msg?: string; +}>; + +type ResponsePacsType = Promise<{ + ID: string; + ParentPatient: string; + ParentSeries: string; + ParentStudy: string; + Path: string; + Status: string; +}>; + +export type ExistInPacsDTO = { + StudyInstanceUID: string; + SeriesInstanceUID: string; +}; + +export const Apis = { + /** + * 用户登录 + */ + signIn: (p: Pick): ResponseType => + Request.post(PREFIX + "/auth/signIn", p), + /** + * 用户认证 + */ + userAuth: (): ResponseType => Request.get(PREFIX_CERT + "/auth/user"), + /** + * 上传dcm到pacs + */ + upload2Pacs: (fd: FormData): ResponsePacsType => + Request.post(PREFIX_PACS + "/instances", fd, { + headers: { + "Content-Type": "multipart/form-data", + }, + }), + /** + * pacs当中是否存在该序列,返回切片数量对比上传的File[].length + */ + existInPacs: ({ + StudyInstanceUID, + SeriesInstanceUID, + }: ExistInPacsDTO): Promise<[]> => + Request.get( + PREFIX_PACS + + `/dicom-web/studies/${StudyInstanceUID}/series/${SeriesInstanceUID}/instances` + ), + /** + * 获取标注人员信息 + */ + getDmpAnnotators: (): ResponseType => + Request.get(PREFIX + `/user/find/annotator`), +}; diff --git a/apps/dmp/index.html b/apps/dmp/index.html new file mode 100644 index 0000000..2b8b92b --- /dev/null +++ b/apps/dmp/index.html @@ -0,0 +1,13 @@ + + + + + + + dmp + + +
+ + + diff --git a/apps/dmp/package.json b/apps/dmp/package.json new file mode 100644 index 0000000..9064ccb --- /dev/null +++ b/apps/dmp/package.json @@ -0,0 +1,41 @@ +{ + "name": "@tavi/dmp-web", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "react": "18.2.0", + "react-dom": "18.2.0", + "react-router": "6.14.2", + "react-router-dom": "6.14.2", + "antd": "5.8.3", + "axios": "1.4.0", + "react-icons": "4.10.1", + "mobx": "6.9.0", + "mobx-react-lite": "3.4.3", + "@ant-design/icons": "5.2.5", + "dicom-parser": "1.8.21", + "path-to-regexp": "6.2.1", + "@tavi/util": "workspace:*" + }, + "devDependencies": { + "@types/react": "18.2.14", + "@types/react-dom": "18.2.6", + "@types/react-router": "5.1.20", + "@types/react-router-dom": "5.3.3", + "@typescript-eslint/eslint-plugin": "^5.61.0", + "@typescript-eslint/parser": "^5.61.0", + "@vitejs/plugin-react": "^4.0.1", + "eslint": "^8.44.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.1", + "typescript": "^5.0.2", + "vite": "^4.4.0" + } +} \ No newline at end of file diff --git a/apps/dmp/public/favicon.svg b/apps/dmp/public/favicon.svg new file mode 100644 index 0000000..ff87503 --- /dev/null +++ b/apps/dmp/public/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/dmp/public/test.json b/apps/dmp/public/test.json new file mode 100644 index 0000000..3ab17cf --- /dev/null +++ b/apps/dmp/public/test.json @@ -0,0 +1,12 @@ +{ + "studies": [ + { + "StudyInstanceUID": "1.2.840.113619.2.416.200043823236217877797891016883696407563", + "series": [ + { + "SeriesInstanceUID": "1.2.840.113619.6.80.114374075765625.22940.1553237925965.1" + } + ] + } + ] +} \ No newline at end of file diff --git a/apps/dmp/public/uploadWorker.js b/apps/dmp/public/uploadWorker.js new file mode 100644 index 0000000..76c715f --- /dev/null +++ b/apps/dmp/public/uploadWorker.js @@ -0,0 +1,27 @@ +/* eslint-disable */ +self.onmessage = function (e) { + const files = e.data; + const promises = []; + + for (let file of files) { + promises.push(readFile(file)); + } + + Promise.all(promises).then(results => { + self.postMessage(results); + }); +} + +function readFile(file) { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onload = function (e) { + resolve({ + name: file.name, + data: e.target.result + }); + }; + reader.onerror = reject; + reader.readAsDataURL(file); // 或者使用其他方法如 readAsArrayBuffer + }); +} diff --git a/apps/dmp/public/wave.svg b/apps/dmp/public/wave.svg new file mode 100644 index 0000000..a823bdf --- /dev/null +++ b/apps/dmp/public/wave.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/dmp/src/App.tsx b/apps/dmp/src/App.tsx new file mode 100644 index 0000000..dfafac7 --- /dev/null +++ b/apps/dmp/src/App.tsx @@ -0,0 +1,16 @@ +import { observer } from "mobx-react-lite"; +import { ConfigProvider } from "antd"; +import { RouterElements } from "./router"; +import { theme } from "./constant"; +import { BrowserRouter } from "react-router-dom"; + +export const App = observer(() => { + console.log("app"); + return ( + + + + + + ); +}); diff --git a/apps/dmp/src/components/Layout/Menu/index.tsx b/apps/dmp/src/components/Layout/Menu/index.tsx new file mode 100644 index 0000000..4b408c1 --- /dev/null +++ b/apps/dmp/src/components/Layout/Menu/index.tsx @@ -0,0 +1,45 @@ +import { MenuItem, RoleNameType, roleMenusMapping } from "./roleMenu.config"; +import { UserService } from "@@/domain/User/UserService"; +import { useEffect, useState } from "react"; +import { observer } from "mobx-react-lite"; +import { useNavigate } from "react-router"; +import { Menu, Spin } from "antd"; + +export const useMenu = () => { + const navigate = useNavigate(); + const [selectedKeys, setSelectedKeys] = useState([location.pathname]); + + useEffect(() => setSelectedKeys([location.pathname]), []); + + const RoleMenu: React.FC<{ domainService: UserService }> = observer( + ({ domainService }) => { + const { user } = domainService; + console.log(user); + const roleNames = user.getRolesName(); + if (roleNames) { + let menuItems: MenuItem[] = []; + for (const key in roleMenusMapping) + if (roleNames.includes(key)) + menuItems = roleMenusMapping[key as RoleNameType]; + return ( + navigate(e.key)} + style={{ width: "100%", height: "100%" }} + selectedKeys={selectedKeys} + defaultOpenKeys={["dicom"]} + mode="inline" + items={menuItems} + /> + ); + } else { + return ( +
+ +
+ ); + } + } + ); + + return { RoleMenu }; +}; diff --git a/apps/dmp/src/components/Layout/Menu/roleMenu.config.tsx b/apps/dmp/src/components/Layout/Menu/roleMenu.config.tsx new file mode 100644 index 0000000..0c2ec39 --- /dev/null +++ b/apps/dmp/src/components/Layout/Menu/roleMenu.config.tsx @@ -0,0 +1,46 @@ +import { ROLE_NAME } from "@/config"; +import { + CloudUploadOutlined, + DatabaseOutlined, + UnorderedListOutlined, +} from "@ant-design/icons"; +import { MenuProps } from "antd"; + +export type MenuItem = Required["items"][number]; + +const getItem = ( + label: React.ReactNode, + key: React.Key, + icon?: React.ReactNode, + children?: MenuItem[], + type?: "group" +): MenuItem => { + return { + key, + icon, + children, + label, + type, + } as MenuItem; +}; + +const adminMenuItems: MenuItem[] = [ + getItem("影像", "dicom", , [ + getItem("上传", "/upload", ), + getItem("列表", "/list", ), + ]), +]; + +const annotatorMenuItems: MenuItem[] = [ + getItem("影像", "dicom", , [ + getItem("标注", "/annotator/list", ), + ]), +]; + +/** + * key对应roles的name字段,创建角色的key + */ +export const roleMenusMapping: Record = { + [ROLE_NAME.ADMIN]: adminMenuItems, + [ROLE_NAME.ANNOTATOR]: annotatorMenuItems, +}; diff --git a/apps/dmp/src/components/Layout/index.less b/apps/dmp/src/components/Layout/index.less new file mode 100644 index 0000000..2db41be --- /dev/null +++ b/apps/dmp/src/components/Layout/index.less @@ -0,0 +1,16 @@ +.layout-container { + >header { + position: relative; + z-index: 10; + max-width: 100%; + background: #ffffff; + height: 60px; + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.03), 0 1px 6px -1px rgba(0, 0, 0, 0.02), 0 2px 4px 0 rgba(0, 0, 0, 0.02); + } + + >div { + display: grid; + grid-template-columns: 1fr 6fr; + height: calc(100vh - 60px); + } +} \ No newline at end of file diff --git a/apps/dmp/src/components/Layout/index.tsx b/apps/dmp/src/components/Layout/index.tsx new file mode 100644 index 0000000..ec2d685 --- /dev/null +++ b/apps/dmp/src/components/Layout/index.tsx @@ -0,0 +1,27 @@ +import { Outlet, useLocation } from "react-router"; +import { useDomain } from "@/hook/useDomain"; +import { useMenu } from "./Menu"; +import "./index.less"; +interface LayoutProps { + children?: JSX.Element; +} + +export const Layout = (props: LayoutProps) => { + const location = useLocation(); + const { userDomainService } = useDomain(); + const { RoleMenu } = useMenu(); + + return ( +
+
{location.pathname}
+
+ +
+ +
+
+
+ ); +}; diff --git a/apps/dmp/src/config/index.ts b/apps/dmp/src/config/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/apps/dmp/src/constant.ts b/apps/dmp/src/constant.ts new file mode 100644 index 0000000..fcb553d --- /dev/null +++ b/apps/dmp/src/constant.ts @@ -0,0 +1,21 @@ +import { ThemeConfig } from "antd"; + +export const defaultDocumentTitle = "dmp - 数据管理平台"; + +export const AuthFailedReplacePath = "/login"; + +/** + * token优先级低于局部ConfigProvider + */ +export const theme: ThemeConfig = { + token: { + colorPrimary: "#fa541c", + borderRadius: 2, + }, +}; + +// value对应认证中心创建角色key +export enum ROLE_NAME { + ADMIN = "dmp_admin", + ANNOTATOR = "dmp_annotator", +} diff --git a/apps/dmp/src/context/auth.tsx b/apps/dmp/src/context/auth.tsx new file mode 100644 index 0000000..6d8d1c2 --- /dev/null +++ b/apps/dmp/src/context/auth.tsx @@ -0,0 +1,32 @@ +import { createContext, useState } from "react"; + +type Auth = { + isLoggedIn: boolean; +}; + +type AuthContextType = { + auth: Auth; + setAuth: React.Dispatch>; +}; + +const defaultAuth: AuthContextType["auth"] = { isLoggedIn: false }; +const defaultSetAuth: AuthContextType["setAuth"] = () => {}; + +export const AuthContext = createContext({ + auth: defaultAuth, + setAuth: defaultSetAuth, +}); + +interface AuthProviderProps { + children?: JSX.Element; +} + +export const AuthProvider = (props: AuthProviderProps) => { + const [auth, setAuth] = useState({ isLoggedIn: false }); + + return ( + + {props.children} + + ); +}; diff --git a/apps/dmp/src/context/domainService.tsx b/apps/dmp/src/context/domainService.tsx new file mode 100644 index 0000000..ca6eeec --- /dev/null +++ b/apps/dmp/src/context/domainService.tsx @@ -0,0 +1,29 @@ +import { DicomRepository } from "@@/domain/Dicom/DicomRepository"; +import { DicomService } from "@@/domain/Dicom/DicomService"; +import { UserRepository } from "@@/domain/User/UserRepository"; +import { UserService } from "@@/domain/User/UserService"; +import { createContext } from "react"; + +export type Services = { + userDomainService: UserService; + dicomDomainService: DicomService; +}; + +const defaultServiceMap = { + userDomainService: new UserService(new UserRepository()), + dicomDomainService: new DicomService(new DicomRepository()), +}; + +export const DomainServiceContext = createContext(defaultServiceMap); + +interface DomainServiceProviderProps { + children?: JSX.Element; +} + +export const DomainServiceProvider = (props: DomainServiceProviderProps) => { + return ( + + {props.children} + + ); +}; diff --git a/apps/dmp/src/hook/useAuth.tsx b/apps/dmp/src/hook/useAuth.tsx new file mode 100644 index 0000000..1ba2569 --- /dev/null +++ b/apps/dmp/src/hook/useAuth.tsx @@ -0,0 +1,4 @@ +import { useContext } from "react"; +import { AuthContext } from "../context/auth"; + +export const useAuth = () => useContext(AuthContext); diff --git a/apps/dmp/src/hook/useDomain.tsx b/apps/dmp/src/hook/useDomain.tsx new file mode 100644 index 0000000..a3ed4ae --- /dev/null +++ b/apps/dmp/src/hook/useDomain.tsx @@ -0,0 +1,10 @@ +import { DomainServiceContext, Services } from "@/context/domainService"; +import { useContext } from "react"; + +export const useDomain = (): Services => { + const context = useContext(DomainServiceContext); + if (context === null) { + throw new Error("useDomain ctx丢失,必须在domainService上下文中使用"); + } + return context; +}; diff --git a/apps/dmp/src/main.tsx b/apps/dmp/src/main.tsx new file mode 100644 index 0000000..7f0238e --- /dev/null +++ b/apps/dmp/src/main.tsx @@ -0,0 +1,5 @@ +import ReactDOM from "react-dom/client"; +import { App } from "./App"; +import "@/styles/app.less"; + +ReactDOM.createRoot(document.getElementById("root")!).render(); diff --git a/apps/dmp/src/modules/Admin/Dicom/List/index.tsx b/apps/dmp/src/modules/Admin/Dicom/List/index.tsx new file mode 100644 index 0000000..2a7ef1c --- /dev/null +++ b/apps/dmp/src/modules/Admin/Dicom/List/index.tsx @@ -0,0 +1,7 @@ +interface DicomListProps { + children?: JSX.Element; +} + +export const DicomList = (props: DicomListProps) => { + return
DicomList
; +}; diff --git a/apps/dmp/src/modules/Admin/Dicom/Upload/DicomTable/columns.tsx b/apps/dmp/src/modules/Admin/Dicom/Upload/DicomTable/columns.tsx new file mode 100644 index 0000000..70b5f35 --- /dev/null +++ b/apps/dmp/src/modules/Admin/Dicom/Upload/DicomTable/columns.tsx @@ -0,0 +1,61 @@ +import { TableColumnsType } from "antd"; +import { Series, Study } from "../DicomUploader/util"; + +export const columnsForStudy: TableColumnsType = [ + { title: "病历号", dataIndex: "patientID", key: "patientID" }, + { title: "姓名", dataIndex: "patientName", key: "patientName" }, + { + title: "序列数", + key: "seriesNumber", + render: (_: any, record: Study) => {record.subs.length}, + }, + { + title: "切片数量", + key: "seriesNumber", + render: (_: any, record: Study) => ( + + {record.subs.map((s) => s.subs.length).reduce((p, n) => p + n)} + + ), + }, + { title: "年龄", dataIndex: "patientAge", key: "patientAge" }, + { title: "性别", dataIndex: "patientSex", key: "patientSex" }, + { + title: "扫描日期", + dataIndex: "acquisitionDate", + key: "acquisitionDate", + }, + { + title: "描述", + dataIndex: "studyDescription", + key: "studyDescription", + }, +]; + +export const columnsForSeries: TableColumnsType = [ + { + title: "序列描述", + dataIndex: "seriesDescription", + key: "seriesDescription", + }, + { + title: "切片数量", + key: "sliceNumber", + render: (_: any, record: Series) => {record.subs.length}, + }, + { + title: "切片层厚", + dataIndex: "sliceThickness", + key: "sliceThickness", + }, + { + title: "成像设备", + dataIndex: "modality", + key: "modality", + }, + { + title: "设备制造商", + dataIndex: "manufacturer", + key: "manufacturer", + }, +]; diff --git a/apps/dmp/src/modules/Admin/Dicom/Upload/DicomTable/index.tsx b/apps/dmp/src/modules/Admin/Dicom/Upload/DicomTable/index.tsx new file mode 100644 index 0000000..64cb8b8 --- /dev/null +++ b/apps/dmp/src/modules/Admin/Dicom/Upload/DicomTable/index.tsx @@ -0,0 +1,76 @@ +import { columnsForSeries, columnsForStudy } from "./columns"; +import { EyeOutlined, TagOutlined } from "@ant-design/icons"; +import { Series, Study } from "../DicomUploader/util"; +import { Button, Space, Table, Tooltip } from "antd"; +interface DicomTableProps { + studys: Study[]; + loading?: boolean; + onSelectedRows?: (rows: Study[]) => void; + onUploadFiles?: (study: Study, series: Series) => void; +} + +export const DicomTable = (props: DicomTableProps) => { + const { studys } = props; + + /** + * 序列级别 + */ + const expandedRowRenderForSeries = (record: Study) => { + return ( +
( + + + + ), + }, + ]} + dataSource={record.subs} + pagination={false} + /> + ); + }; + + return ( +
+ props.onSelectedRows?.(selectedRows), + }} + columns={[ + ...columnsForStudy, + { + title: "操作", + dataIndex: "operation", + render: (_: any, record: Study) => ( + + + + + + 文件统计, dicom文件: {dcmFileNum}, 总文件: {totalFileNum}, 大小: + {dcmFileSize} + + + + + + + + + + + + setSelectedRows(rows)} + onUploadFiles={onUploadFiles} + /> + + ); +}; diff --git a/apps/dmp/src/modules/Admin/index.tsx b/apps/dmp/src/modules/Admin/index.tsx new file mode 100644 index 0000000..42ee0c7 --- /dev/null +++ b/apps/dmp/src/modules/Admin/index.tsx @@ -0,0 +1,7 @@ +interface AdminDashboardProps { + children?: JSX.Element; +} + +export const AdminDashboard = (props: AdminDashboardProps) => { + return
AdminDashboard
; +}; diff --git a/apps/dmp/src/modules/Annotator/List/index.tsx b/apps/dmp/src/modules/Annotator/List/index.tsx new file mode 100644 index 0000000..1b03b7b --- /dev/null +++ b/apps/dmp/src/modules/Annotator/List/index.tsx @@ -0,0 +1,7 @@ +interface AnnotatorProps { + children?: JSX.Element; +} + +export const AnnotatorList = (props: AnnotatorProps) => { + return
Annotator
; +}; diff --git a/apps/dmp/src/modules/Annotator/index.tsx b/apps/dmp/src/modules/Annotator/index.tsx new file mode 100644 index 0000000..5da46fe --- /dev/null +++ b/apps/dmp/src/modules/Annotator/index.tsx @@ -0,0 +1,7 @@ +interface AnnotatorDashBoardProps { + children?: JSX.Element; +} + +export const AnnotatorDashBoard = (props: AnnotatorDashBoardProps) => { + return
AnnotatorDashBoard
+} diff --git a/apps/dmp/src/modules/Login/index.less b/apps/dmp/src/modules/Login/index.less new file mode 100644 index 0000000..67b8dab --- /dev/null +++ b/apps/dmp/src/modules/Login/index.less @@ -0,0 +1,7 @@ +.login-container { + display: flex; + justify-content: center; + align-items: center; + background-size: cover; + height: 100vh; +} \ No newline at end of file diff --git a/apps/dmp/src/modules/Login/index.tsx b/apps/dmp/src/modules/Login/index.tsx new file mode 100644 index 0000000..1b2f83f --- /dev/null +++ b/apps/dmp/src/modules/Login/index.tsx @@ -0,0 +1,63 @@ +import { Button, Form, Input, message } from "antd"; +import { useDomain } from "@/hook/useDomain"; +import "./index.less"; +import { useNavigate } from "react-router"; + +interface LoginProps { + children?: JSX.Element; +} + +export const Login = (props: LoginProps) => { + const { userDomainService } = useDomain(); + const [messageApi, contextHolder] = message.useMessage(); + const navigate = useNavigate(); + + const onFinish = (values: { username: string; password: string }) => { + userDomainService.signIn(values).then((result) => { + const { success, msg } = result; + if (success) { + messageApi.success(msg); + navigate("/"); + } else { + messageApi.error(msg); + } + }); + }; + + return ( +
+ + + + + + + + + + + + + {contextHolder} +
+ ); +}; diff --git a/apps/dmp/src/router/Guard.tsx b/apps/dmp/src/router/Guard.tsx new file mode 100644 index 0000000..c48e805 --- /dev/null +++ b/apps/dmp/src/router/Guard.tsx @@ -0,0 +1,30 @@ +import { useDomain } from "@/hook/useDomain"; +import React from "react"; +import { useLocation, useNavigate } from "react-router"; +import { pathToRegexp } from "path-to-regexp"; +import { AuthFailedReplacePath } from "@/constant"; + +interface RouteGuardProps { + children?: React.ReactNode; + ignorePaths: string[]; +} + +export const RouteGuard = (props: RouteGuardProps) => { + const { children, ignorePaths } = props; + const { userDomainService } = useDomain(); + const { user } = userDomainService; + const location = useLocation(); + const navigate = useNavigate(); + + const ignore = ignorePaths.some((p) => + pathToRegexp(p).test(location.pathname) + ); + + if (!ignore && !user.isLoggedIn) { + userDomainService.userAuth().then(({ success }) => { + if (!success) navigate(AuthFailedReplacePath); + }); + } + + return children; +}; diff --git a/apps/dmp/src/router/baseRoutes.tsx b/apps/dmp/src/router/baseRoutes.tsx new file mode 100644 index 0000000..9e54615 --- /dev/null +++ b/apps/dmp/src/router/baseRoutes.tsx @@ -0,0 +1,14 @@ +import { Login } from "@/modules/Login"; +import { RouteObject } from "react-router"; +import { ExpandRouteProps } from "."; + +/** + * 基础路由 + */ +export const baseRoutes: (RouteObject & ExpandRouteProps)[] = [ + { + path: "/login", + element: , + title: "登录 - 数据管理平台", + }, +]; diff --git a/apps/dmp/src/router/index.tsx b/apps/dmp/src/router/index.tsx new file mode 100644 index 0000000..61c02f4 --- /dev/null +++ b/apps/dmp/src/router/index.tsx @@ -0,0 +1,48 @@ +import { useDomain } from "@/hook/useDomain"; +import { BrowserRouter, Route, Routes, useLocation } from "react-router-dom"; +import { baseRoutes } from "./baseRoutes"; +import { roleRoutes } from "./roleRoutes"; +import { RouteGuard } from "./Guard"; +import { observer } from "mobx-react-lite"; +import { ROLE_NAME, defaultDocumentTitle } from "@/constant"; +import { pathToRegexp } from "path-to-regexp"; + +export type ExpandRouteProps = { + title?: string; +}; + +export const RouterElements = observer(() => { + const { userDomainService } = useDomain(); + const { user } = userDomainService; + const location = useLocation(); + + const roleNames = user.roles?.map( + (r: { name: string }) => r.name + ) as ROLE_NAME[]; + + /** + * 根据角色生成路由 + */ + const currentRoutes = roleNames?.map((name) => roleRoutes[name]).flat() ?? []; + + /** + * document.title + */ + const currentRoute = [...currentRoutes, ...baseRoutes].find((r) => + pathToRegexp(r.path!).test(location.pathname) + ); + if (currentRoute) document.title = currentRoute.title || defaultDocumentTitle; + + return ( + r.path!)}> + + {currentRoutes.map((r) => ( + + ))} + {baseRoutes.map((r) => ( + + ))} + + + ); +}); diff --git a/apps/dmp/src/router/roleRoutes.tsx b/apps/dmp/src/router/roleRoutes.tsx new file mode 100644 index 0000000..a16ec7b --- /dev/null +++ b/apps/dmp/src/router/roleRoutes.tsx @@ -0,0 +1,41 @@ +import { AnnotatorList } from "@/modules/Annotator/List"; +import { DicomList } from "@/modules/Admin/Dicom/List"; +import { DicomUpload } from "@/modules/Admin/Dicom/Upload"; +import { Navigate, RouteObject } from "react-router-dom"; +import { ExpandRouteProps } from "."; +import { ROLE_NAME } from "@/constant"; + +export const roleRoutes: Record = + { + /** + * 管理员 + */ + [ROLE_NAME.ADMIN]: [ + { path: "/", element: , title: "管理员" }, + { + path: "/list", + element: , + title: "管理员", + }, + { + path: "/upload", + element: , + title: "管理员", + }, + ], + /** + * 标注 + */ + [ROLE_NAME.ANNOTATOR]: [ + { + path: "/", + element: , + title: "标注", + }, + { + path: "/annotator/list", + element: , + title: "标注", + }, + ], + }; diff --git a/apps/dmp/src/styles/app.less b/apps/dmp/src/styles/app.less new file mode 100644 index 0000000..14dab9e --- /dev/null +++ b/apps/dmp/src/styles/app.less @@ -0,0 +1,10 @@ +* { + box-sizing: border-box; +} + +html, +body { + margin: 0; + padding: 0; + font-size: 14px; +} \ No newline at end of file diff --git a/apps/dmp/src/vite-env.d.ts b/apps/dmp/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/apps/dmp/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/apps/dmp/tsconfig.json b/apps/dmp/tsconfig.json new file mode 100644 index 0000000..492be18 --- /dev/null +++ b/apps/dmp/tsconfig.json @@ -0,0 +1,43 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": [ + "src/*" + ], + "@@/*": [ + "core/*" + ] + }, + "target": "ES2020", + "useDefineForClassFields": true, + "lib": [ + "ES2020", + "DOM", + "DOM.Iterable" + ], + "module": "ESNext", + "skipLibCheck": true, + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": [ + "src", + "./core", + ], + "references": [ + { + "path": "./tsconfig.node.json" + } + ] +} \ No newline at end of file diff --git a/apps/dmp/tsconfig.node.json b/apps/dmp/tsconfig.node.json new file mode 100644 index 0000000..42872c5 --- /dev/null +++ b/apps/dmp/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/apps/dmp/vite.config.ts b/apps/dmp/vite.config.ts new file mode 100644 index 0000000..915f340 --- /dev/null +++ b/apps/dmp/vite.config.ts @@ -0,0 +1,33 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; +import { resolve } from "path"; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + "@": resolve(__dirname, "src"), + "@@": resolve(__dirname, "core"), + }, + }, + server: { + port: 5177, + proxy: { + "/api/dmp": { + target: "http://localhost:9012", + changeOrigin: true, + rewrite: (path) => path.replace(/^\/api/, ""), + }, + "/cert": { + target: "http://localhost:12144", + changeOrigin: true, + }, + "/dicom-web": { + target: "http://localhost:8042/", + changeOrigin: true, + rewrite: (path) => path.replace(/^\/dicom-web\//, "/"), + }, + }, + }, +}); diff --git a/apps/services/aorta/docker-compose.yml b/apps/services/aorta/docker-compose.yml new file mode 100644 index 0000000..337af3d --- /dev/null +++ b/apps/services/aorta/docker-compose.yml @@ -0,0 +1,17 @@ +version: '3' +services: + gateway: + build: './gateway' + restart: always + hostname: gateway + ports: + - "8000:8000" + auth: + build: './auth' + restart: always + hostname: auth + links: + - mysql + + mysql: + image: '' diff --git a/apps/services/aorta/gateway/.env.dev b/apps/services/aorta/gateway/.env.dev new file mode 100644 index 0000000..ac988cd --- /dev/null +++ b/apps/services/aorta/gateway/.env.dev @@ -0,0 +1,8 @@ +# 全局url前缀 +GLOBAL_PREFIX=aorta +PORT=9008 +MYSQL_HOST=localhost +MYSQL_PORT=3306 +MYSQL_USERNAME=root +MYSQL_PASSWORD=root +MYSQL_DATABASE=report diff --git a/apps/services/aorta/gateway/.env.prod b/apps/services/aorta/gateway/.env.prod new file mode 100644 index 0000000..05095db --- /dev/null +++ b/apps/services/aorta/gateway/.env.prod @@ -0,0 +1 @@ +PORT=19008 \ No newline at end of file diff --git a/apps/services/aorta/gateway/.eslintrc.js b/apps/services/aorta/gateway/.eslintrc.js new file mode 100644 index 0000000..259de13 --- /dev/null +++ b/apps/services/aorta/gateway/.eslintrc.js @@ -0,0 +1,25 @@ +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.json', + tsconfigRootDir: __dirname, + sourceType: 'module', + }, + plugins: ['@typescript-eslint/eslint-plugin'], + extends: [ + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + root: true, + env: { + node: true, + jest: true, + }, + ignorePatterns: ['.eslintrc.js'], + rules: { + '@typescript-eslint/interface-name-prefix': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-explicit-any': 'off', + }, +}; diff --git a/apps/services/aorta/gateway/.gitignore b/apps/services/aorta/gateway/.gitignore new file mode 100644 index 0000000..22f55ad --- /dev/null +++ b/apps/services/aorta/gateway/.gitignore @@ -0,0 +1,35 @@ +# compiled output +/dist +/node_modules + +# Logs +logs +*.log +npm-debug.log* +pnpm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# OS +.DS_Store + +# Tests +/coverage +/.nyc_output + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json \ No newline at end of file diff --git a/apps/services/aorta/gateway/.prettierrc b/apps/services/aorta/gateway/.prettierrc new file mode 100644 index 0000000..dcb7279 --- /dev/null +++ b/apps/services/aorta/gateway/.prettierrc @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "trailingComma": "all" +} \ No newline at end of file diff --git a/apps/services/aorta/gateway/Dockerfile b/apps/services/aorta/gateway/Dockerfile new file mode 100644 index 0000000..881dad4 --- /dev/null +++ b/apps/services/aorta/gateway/Dockerfile @@ -0,0 +1,7 @@ +FROM node:16.19-alpine +RUN npm install -g pnpm +RUN mkdir -p /www/wwwroot/aorta/gateway +WORKDIR /www/wwwroot/aorta/gateway +ADD . /www/wwwroot/aorta/gateway +RUN pnpm install +CMD pnpm run build && pnpm run start:prod \ No newline at end of file diff --git a/apps/services/aorta/gateway/nest-cli.json b/apps/services/aorta/gateway/nest-cli.json new file mode 100644 index 0000000..f9aa683 --- /dev/null +++ b/apps/services/aorta/gateway/nest-cli.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/nest-cli", + "collection": "@nestjs/schematics", + "sourceRoot": "src", + "compilerOptions": { + "deleteOutDir": true + } +} diff --git a/apps/services/aorta/gateway/package.json b/apps/services/aorta/gateway/package.json new file mode 100644 index 0000000..9fde298 --- /dev/null +++ b/apps/services/aorta/gateway/package.json @@ -0,0 +1,51 @@ +{ + "name": "@tavi/aorta-gateway", + "version": "1.0.0", + "scripts": { + "build": "nest build", + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", + "start": "nest start", + "start:dev": "cross-env NODE_ENV=dev nest start --watch", + "start:debug": "nest start --debug --watch", + "start:prod": "cross-env NODE_ENV=prod node dist/main", + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix" + }, + "dependencies": { + "@tavi/util": "workspace:*", + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "reflect-metadata": "^0.1.13", + "@nestjs/config": "3.0.0", + "rxjs": "7.8.1", + "nats": "2.15.1", + "@nestjs/microservices": "10.0.5", + "nacos": "2.5.1", + "cross-env": "7.0.3", + "cookie-parser": "1.4.6", + "minio": "7.1.1", + "@tavi/oss": "workspace:*", + "typeorm": "0.3.16" + }, + "devDependencies": { + "@nestjs/cli": "^10.0.0", + "@nestjs/schematics": "^10.0.0", + "@nestjs/testing": "^10.0.0", + "@types/express": "^4.17.17", + "@types/node": "^20.3.1", + "@types/supertest": "^2.0.12", + "@typescript-eslint/eslint-plugin": "^5.59.11", + "@typescript-eslint/parser": "^5.59.11", + "eslint": "^8.42.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^4.2.1", + "prettier": "^2.8.8", + "source-map-support": "^0.5.21", + "supertest": "^6.3.3", + "ts-loader": "^9.4.3", + "ts-node": "^10.9.1", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.1.3", + "@types/multer": "1.4.7" + } +} \ No newline at end of file diff --git a/apps/services/aorta/gateway/src/app.controller.ts b/apps/services/aorta/gateway/src/app.controller.ts new file mode 100644 index 0000000..24fa193 --- /dev/null +++ b/apps/services/aorta/gateway/src/app.controller.ts @@ -0,0 +1,4 @@ +import { Controller } from '@nestjs/common'; + +@Controller() +export class AppController {} diff --git a/apps/services/aorta/gateway/src/app.module.ts b/apps/services/aorta/gateway/src/app.module.ts new file mode 100644 index 0000000..6683067 --- /dev/null +++ b/apps/services/aorta/gateway/src/app.module.ts @@ -0,0 +1,61 @@ +import { + MiddlewareConsumer, + Module, + NestModule, + UseFilters, +} from '@nestjs/common'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; +import { NacosService } from './nacos/nacos.service'; +import { NacosModule } from './nacos/nacos.module'; +import { ConfigModule } from '@nestjs/config'; +import { ReportController } from './report/report.controller'; +import { ReportModule } from './report/report.module'; +import { APP_FILTER, APP_GUARD } from '@nestjs/core'; +import { AuthGuard } from './guard/auth.guard'; +import { AuthModule } from './auth/auth.module'; +import { ClientsModule, Transport } from '@nestjs/microservices'; +import * as cookieParser from 'cookie-parser'; +import { ForbiddenExceptionFilter } from './filter/forbid.filter'; + +@Module({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + envFilePath: `.env.${process.env.NODE_ENV}`, + }), + ClientsModule.register([ + { + name: 'Client', + transport: Transport.NATS, + options: { + servers: ['nats://localhost:4222'], + maxReconnectAttempts: 5, + reconnectTimeWait: 1000, + }, + }, + ]), + NacosModule, + ReportModule, + AuthModule, + // DbModule, + ], + controllers: [AppController, ReportController], + providers: [ + AppService, + NacosService, + { + provide: APP_GUARD, + useClass: AuthGuard, + }, + { + provide: APP_FILTER, + useClass: ForbiddenExceptionFilter, + }, + ], +}) +export class AppModule implements NestModule { + configure(consumer: MiddlewareConsumer) { + consumer.apply(cookieParser()).forRoutes('*'); + } +} diff --git a/apps/services/aorta/gateway/src/app.service.ts b/apps/services/aorta/gateway/src/app.service.ts new file mode 100644 index 0000000..c9ff19e --- /dev/null +++ b/apps/services/aorta/gateway/src/app.service.ts @@ -0,0 +1,3 @@ +import { Injectable } from '@nestjs/common'; +@Injectable() +export class AppService {} diff --git a/apps/services/aorta/gateway/src/auth/auth.controller.ts b/apps/services/aorta/gateway/src/auth/auth.controller.ts new file mode 100644 index 0000000..9add141 --- /dev/null +++ b/apps/services/aorta/gateway/src/auth/auth.controller.ts @@ -0,0 +1,58 @@ +import { Body, Controller, Inject, Post, Req, Res } from '@nestjs/common'; +import { ClientProxy } from '@nestjs/microservices'; +import { UserLoginDto } from './auth.dto'; +import { firstValueFrom } from 'rxjs'; +import { Response, Request } from 'express'; + +@Controller('auth') +export class AuthController { + constructor(@Inject('Client') private readonly client: ClientProxy) {} + + /** + * 业务系统登录接口 + * 1.对于登录的dto对象,由于业务的不同,有可能存在dto对象的不同,因此校验逻辑一定是放在业务的登录接口 + * 2.除了对参数进行校验,此外还需要对用户的身份进行校验:角色(是否属于这个系统)、可用(isEnabled) + * 3.签发token + */ + @Post('signIn') + async auth( + @Req() request: Request, + @Body() userLoginDto: UserLoginDto, + @Res({ passthrough: true }) res: Response, + ) { + const { username, password, phoneNumber } = userLoginDto; + // TODO: isEnabled、phoneNumber,用于后续验证 + const { isLegal, data, msg } = await firstValueFrom( + this.client.send({ cmd: 'cert.user.account' }, { username, password }), + ); + await firstValueFrom( + this.client.send( + { cmd: 'logger.user.signIn' }, + { + platform: 'dmp', + username, + finger: request.headers['x-finger'] as string, + finger2: request.headers['x-finger2'] as string, + isLegal, + }, + ), + ); + if (isLegal) { + // 签发token + const { token } = await firstValueFrom( + this.client.send({ cmd: 'cert.token.create' }, { username }), + ); + const { tokenKeyInCookie, expires } = await firstValueFrom( + this.client.send({ cmd: 'cert.token.config' }, []), + ); + res.cookie(tokenKeyInCookie, token, { + maxAge: expires * 1000, + httpOnly: true, + }); + const { password, ...rest } = data; + return { code: 'ok', data: rest, msg: '登陆成功' }; + } else { + return { code: 'fail', msg }; + } + } +} diff --git a/apps/services/aorta/gateway/src/auth/auth.dto.ts b/apps/services/aorta/gateway/src/auth/auth.dto.ts new file mode 100644 index 0000000..8f41f5e --- /dev/null +++ b/apps/services/aorta/gateway/src/auth/auth.dto.ts @@ -0,0 +1,6 @@ +export class UserLoginDto { + username: string; + password: string; + phoneNumber?: string | number; + verifyCode?: string | number; +} diff --git a/apps/services/aorta/gateway/src/auth/auth.module.ts b/apps/services/aorta/gateway/src/auth/auth.module.ts new file mode 100644 index 0000000..5dc2212 --- /dev/null +++ b/apps/services/aorta/gateway/src/auth/auth.module.ts @@ -0,0 +1,23 @@ +import { Module, UseFilters, UseGuards } from '@nestjs/common'; +import { AuthController } from './auth.controller'; +import { AuthService } from './auth.service'; +import { ClientsModule, Transport } from '@nestjs/microservices'; + +@Module({ + imports: [ + ClientsModule.register([ + { + name: 'Client', + transport: Transport.NATS, + options: { + servers: ['nats://localhost:4222'], + maxReconnectAttempts: 5, + reconnectTimeWait: 1000, + }, + }, + ]), + ], + controllers: [AuthController], + providers: [AuthService], +}) +export class AuthModule {} diff --git a/apps/services/aorta/gateway/src/auth/auth.service.ts b/apps/services/aorta/gateway/src/auth/auth.service.ts new file mode 100644 index 0000000..a41c649 --- /dev/null +++ b/apps/services/aorta/gateway/src/auth/auth.service.ts @@ -0,0 +1,4 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class AuthService {} diff --git a/apps/services/aorta/gateway/src/constant.ts b/apps/services/aorta/gateway/src/constant.ts new file mode 100644 index 0000000..e69de29 diff --git a/apps/services/aorta/gateway/src/db/db.module.ts b/apps/services/aorta/gateway/src/db/db.module.ts new file mode 100644 index 0000000..1c8a0ae --- /dev/null +++ b/apps/services/aorta/gateway/src/db/db.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; +import { MysqlProvider } from './mysql.provider'; + +@Module({ + providers: [...MysqlProvider], + exports: [...MysqlProvider], +}) +export class DbModule {} diff --git a/apps/services/aorta/gateway/src/db/mysql.provider.ts b/apps/services/aorta/gateway/src/db/mysql.provider.ts new file mode 100644 index 0000000..9561359 --- /dev/null +++ b/apps/services/aorta/gateway/src/db/mysql.provider.ts @@ -0,0 +1,23 @@ +import { ConfigService } from '@nestjs/config'; +import { DataSource } from 'typeorm'; + +export const MysqlProvider = [ + { + provide: 'mysql', + useFactory: async (configService: ConfigService) => { + const host = configService.get('MYSQL_HOST'); + const port = configService.get('MYSQL_PORT'); + const username = configService.get('MYSQL_USERNAME'); + const password = configService.get('MYSQL_PASSWORD'); + const database = configService.get('MYSQL_DATABASE'); + const config = { host, port, username, password, database }; + const dataSource = new DataSource({ + ...config, + type: 'mysql', + entities: [__dirname + '/../**/*.entity{.ts,.js}'], + synchronize: true, + }); + return dataSource.initialize(); + }, + }, +]; diff --git a/apps/services/aorta/gateway/src/filter/forbid.filter.ts b/apps/services/aorta/gateway/src/filter/forbid.filter.ts new file mode 100644 index 0000000..a5675d1 --- /dev/null +++ b/apps/services/aorta/gateway/src/filter/forbid.filter.ts @@ -0,0 +1,24 @@ +import { + ExceptionFilter, + Catch, + ArgumentsHost, + ForbiddenException, +} from '@nestjs/common'; +import { Response } from 'express'; + +@Catch(ForbiddenException) +export class ForbiddenExceptionFilter implements ExceptionFilter { + catch(exception: ForbiddenException, host: ArgumentsHost) { + const ctx = host.switchToHttp(); + const response = ctx.getResponse(); + const request = ctx.getRequest(); + const status = exception.getStatus(); + response.status(status).json({ + statusCode: status, + timestamp: new Date().toISOString(), + path: request.url, + }); + // 你可以设置一个重定向地址 + // response.redirect('/'); + } +} diff --git a/apps/services/aorta/gateway/src/guard/auth.guard.ts b/apps/services/aorta/gateway/src/guard/auth.guard.ts new file mode 100644 index 0000000..020f8f6 --- /dev/null +++ b/apps/services/aorta/gateway/src/guard/auth.guard.ts @@ -0,0 +1,75 @@ +import { + Injectable, + CanActivate, + ExecutionContext, + ForbiddenException, + Inject, +} from '@nestjs/common'; +import { ClientProxy } from '@nestjs/microservices'; +import { firstValueFrom } from 'rxjs'; +import { Request } from 'express'; + +@Injectable() +export class AuthGuard implements CanActivate { + constructor(@Inject('Client') private readonly client: ClientProxy) {} + + async canActivate(context: ExecutionContext): Promise { + const request: Request = context.switchToHttp().getRequest(); + + // 登录接口 + if ('/aorta/auth/signIn' === request.url) { + const { username } = request.body; + const { allow } = await this.rolePermissionAllow( + { username }, + request.url, + ); + if (!allow) throw new ForbiddenException('无权限访问'); + return true; + } + + // 获取token的配置 + const { tokenKeyInCookie, tokenResignIn, expires } = await firstValueFrom( + this.client.send({ cmd: 'cert.token.config' }, []), + ); + const tokenCipher = request.cookies[tokenKeyInCookie]; + if (!tokenCipher) throw new ForbiddenException('您没有执行此操作的权限'); + + // 1.验证token是否合法 + const { tokenValid, payload } = await firstValueFrom( + this.client.send({ cmd: 'cert.token.decode' }, tokenCipher), + ); + if (!tokenValid) throw new ForbiddenException('您没有执行此操作的权限'); + + // 2.token续签 + const { exp } = payload; + const tokenExpiredSoon = tokenResignIn * 1000 > exp * 1000 - Date.now(); + if (tokenExpiredSoon) { + const { username } = payload; + const { token: newToken } = await firstValueFrom( + this.client.send({ cmd: 'cert.token.create' }, { username }), + ); + request.res.cookie(tokenKeyInCookie, newToken, { + maxAge: expires * 1000, + httpOnly: true, + }); + } + + // 3.验证角色授权 + const { allow } = await this.rolePermissionAllow(payload, request.url); + if (!allow) throw new ForbiddenException('无权限访问'); + return true; + } + + /** + * 用户是否有权限 + */ + async rolePermissionAllow(payload: { username: string }, requestUrl: string) { + const { allow } = await firstValueFrom( + this.client.send( + { cmd: 'cert.role.authorize' }, + { user: payload, url: requestUrl }, + ), + ); + return { allow }; + } +} diff --git a/apps/services/aorta/gateway/src/main.ts b/apps/services/aorta/gateway/src/main.ts new file mode 100644 index 0000000..3ec6ff5 --- /dev/null +++ b/apps/services/aorta/gateway/src/main.ts @@ -0,0 +1,15 @@ +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app.module'; +import { ConfigService } from '@nestjs/config'; +import * as cookieParser from 'cookie-parser'; + +async function bootstrap() { + const app = await NestFactory.create(AppModule); + const configService = app.get(ConfigService); + app.use(cookieParser()); + const prefix = configService.get('GLOBAL_PREFIX'); + app.setGlobalPrefix(prefix); + const port = configService.get('PORT'); + await app.listen(port); +} +bootstrap(); diff --git a/apps/services/aorta/gateway/src/nacos/nacos.config.ts b/apps/services/aorta/gateway/src/nacos/nacos.config.ts new file mode 100644 index 0000000..47fbd98 --- /dev/null +++ b/apps/services/aorta/gateway/src/nacos/nacos.config.ts @@ -0,0 +1,12 @@ +const logger = console; + +export const serviceDiscovery = { + logger, + serverList: '127.0.0.1:8848', + namespace: '56a3b295-f319-4ced-82b5-0df2e98cc541', +}; + +export const configurationCenter = { + namespace: '56a3b295-f319-4ced-82b5-0df2e98cc541', + serverAddr: '127.0.0.1:8848', +}; diff --git a/apps/services/aorta/gateway/src/nacos/nacos.module.ts b/apps/services/aorta/gateway/src/nacos/nacos.module.ts new file mode 100644 index 0000000..d9daedc --- /dev/null +++ b/apps/services/aorta/gateway/src/nacos/nacos.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; +import { NacosService } from './nacos.service'; + +@Module({ + providers: [NacosService], + exports: [NacosService], +}) +export class NacosModule {} diff --git a/apps/services/aorta/gateway/src/nacos/nacos.service.ts b/apps/services/aorta/gateway/src/nacos/nacos.service.ts new file mode 100644 index 0000000..4b090bc --- /dev/null +++ b/apps/services/aorta/gateway/src/nacos/nacos.service.ts @@ -0,0 +1,102 @@ +// nacos.service.ts +import { + Injectable, + OnApplicationBootstrap, + OnApplicationShutdown, +} from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { NacosConfigClient, NacosNamingClient } from 'nacos'; // ts +import { configurationCenter, serviceDiscovery } from './nacos.config'; +import * as os from 'os'; + +@Injectable() +export class NacosService + implements OnApplicationBootstrap, OnApplicationShutdown +{ + private nacosNamingClient: NacosNamingClient; + private nacosConfigClient: NacosConfigClient; + serviceName: string; + instance: { ip: string; port: number }; + group: string; + dataId: string; + constructor(private configService: ConfigService) { + this.nacosNamingClient = new NacosNamingClient(serviceDiscovery); + this.nacosConfigClient = new NacosConfigClient(configurationCenter); + this.serviceName = 'gateway'; + this.dataId = 'test'; + this.group = 'DEFAULT_GROUP'; + this.instance = { + ip: this.getServerIP(), + port: configService.get('PORT'), + }; + } + + /** + * nestjs应用被关闭前 + * @param {string} signal 'SIGTERM' | 'SIGINT' | 'SIGHUP' | 'SIGBREAK' + */ + onApplicationShutdown(signal?: string) { + if (signal) { + const { serviceName, instance, group } = this; + this.nacosNamingClient.deregisterInstance(serviceName, instance, group); + this.nacosConfigClient.close(); + } + } + + /** + * 应用完全启动&微服务也被成功启动 + */ + onApplicationBootstrap() { + const { serviceName, instance } = this; + this.nacosNamingClient.registerInstance(serviceName, instance); + } + + /** + * 先于 onApplicationBootstrap + */ + async onModuleInit() { + this.nacosNamingClient.ready(); + } + + /** + * 从nacos获取最新的配置信息 + */ + async getConfig() { + const { dataId, group } = this; + const configFromNacos = await this.nacosConfigClient.getConfig( + dataId, + group, + ); + return configFromNacos; + } + + /** + * 订阅配置中心,当远程修改nacos的配置时,触发 + */ + async subscribeConfiguration() { + const { dataId, group } = this; + this.nacosConfigClient.subscribe( + { + dataId, + group, + }, + (content) => console.log('content', content), + ); + } + + getServerIP(): string { + const networkInterfaces = os.networkInterfaces(); + for (const name of Object.keys(networkInterfaces)) { + for (const iface of networkInterfaces[name]) { + // 跳过IPv6和内部地址 + if ('IPv4' !== iface.family || iface.internal !== false) { + continue; + } + + // 返回第一个找到的IPv4地址 + return iface.address; + } + } + return 'localhost'; // 如果找不到外部IPv4地址,返回localhost + } +} diff --git a/apps/services/aorta/gateway/src/report/report.config.ts b/apps/services/aorta/gateway/src/report/report.config.ts new file mode 100644 index 0000000..cbcec14 --- /dev/null +++ b/apps/services/aorta/gateway/src/report/report.config.ts @@ -0,0 +1,8 @@ +export const clientConfig = { + bucketName: 'test', + endPoint: 'localhost', + port: 19000, + useSSL: false, + accessKey: 'KqlCqvg8BBGVjrv82kY7', + secretKey: 'XjMjao8enBuAPM9R88gsn7dksjKh34RitIPEQIQz', +}; diff --git a/apps/services/aorta/gateway/src/report/report.controller.ts b/apps/services/aorta/gateway/src/report/report.controller.ts new file mode 100644 index 0000000..1ea664e --- /dev/null +++ b/apps/services/aorta/gateway/src/report/report.controller.ts @@ -0,0 +1,55 @@ +import { + Controller, + Get, + Inject, + Param, + Post, + Res, + UploadedFile, + UseInterceptors, +} from '@nestjs/common'; +import { ClientProxy } from '@nestjs/microservices'; +import { FileInterceptor } from '@nestjs/platform-express'; +import { getFileExt } from './report.util'; +import { clientConfig } from './report.config'; +import { MinioOSS } from '@tavi/oss'; +import { Response } from 'express'; + +@Controller('report') +export class ReportController { + constructor(@Inject('Client') private client: ClientProxy) {} + + @Post('/upload') + @UseInterceptors(FileInterceptor('file')) + async report(@UploadedFile() file: Express.Multer.File) { + try { + const { buffer, originalname } = file; + const objectName = Date.now() + '.' + getFileExt(originalname); + const { bucketName, ...config } = clientConfig; + const minio = new MinioOSS(config); + const res = await minio.put({ + file: buffer, + objectName, + bucketName, + }); + return { res, objectName }; + } catch (error) { + console.log('error', error); + } + } + + @Get('/img/:name') + getReportImage(@Param('name') objectName: string, @Res() res: Response) { + const { bucketName, ...config } = clientConfig; + const minio = new MinioOSS(config); + minio.client.getObject('test', objectName, (err, dataStream) => { + if (err) return res.status(500).send(err); + dataStream.pipe(res); + }); + } + + @Get('/root') + async root() { + return '123'; + } +} diff --git a/apps/services/aorta/gateway/src/report/report.module.ts b/apps/services/aorta/gateway/src/report/report.module.ts new file mode 100644 index 0000000..21f50b3 --- /dev/null +++ b/apps/services/aorta/gateway/src/report/report.module.ts @@ -0,0 +1,7 @@ +import { Module } from '@nestjs/common'; +import { ReportService } from './report.service'; + +@Module({ + providers: [ReportService], +}) +export class ReportModule {} diff --git a/apps/services/aorta/gateway/src/report/report.service.ts b/apps/services/aorta/gateway/src/report/report.service.ts new file mode 100644 index 0000000..989bd98 --- /dev/null +++ b/apps/services/aorta/gateway/src/report/report.service.ts @@ -0,0 +1,4 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class ReportService {} diff --git a/apps/services/aorta/gateway/src/report/report.util.ts b/apps/services/aorta/gateway/src/report/report.util.ts new file mode 100644 index 0000000..c3ea66b --- /dev/null +++ b/apps/services/aorta/gateway/src/report/report.util.ts @@ -0,0 +1,18 @@ +import { extname } from 'path'; + +export const editFileName = (req, file, callback) => { + const fileExtName = extname(file.originalname); + const randomName = Date.now(); + callback(null, `${randomName}${fileExtName}`); +}; + +export const getFileExt = (filename: string): string | null => { + // 文件名为空或者只包含点时,返回 null + if (!filename || filename.trim().startsWith('.')) return null; + // 使用 lastIndexOf 获取最后一个点的位置,以支持文件名中存在多个点的情况 + const pos = filename.lastIndexOf('.'); + // 如果没有找到点或者点在文件名的最后一位,返回 null + if (pos === -1 || pos === filename.length - 1) return null; + // 返回后缀名,不包括点 + return filename.substring(pos + 1); +}; diff --git a/apps/services/aorta/gateway/tsconfig.build.json b/apps/services/aorta/gateway/tsconfig.build.json new file mode 100644 index 0000000..64f86c6 --- /dev/null +++ b/apps/services/aorta/gateway/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] +} diff --git a/apps/services/aorta/gateway/tsconfig.json b/apps/services/aorta/gateway/tsconfig.json new file mode 100644 index 0000000..95f5641 --- /dev/null +++ b/apps/services/aorta/gateway/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "ES2021", + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": false, + "noImplicitAny": false, + "strictBindCallApply": false, + "forceConsistentCasingInFileNames": false, + "noFallthroughCasesInSwitch": false + } +} diff --git a/apps/services/aorta/report/.env.dev b/apps/services/aorta/report/.env.dev new file mode 100644 index 0000000..7bef276 --- /dev/null +++ b/apps/services/aorta/report/.env.dev @@ -0,0 +1 @@ +PORT=12345 \ No newline at end of file diff --git a/apps/services/aorta/report/.env.prod b/apps/services/aorta/report/.env.prod new file mode 100644 index 0000000..a8fcff2 --- /dev/null +++ b/apps/services/aorta/report/.env.prod @@ -0,0 +1 @@ +PORT=22345 \ No newline at end of file diff --git a/apps/services/aorta/report/.eslintrc.js b/apps/services/aorta/report/.eslintrc.js new file mode 100644 index 0000000..259de13 --- /dev/null +++ b/apps/services/aorta/report/.eslintrc.js @@ -0,0 +1,25 @@ +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.json', + tsconfigRootDir: __dirname, + sourceType: 'module', + }, + plugins: ['@typescript-eslint/eslint-plugin'], + extends: [ + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + root: true, + env: { + node: true, + jest: true, + }, + ignorePatterns: ['.eslintrc.js'], + rules: { + '@typescript-eslint/interface-name-prefix': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-explicit-any': 'off', + }, +}; diff --git a/apps/services/aorta/report/.gitignore b/apps/services/aorta/report/.gitignore new file mode 100644 index 0000000..22f55ad --- /dev/null +++ b/apps/services/aorta/report/.gitignore @@ -0,0 +1,35 @@ +# compiled output +/dist +/node_modules + +# Logs +logs +*.log +npm-debug.log* +pnpm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# OS +.DS_Store + +# Tests +/coverage +/.nyc_output + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json \ No newline at end of file diff --git a/apps/services/aorta/report/.prettierrc b/apps/services/aorta/report/.prettierrc new file mode 100644 index 0000000..dcb7279 --- /dev/null +++ b/apps/services/aorta/report/.prettierrc @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "trailingComma": "all" +} \ No newline at end of file diff --git a/apps/services/aorta/report/README.md b/apps/services/aorta/report/README.md new file mode 100644 index 0000000..f5aa86c --- /dev/null +++ b/apps/services/aorta/report/README.md @@ -0,0 +1,73 @@ +

+ Nest Logo +

+ +[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 +[circleci-url]: https://circleci.com/gh/nestjs/nest + +

A progressive Node.js framework for building efficient and scalable server-side applications.

+

+NPM Version +Package License +NPM Downloads +CircleCI +Coverage +Discord +Backers on Open Collective +Sponsors on Open Collective + + Support us + +

+ + +## Description + +[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. + +## Installation + +```bash +$ pnpm install +``` + +## Running the app + +```bash +# development +$ pnpm run start + +# watch mode +$ pnpm run start:dev + +# production mode +$ pnpm run start:prod +``` + +## Test + +```bash +# unit tests +$ pnpm run test + +# e2e tests +$ pnpm run test:e2e + +# test coverage +$ pnpm run test:cov +``` + +## Support + +Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). + +## Stay in touch + +- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) +- Website - [https://nestjs.com](https://nestjs.com/) +- Twitter - [@nestframework](https://twitter.com/nestframework) + +## License + +Nest is [MIT licensed](LICENSE). diff --git a/apps/services/aorta/report/nest-cli.json b/apps/services/aorta/report/nest-cli.json new file mode 100644 index 0000000..f9aa683 --- /dev/null +++ b/apps/services/aorta/report/nest-cli.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/nest-cli", + "collection": "@nestjs/schematics", + "sourceRoot": "src", + "compilerOptions": { + "deleteOutDir": true + } +} diff --git a/apps/services/aorta/report/package.json b/apps/services/aorta/report/package.json new file mode 100644 index 0000000..d41be91 --- /dev/null +++ b/apps/services/aorta/report/package.json @@ -0,0 +1,53 @@ +{ + "name": "@tavi/report-web", + "version": "1.0.0", + "description": "报告服务", + "scripts": { + "build": "nest build", + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", + "start": "nest start", + "start:dev": "cross-env NODE_ENV=dev nest start --watch", + "start:debug": "nest start --debug --watch", + "start:prod": "cross-env NODE_ENV=prod node dist/main", + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix" + }, + "dependencies": { + "@nestjs/common": "^9.0.0", + "@nestjs/core": "^9.0.0", + "@nestjs/config": "2.3.2", + "@nestjs/jwt": "10.0.3", + "@nestjs/axios": "2.0.0", + "@nestjs/microservices": "10.0.5", + "@nestjs/platform-express": "^9.0.0", + "reflect-metadata": "^0.1.13", + "cookie-parser": "1.4.6", + "cross-env": "7.0.3", + "js-yaml": "4.1.0", + "rxjs": "7.8.1", + "typeorm": "0.3.16", + "md5": "2.3.0", + "mysql2": "3.3.3", + "@tavi/oss": "workspace:*", + "minio": "7.1.1", + "nacos": "2.5.1" + }, + "devDependencies": { + "@nestjs/cli": "^9.0.0", + "@nestjs/schematics": "^9.0.0", + "@types/express": "^4.17.13", + "@types/node": "18.16.12", + "@types/cookie-parser": "1.4.3", + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^8.0.1", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-prettier": "^4.0.0", + "prettier": "^2.3.2", + "source-map-support": "^0.5.20", + "ts-loader": "^9.2.3", + "ts-node": "^10.0.0", + "tsconfig-paths": "4.2.0", + "typescript": "^5.0.0", + "@types/multer": "1.4.7" + } +} \ No newline at end of file diff --git a/apps/services/aorta/report/src/app.config.ts b/apps/services/aorta/report/src/app.config.ts new file mode 100644 index 0000000..cbcec14 --- /dev/null +++ b/apps/services/aorta/report/src/app.config.ts @@ -0,0 +1,8 @@ +export const clientConfig = { + bucketName: 'test', + endPoint: 'localhost', + port: 19000, + useSSL: false, + accessKey: 'KqlCqvg8BBGVjrv82kY7', + secretKey: 'XjMjao8enBuAPM9R88gsn7dksjKh34RitIPEQIQz', +}; diff --git a/apps/services/aorta/report/src/app.controller.ts b/apps/services/aorta/report/src/app.controller.ts new file mode 100644 index 0000000..225f520 --- /dev/null +++ b/apps/services/aorta/report/src/app.controller.ts @@ -0,0 +1,21 @@ +import { Controller } from '@nestjs/common'; +import { EventPattern } from '@nestjs/microservices'; +import { getFileExt } from './app.util'; +import { clientConfig } from './app.config'; +import { MinioOSS } from '@tavi/oss'; + +@Controller() +export class AppController { + @EventPattern({ cmd: 'report-upload-image' }) + async uploadImageHandler({ buffer, originalName }) { + const objectName = Date.now() + '.' + getFileExt(originalName); + const { bucketName, ...config } = clientConfig; + const minio = new MinioOSS(config); + const res = await minio.put({ + file: buffer, + objectName, + bucketName, + }); + return { res, objectName }; + } +} diff --git a/apps/services/aorta/report/src/app.module.ts b/apps/services/aorta/report/src/app.module.ts new file mode 100644 index 0000000..9c1a0ea --- /dev/null +++ b/apps/services/aorta/report/src/app.module.ts @@ -0,0 +1,18 @@ +import { Module } from '@nestjs/common'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; +import { ConfigModule } from '@nestjs/config'; +import { NacosModule } from './nacos/nacos.module'; + +@Module({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + envFilePath: `.env.${process.env.NODE_ENV}`, + }), + NacosModule, + ], + controllers: [AppController], + providers: [AppService], +}) +export class AppModule {} diff --git a/apps/services/aorta/report/src/app.service.ts b/apps/services/aorta/report/src/app.service.ts new file mode 100644 index 0000000..927d7cc --- /dev/null +++ b/apps/services/aorta/report/src/app.service.ts @@ -0,0 +1,8 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class AppService { + getHello(): string { + return 'Hello World!'; + } +} diff --git a/apps/services/aorta/report/src/app.util.ts b/apps/services/aorta/report/src/app.util.ts new file mode 100644 index 0000000..c3ea66b --- /dev/null +++ b/apps/services/aorta/report/src/app.util.ts @@ -0,0 +1,18 @@ +import { extname } from 'path'; + +export const editFileName = (req, file, callback) => { + const fileExtName = extname(file.originalname); + const randomName = Date.now(); + callback(null, `${randomName}${fileExtName}`); +}; + +export const getFileExt = (filename: string): string | null => { + // 文件名为空或者只包含点时,返回 null + if (!filename || filename.trim().startsWith('.')) return null; + // 使用 lastIndexOf 获取最后一个点的位置,以支持文件名中存在多个点的情况 + const pos = filename.lastIndexOf('.'); + // 如果没有找到点或者点在文件名的最后一位,返回 null + if (pos === -1 || pos === filename.length - 1) return null; + // 返回后缀名,不包括点 + return filename.substring(pos + 1); +}; diff --git a/apps/services/aorta/report/src/main.ts b/apps/services/aorta/report/src/main.ts new file mode 100644 index 0000000..14a0dc7 --- /dev/null +++ b/apps/services/aorta/report/src/main.ts @@ -0,0 +1,19 @@ +import { MicroserviceOptions, Transport } from '@nestjs/microservices'; +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app.module'; + +async function bootstrap() { + const app = await NestFactory.createMicroservice( + AppModule, + { + transport: Transport.NATS, + options: { + servers: ['nats://localhost:4222'], // 可以指定链接到多个nats的消息队列 + maxReconnectAttempts: 5, + reconnectTimeWait: 1000, + }, + }, + ); + await app.listen(); +} +bootstrap(); diff --git a/apps/services/aorta/report/src/nacos/nacos.config.ts b/apps/services/aorta/report/src/nacos/nacos.config.ts new file mode 100644 index 0000000..47fbd98 --- /dev/null +++ b/apps/services/aorta/report/src/nacos/nacos.config.ts @@ -0,0 +1,12 @@ +const logger = console; + +export const serviceDiscovery = { + logger, + serverList: '127.0.0.1:8848', + namespace: '56a3b295-f319-4ced-82b5-0df2e98cc541', +}; + +export const configurationCenter = { + namespace: '56a3b295-f319-4ced-82b5-0df2e98cc541', + serverAddr: '127.0.0.1:8848', +}; diff --git a/apps/services/aorta/report/src/nacos/nacos.module.ts b/apps/services/aorta/report/src/nacos/nacos.module.ts new file mode 100644 index 0000000..d9daedc --- /dev/null +++ b/apps/services/aorta/report/src/nacos/nacos.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; +import { NacosService } from './nacos.service'; + +@Module({ + providers: [NacosService], + exports: [NacosService], +}) +export class NacosModule {} diff --git a/apps/services/aorta/report/src/nacos/nacos.service.ts b/apps/services/aorta/report/src/nacos/nacos.service.ts new file mode 100644 index 0000000..a3248d7 --- /dev/null +++ b/apps/services/aorta/report/src/nacos/nacos.service.ts @@ -0,0 +1,102 @@ +// nacos.service.ts +import { + Injectable, + OnApplicationBootstrap, + OnApplicationShutdown, +} from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { NacosConfigClient, NacosNamingClient } from 'nacos'; // ts +import { configurationCenter, serviceDiscovery } from './nacos.config'; +import * as os from 'os'; + +@Injectable() +export class NacosService + implements OnApplicationBootstrap, OnApplicationShutdown +{ + private nacosNamingClient: NacosNamingClient; + private nacosConfigClient: NacosConfigClient; + serviceName: string; + instance: { ip: string; port: number }; + group: string; + dataId: string; + constructor(private configService: ConfigService) { + this.nacosNamingClient = new NacosNamingClient(serviceDiscovery); + this.nacosConfigClient = new NacosConfigClient(configurationCenter); + this.serviceName = 'report'; + this.dataId = 'test'; + this.group = 'DEFAULT_GROUP'; + this.instance = { + ip: this.getServerIP(), + port: configService.get('PORT') ?? 0, + }; + } + + /** + * nestjs应用被关闭前 + * @param {string} signal 'SIGTERM' | 'SIGINT' | 'SIGHUP' | 'SIGBREAK' + */ + onApplicationShutdown(signal?: string) { + if (signal) { + const { serviceName, instance, group } = this; + this.nacosNamingClient.deregisterInstance(serviceName, instance, group); + this.nacosConfigClient.close(); + } + } + + /** + * 应用完全启动&微服务也被成功启动 + */ + onApplicationBootstrap() { + const { serviceName, instance } = this; + this.nacosNamingClient.registerInstance(serviceName, instance); + } + + /** + * 先于 onApplicationBootstrap + */ + async onModuleInit() { + this.nacosNamingClient.ready(); + } + + /** + * 从nacos获取最新的配置信息 + */ + async getConfig() { + const { dataId, group } = this; + const configFromNacos = await this.nacosConfigClient.getConfig( + dataId, + group, + ); + return configFromNacos; + } + + /** + * 订阅配置中心,当远程修改nacos的配置时,触发 + */ + async subscribeConfiguration() { + const { dataId, group } = this; + this.nacosConfigClient.subscribe( + { + dataId, + group, + }, + (content) => console.log('content', content), + ); + } + + getServerIP(): string { + const networkInterfaces = os.networkInterfaces(); + for (const name of Object.keys(networkInterfaces)) { + for (const iface of networkInterfaces[name]) { + // 跳过IPv6和内部地址 + if ('IPv4' !== iface.family || iface.internal !== false) { + continue; + } + + // 返回第一个找到的IPv4地址 + return iface.address; + } + } + return 'localhost'; // 如果找不到外部IPv4地址,返回localhost + } +} diff --git a/apps/services/aorta/report/tsconfig.build.json b/apps/services/aorta/report/tsconfig.build.json new file mode 100644 index 0000000..64f86c6 --- /dev/null +++ b/apps/services/aorta/report/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] +} diff --git a/apps/services/aorta/report/tsconfig.json b/apps/services/aorta/report/tsconfig.json new file mode 100644 index 0000000..adb614c --- /dev/null +++ b/apps/services/aorta/report/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "es2017", + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": false, + "noImplicitAny": false, + "strictBindCallApply": false, + "forceConsistentCasingInFileNames": false, + "noFallthroughCasesInSwitch": false + } +} diff --git a/apps/services/cert/authenticate/.env.dev b/apps/services/cert/authenticate/.env.dev new file mode 100644 index 0000000..1679d19 --- /dev/null +++ b/apps/services/cert/authenticate/.env.dev @@ -0,0 +1,21 @@ +PORT=43124 + +# nacos中注册服务的名称 +NACOS_SERVICE_NAME=cert-authenticate +NACOS_ADDR=127.0.0.1:8848 +NACOS_NAMESPACE=56a3b295-f319-4ced-82b5-0df2e98cc541 +# nacos配置中心 +NACOS_DATAID='test' +NACOS_GROUP='DEFAULT_GROUP' + +# token配置 +JWT_SECRET=35ff73f70a2611ff7daba19ee8dd56807102b0fbdd50ea2e898f8a3f80a3f5b3 +# 过期时间 s:秒 +JWT_EXPIRES_IN=86400 +# TOKEN在cookies中的key, 保证所有业务系统都使用这个拿cookies中的token +TOKEN_KEY_IN_COOKIE=authToken +# TOKEN续签,到期前多少s +TOKEN_RESIGN_IN=3600 + +# redis redis://:password@localhost:6379/db +REDIS_URL=redis://:redis@localhost:6379/1 \ No newline at end of file diff --git a/apps/services/cert/authenticate/.env.prod b/apps/services/cert/authenticate/.env.prod new file mode 100644 index 0000000..e69de29 diff --git a/apps/services/cert/authenticate/.eslintrc.js b/apps/services/cert/authenticate/.eslintrc.js new file mode 100644 index 0000000..259de13 --- /dev/null +++ b/apps/services/cert/authenticate/.eslintrc.js @@ -0,0 +1,25 @@ +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.json', + tsconfigRootDir: __dirname, + sourceType: 'module', + }, + plugins: ['@typescript-eslint/eslint-plugin'], + extends: [ + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + root: true, + env: { + node: true, + jest: true, + }, + ignorePatterns: ['.eslintrc.js'], + rules: { + '@typescript-eslint/interface-name-prefix': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-explicit-any': 'off', + }, +}; diff --git a/apps/services/cert/authenticate/.gitignore b/apps/services/cert/authenticate/.gitignore new file mode 100644 index 0000000..22f55ad --- /dev/null +++ b/apps/services/cert/authenticate/.gitignore @@ -0,0 +1,35 @@ +# compiled output +/dist +/node_modules + +# Logs +logs +*.log +npm-debug.log* +pnpm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# OS +.DS_Store + +# Tests +/coverage +/.nyc_output + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json \ No newline at end of file diff --git a/apps/services/cert/authenticate/.prettierrc b/apps/services/cert/authenticate/.prettierrc new file mode 100644 index 0000000..dcb7279 --- /dev/null +++ b/apps/services/cert/authenticate/.prettierrc @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "trailingComma": "all" +} \ No newline at end of file diff --git a/apps/services/cert/authenticate/README.md b/apps/services/cert/authenticate/README.md new file mode 100644 index 0000000..f5aa86c --- /dev/null +++ b/apps/services/cert/authenticate/README.md @@ -0,0 +1,73 @@ +

+ Nest Logo +

+ +[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 +[circleci-url]: https://circleci.com/gh/nestjs/nest + +

A progressive Node.js framework for building efficient and scalable server-side applications.

+

+NPM Version +Package License +NPM Downloads +CircleCI +Coverage +Discord +Backers on Open Collective +Sponsors on Open Collective + + Support us + +

+ + +## Description + +[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. + +## Installation + +```bash +$ pnpm install +``` + +## Running the app + +```bash +# development +$ pnpm run start + +# watch mode +$ pnpm run start:dev + +# production mode +$ pnpm run start:prod +``` + +## Test + +```bash +# unit tests +$ pnpm run test + +# e2e tests +$ pnpm run test:e2e + +# test coverage +$ pnpm run test:cov +``` + +## Support + +Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). + +## Stay in touch + +- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) +- Website - [https://nestjs.com](https://nestjs.com/) +- Twitter - [@nestframework](https://twitter.com/nestframework) + +## License + +Nest is [MIT licensed](LICENSE). diff --git a/apps/services/cert/authenticate/nest-cli.json b/apps/services/cert/authenticate/nest-cli.json new file mode 100644 index 0000000..f9aa683 --- /dev/null +++ b/apps/services/cert/authenticate/nest-cli.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/nest-cli", + "collection": "@nestjs/schematics", + "sourceRoot": "src", + "compilerOptions": { + "deleteOutDir": true + } +} diff --git a/apps/services/cert/authenticate/package.json b/apps/services/cert/authenticate/package.json new file mode 100644 index 0000000..7280a91 --- /dev/null +++ b/apps/services/cert/authenticate/package.json @@ -0,0 +1,50 @@ +{ + "name": "@tavi/authenticate", + "version": "0.0.1", + "description": "", + "author": "", + "private": true, + "license": "UNLICENSED", + "scripts": { + "build": "nest build", + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", + "start": "nest start", + "start:dev": "cross-env NODE_ENV=dev nest start --watch", + "start:debug": "nest start --debug --watch", + "start:prod": "cross-env NODE_ENV=dev node dist/main", + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix" + }, + "dependencies": { + "@nestjs/common": "10.1.0", + "@nestjs/core": "10.1.0", + "@nestjs/platform-express": "10.1.0", + "reflect-metadata": "^0.1.13", + "@nestjs/config": "3.0.0", + "rxjs": "7.8.1", + "nats": "2.15.1", + "@nestjs/microservices": "10.0.5", + "nacos": "2.5.1", + "cross-env": "7.0.3", + "cookie-parser": "1.4.6", + "@nestjs/passport": "10.0.0", + "@nestjs/jwt": "10.1.0", + "ioredis": "5.3.2" + }, + "devDependencies": { + "@nestjs/cli": "^9.0.0", + "@nestjs/schematics": "^9.0.0", + "@types/express": "^4.17.13", + "@types/node": "18.16.12", + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^8.0.1", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-prettier": "^4.0.0", + "prettier": "^2.3.2", + "source-map-support": "^0.5.20", + "ts-loader": "^9.2.3", + "ts-node": "^10.0.0", + "tsconfig-paths": "4.2.0", + "typescript": "^5.0.0" + } +} \ No newline at end of file diff --git a/apps/services/cert/authenticate/src/app.controller.ts b/apps/services/cert/authenticate/src/app.controller.ts new file mode 100644 index 0000000..0032542 --- /dev/null +++ b/apps/services/cert/authenticate/src/app.controller.ts @@ -0,0 +1,65 @@ +import { EventPattern } from '@nestjs/microservices'; +import { RedisService } from './redis/redis.service'; +import { ConfigService } from '@nestjs/config'; +import { Controller } from '@nestjs/common'; +import { JwtService } from '@nestjs/jwt'; + +@Controller() +export class AppController { + constructor( + private configService: ConfigService, + private redisService: RedisService, + private jwtService: JwtService, + ) {} + + /** + * 给业务系统登录接口进行token签发,注入用户的角色信息 + * @description redis的EX、cookie的maxAge(ms)、jwt的expiresIn,三者保持一致 + */ + @EventPattern({ cmd: 'cert.token.create' }) + async createToken(payload) { + const { username } = payload; + const token = await this.jwtService.sign(payload); + this.redisService.setToken(username, token); + return { token }; + } + + /** + * 检查token有效性 && 解token + * @description 业务系统的guard对请求token进行拦截,校验每次请求token是否合法&是否在redis中 + */ + @EventPattern({ cmd: 'cert.token.decode' }) + async decodeToken( + token: string, + ): Promise<{ tokenValid: boolean; payload: unknown; error?: unknown }> { + try { + await this.jwtService.verify(token); + const payload = (await this.jwtService.decode(token)) as any; + const { username } = payload; + const inRedis = await this.redisService.tokenInRedis(username); + return { tokenValid: true && inRedis, payload }; + } catch (error) { + return { tokenValid: false, payload: null, error }; + } + } + + /** + * 获取token在cookie中存储的key + * @description cookie的maxAge单位是毫秒,如果给cookie使用expires需要 x1000 + */ + @EventPattern({ cmd: 'cert.token.config' }) + async tokenConfig() { + return { + tokenResignIn: this.configService.get('TOKEN_RESIGN_IN'), + tokenKeyInCookie: this.configService.get('TOKEN_KEY_IN_COOKIE'), + expires: Number(this.configService.get('JWT_EXPIRES_IN')), + }; + } + + @EventPattern({ cmd: 'cert.token.deprecated' }) + async removeToken(payload) { + const { username } = payload; + console.log('username', username); + return await this.redisService.removeToken(username); + } +} diff --git a/apps/services/cert/authenticate/src/app.module.ts b/apps/services/cert/authenticate/src/app.module.ts new file mode 100644 index 0000000..314729e --- /dev/null +++ b/apps/services/cert/authenticate/src/app.module.ts @@ -0,0 +1,29 @@ +import { Module } from '@nestjs/common'; +import { AppController } from './app.controller'; +import { NacosModule } from './nacos/nacos.module'; +import { ConfigModule, ConfigService } from '@nestjs/config'; +import { JwtModule } from '@nestjs/jwt'; +import { RedisModule } from './redis/redis.module'; + +@Module({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + envFilePath: `.env.${process.env.NODE_ENV}`, + }), + NacosModule, + JwtModule.registerAsync({ + imports: [ConfigModule], + inject: [ConfigService], + useFactory: async (configService: ConfigService) => ({ + secret: configService.get('JWT_SECRET'), + signOptions: { + expiresIn: configService.get('JWT_EXPIRES_IN') + 's', + }, + }), + }), + RedisModule, + ], + controllers: [AppController], +}) +export class AppModule {} diff --git a/apps/services/cert/authenticate/src/main.ts b/apps/services/cert/authenticate/src/main.ts new file mode 100644 index 0000000..14a0dc7 --- /dev/null +++ b/apps/services/cert/authenticate/src/main.ts @@ -0,0 +1,19 @@ +import { MicroserviceOptions, Transport } from '@nestjs/microservices'; +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app.module'; + +async function bootstrap() { + const app = await NestFactory.createMicroservice( + AppModule, + { + transport: Transport.NATS, + options: { + servers: ['nats://localhost:4222'], // 可以指定链接到多个nats的消息队列 + maxReconnectAttempts: 5, + reconnectTimeWait: 1000, + }, + }, + ); + await app.listen(); +} +bootstrap(); diff --git a/apps/services/cert/authenticate/src/nacos/nacos.module.ts b/apps/services/cert/authenticate/src/nacos/nacos.module.ts new file mode 100644 index 0000000..d9daedc --- /dev/null +++ b/apps/services/cert/authenticate/src/nacos/nacos.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; +import { NacosService } from './nacos.service'; + +@Module({ + providers: [NacosService], + exports: [NacosService], +}) +export class NacosModule {} diff --git a/apps/services/cert/authenticate/src/nacos/nacos.service.ts b/apps/services/cert/authenticate/src/nacos/nacos.service.ts new file mode 100644 index 0000000..4a2e7f9 --- /dev/null +++ b/apps/services/cert/authenticate/src/nacos/nacos.service.ts @@ -0,0 +1,108 @@ +// nacos.service.ts +import { + Injectable, + OnApplicationBootstrap, + OnApplicationShutdown, +} from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { NacosConfigClient, NacosNamingClient } from 'nacos'; // ts +import * as os from 'os'; + +@Injectable() +export class NacosService + implements OnApplicationBootstrap, OnApplicationShutdown +{ + private nacosNamingClient: NacosNamingClient; + private nacosConfigClient: NacosConfigClient; + serviceName: string; + instance: { ip: string; port: number }; + group: string; + dataId: string; + constructor(private configService: ConfigService) { + this.nacosNamingClient = new NacosNamingClient({ + logger: console, + serverList: configService.get('NACOS_ADDR'), + namespace: configService.get('NACOS_NAMESPACE'), + }); + this.nacosConfigClient = new NacosConfigClient({ + namespace: configService.get('NACOS_NAMESPACE'), + serverAddr: configService.get('NACOS_ADDR'), + }); + this.serviceName = configService.get('NACOS_SERVICE_NAME'); + this.dataId = configService.get('NACOS_DATAID'); + this.group = configService.get('NACOS_GROUP'); + this.instance = { + ip: this.getServerIP(), + port: configService.get('PORT'), + }; + } + + /** + * nestjs应用被关闭前 + * @param {string} signal 'SIGTERM' | 'SIGINT' | 'SIGHUP' | 'SIGBREAK' + */ + onApplicationShutdown(signal?: string) { + if (signal) { + const { serviceName, instance, group } = this; + this.nacosNamingClient.deregisterInstance(serviceName, instance, group); + this.nacosConfigClient.close(); + } + } + + /** + * 应用完全启动&微服务也被成功启动 + */ + onApplicationBootstrap() { + const { serviceName, instance } = this; + this.nacosNamingClient.registerInstance(serviceName, instance); + } + + /** + * 先于 onApplicationBootstrap + */ + async onModuleInit() { + this.nacosNamingClient.ready(); + } + + /** + * 从nacos获取最新的配置信息 + */ + async getConfig() { + const { dataId, group } = this; + const configFromNacos = await this.nacosConfigClient.getConfig( + dataId, + group, + ); + return configFromNacos; + } + + /** + * 订阅配置中心,当远程修改nacos的配置时,触发 + */ + async subscribeConfiguration() { + const { dataId, group } = this; + this.nacosConfigClient.subscribe( + { + dataId, + group, + }, + (content) => console.log('content', content), + ); + } + + getServerIP(): string { + const networkInterfaces = os.networkInterfaces(); + for (const name of Object.keys(networkInterfaces)) { + for (const iface of networkInterfaces[name]) { + // 跳过IPv6和内部地址 + if ('IPv4' !== iface.family || iface.internal !== false) { + continue; + } + + // 返回第一个找到的IPv4地址 + return iface.address; + } + } + return 'localhost'; // 如果找不到外部IPv4地址,返回localhost + } +} diff --git a/apps/services/cert/authenticate/src/redis/redis.entity.ts b/apps/services/cert/authenticate/src/redis/redis.entity.ts new file mode 100644 index 0000000..c178f46 --- /dev/null +++ b/apps/services/cert/authenticate/src/redis/redis.entity.ts @@ -0,0 +1,14 @@ +export class RedisToken { + private id: string; + constructor({ id }: { id: string }) { + this.id = id; + } + + /** + * 生成redis存储用户token的key + * @description user:token:${id} + */ + key() { + return `token:user:${this.id}`; + } +} diff --git a/apps/services/cert/authenticate/src/redis/redis.module.ts b/apps/services/cert/authenticate/src/redis/redis.module.ts new file mode 100644 index 0000000..55332bd --- /dev/null +++ b/apps/services/cert/authenticate/src/redis/redis.module.ts @@ -0,0 +1,20 @@ +import { Module } from '@nestjs/common'; +import { RedisService } from './redis.service'; +import { ConfigService } from '@nestjs/config'; +import Redis from 'ioredis'; + +@Module({ + imports: [], + providers: [ + RedisService, + { + provide: 'Redis', + useFactory: (configService: ConfigService) => { + return new Redis(configService.get('REDIS_URL')); + }, + inject: [ConfigService], + }, + ], + exports: ['Redis', RedisService], +}) +export class RedisModule {} diff --git a/apps/services/cert/authenticate/src/redis/redis.service.ts b/apps/services/cert/authenticate/src/redis/redis.service.ts new file mode 100644 index 0000000..d14e497 --- /dev/null +++ b/apps/services/cert/authenticate/src/redis/redis.service.ts @@ -0,0 +1,49 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { Redis } from 'ioredis'; +import { RedisToken } from './redis.entity'; +import { ConfigService } from '@nestjs/config'; + +@Injectable() +export class RedisService { + constructor( + @Inject('Redis') private readonly redis: Redis, + private configService: ConfigService, + ) {} + + /** + * 存储用户的token到redis中 + * @param {string|number} id 用户的唯一id、userId || openId + * @param {string} token jwt生成的字符串 + */ + setToken(username: string, token: string) { + const redisKey = new RedisToken({ id: username }).key(); + const expireSeconds = Number(this.configService.get('JWT_EXPIRES_IN')); + this.redis.set(redisKey, token, 'EX', expireSeconds); + } + + /** + * 获取redis中用户的token + * @param {string|number} key 用户的唯一id、userId || openId + * @param {string} token jwt生成的字符串 + */ + async getToken(key: string | number) { + const redisKey = new RedisToken({ id: String(key) }).key(); + return await this.redis.get(redisKey); + } + + /** + * 判断redis key是否在在redis当中 + */ + async tokenInRedis(key: string | number) { + const redisKey = new RedisToken({ id: String(key) }).key(); + return (await this.redis.exists(redisKey)) === 1; + } + + /** + * 移除token + */ + async removeToken(key: string | number) { + const redisKey = new RedisToken({ id: String(key) }).key(); + return await this.redis.del(redisKey); + } +} diff --git a/apps/services/cert/authenticate/tsconfig.build.json b/apps/services/cert/authenticate/tsconfig.build.json new file mode 100644 index 0000000..64f86c6 --- /dev/null +++ b/apps/services/cert/authenticate/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] +} diff --git a/apps/services/cert/authenticate/tsconfig.json b/apps/services/cert/authenticate/tsconfig.json new file mode 100644 index 0000000..adb614c --- /dev/null +++ b/apps/services/cert/authenticate/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "es2017", + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": false, + "noImplicitAny": false, + "strictBindCallApply": false, + "forceConsistentCasingInFileNames": false, + "noFallthroughCasesInSwitch": false + } +} diff --git a/apps/services/cert/authorize/.env.dev b/apps/services/cert/authorize/.env.dev new file mode 100644 index 0000000..9faf325 --- /dev/null +++ b/apps/services/cert/authorize/.env.dev @@ -0,0 +1,8 @@ +PORT=33124 +# nacos中注册服务的名称 +NACOS_SERVICE_NAME=cert-authorize +NACOS_ADDR=127.0.0.1:8848 +NACOS_NAMESPACE=56a3b295-f319-4ced-82b5-0df2e98cc541 +# nacos配置中心 +NACOS_DATAID='test' +NACOS_GROUP='DEFAULT_GROUP' \ No newline at end of file diff --git a/apps/services/cert/authorize/.env.prod b/apps/services/cert/authorize/.env.prod new file mode 100644 index 0000000..e69de29 diff --git a/apps/services/cert/authorize/.eslintrc.js b/apps/services/cert/authorize/.eslintrc.js new file mode 100644 index 0000000..259de13 --- /dev/null +++ b/apps/services/cert/authorize/.eslintrc.js @@ -0,0 +1,25 @@ +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.json', + tsconfigRootDir: __dirname, + sourceType: 'module', + }, + plugins: ['@typescript-eslint/eslint-plugin'], + extends: [ + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + root: true, + env: { + node: true, + jest: true, + }, + ignorePatterns: ['.eslintrc.js'], + rules: { + '@typescript-eslint/interface-name-prefix': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-explicit-any': 'off', + }, +}; diff --git a/apps/services/cert/authorize/.gitignore b/apps/services/cert/authorize/.gitignore new file mode 100644 index 0000000..22f55ad --- /dev/null +++ b/apps/services/cert/authorize/.gitignore @@ -0,0 +1,35 @@ +# compiled output +/dist +/node_modules + +# Logs +logs +*.log +npm-debug.log* +pnpm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# OS +.DS_Store + +# Tests +/coverage +/.nyc_output + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json \ No newline at end of file diff --git a/apps/services/cert/authorize/.prettierrc b/apps/services/cert/authorize/.prettierrc new file mode 100644 index 0000000..dcb7279 --- /dev/null +++ b/apps/services/cert/authorize/.prettierrc @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "trailingComma": "all" +} \ No newline at end of file diff --git a/apps/services/cert/authorize/README.md b/apps/services/cert/authorize/README.md new file mode 100644 index 0000000..f5aa86c --- /dev/null +++ b/apps/services/cert/authorize/README.md @@ -0,0 +1,73 @@ +

+ Nest Logo +

+ +[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 +[circleci-url]: https://circleci.com/gh/nestjs/nest + +

A progressive Node.js framework for building efficient and scalable server-side applications.

+

+NPM Version +Package License +NPM Downloads +CircleCI +Coverage +Discord +Backers on Open Collective +Sponsors on Open Collective + + Support us + +

+ + +## Description + +[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. + +## Installation + +```bash +$ pnpm install +``` + +## Running the app + +```bash +# development +$ pnpm run start + +# watch mode +$ pnpm run start:dev + +# production mode +$ pnpm run start:prod +``` + +## Test + +```bash +# unit tests +$ pnpm run test + +# e2e tests +$ pnpm run test:e2e + +# test coverage +$ pnpm run test:cov +``` + +## Support + +Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). + +## Stay in touch + +- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) +- Website - [https://nestjs.com](https://nestjs.com/) +- Twitter - [@nestframework](https://twitter.com/nestframework) + +## License + +Nest is [MIT licensed](LICENSE). diff --git a/apps/services/cert/authorize/nest-cli.json b/apps/services/cert/authorize/nest-cli.json new file mode 100644 index 0000000..f9aa683 --- /dev/null +++ b/apps/services/cert/authorize/nest-cli.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/nest-cli", + "collection": "@nestjs/schematics", + "sourceRoot": "src", + "compilerOptions": { + "deleteOutDir": true + } +} diff --git a/apps/services/cert/authorize/package.json b/apps/services/cert/authorize/package.json new file mode 100644 index 0000000..c48ea4e --- /dev/null +++ b/apps/services/cert/authorize/package.json @@ -0,0 +1,52 @@ +{ + "name": "@tavi/authorize", + "version": "0.0.1", + "description": "", + "author": "", + "private": true, + "license": "UNLICENSED", + "scripts": { + "build": "nest build", + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", + "start": "nest start", + "start:dev": "cross-env NODE_ENV=dev nest start --watch", + "start:debug": "nest start --debug --watch", + "start:prod": "cross-env NODE_ENV=dev node dist/main", + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix" + }, + "dependencies": { + "@nestjs/common": "10.1.0", + "@nestjs/core": "10.1.0", + "@nestjs/platform-express": "10.1.0", + "reflect-metadata": "^0.1.13", + "@nestjs/config": "3.0.0", + "rxjs": "7.8.1", + "nats": "2.15.1", + "@nestjs/microservices": "10.0.5", + "nacos": "2.5.1", + "cross-env": "7.0.3", + "cookie-parser": "1.4.6", + "@casl/ability": "6.5.0", + "typeorm": "0.3.17", + "@nestjs/typeorm": "10.0.0", + "bcrypt": "5.1.0", + "minimatch": "9.0.3" + }, + "devDependencies": { + "@nestjs/cli": "^9.0.0", + "@nestjs/schematics": "^9.0.0", + "@types/express": "^4.17.13", + "@types/node": "18.16.12", + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^8.0.1", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-prettier": "^4.0.0", + "prettier": "^2.3.2", + "source-map-support": "^0.5.20", + "ts-loader": "^9.2.3", + "ts-node": "^10.0.0", + "tsconfig-paths": "4.2.0", + "typescript": "^5.0.0" + } +} \ No newline at end of file diff --git a/apps/services/cert/authorize/src/app.controller.ts b/apps/services/cert/authorize/src/app.controller.ts new file mode 100644 index 0000000..965f241 --- /dev/null +++ b/apps/services/cert/authorize/src/app.controller.ts @@ -0,0 +1,70 @@ +import { Controller } from '@nestjs/common'; +import { AppService } from './app.service'; +import { EventPattern, MessagePattern } from '@nestjs/microservices'; +import { RbacService } from './rbac/rbac.service'; + +@Controller() +export class AppController { + constructor( + private readonly appService: AppService, + private readonly rbacService: RbacService, + ) {} + + @EventPattern({ cmd: 'cert.authorize' }) + async authorize(payload) { + console.log('获取user的token,进行payload权限的验证', payload); + return false; + } + + @EventPattern({ cmd: 'cert.init.role.admin' }) + async initRole() { + await this.rbacService.initSuperAdminRole(); + await this.rbacService.initSuperAdminAccount(); + } + + @EventPattern({ cmd: 'cert.create.role' }) + async createRole(payload) { + return await this.rbacService.createRole(payload); + } + + @EventPattern({ cmd: 'cert.remove.role' }) + async removeRole(payload) { + return await this.rbacService.removeRole(payload); + } + + @EventPattern({ cmd: 'cert.find.role.all' }) + async findAllRole() { + return await this.rbacService.findAllRole(); + } + + @EventPattern({ cmd: 'cert.init.permission.resource' }) + async initPermission(payload) { + await this.rbacService.initPermission(payload); + } + + @EventPattern({ cmd: 'cert.find.role.permission' }) + async findRolePermission(payload) { + return await this.rbacService.findRolePermission(payload); + } + + @EventPattern({ cmd: 'cert.update.role.permissions' }) + async updateRolePermissions(payload) { + return await this.rbacService.updateRolePermissions(payload); + } + + @EventPattern({ cmd: 'cert.update.role' }) + async updateRole(payload) { + return await this.rbacService.updateRole(payload); + } + + @EventPattern({ cmd: 'cert.find.all.user' }) + async findAllUser() { + return await this.rbacService.findAllUser(); + } + + @EventPattern({ cmd: 'cert.role.authorize' }) + async roleAuthorize({ user, url }) { + const allow = await this.rbacService.roleAuthorize(user, url); + return { allow }; + } +} diff --git a/apps/services/cert/authorize/src/app.module.ts b/apps/services/cert/authorize/src/app.module.ts new file mode 100644 index 0000000..c5f50f2 --- /dev/null +++ b/apps/services/cert/authorize/src/app.module.ts @@ -0,0 +1,28 @@ +import { Module } from '@nestjs/common'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; +import { NacosModule } from './nacos/nacos.module'; +import { ConfigModule } from '@nestjs/config'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { RbacModule } from './rbac/rbac.module'; +import { User } from './rbac/entity/user.entity'; +import { Role } from './rbac/entity/role.entity'; +import { Permission } from './rbac/entity/permission.entity'; +import { UserModule } from './user/user.module'; + +@Module({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + envFilePath: `.env.${process.env.NODE_ENV}`, + }), + NacosModule, + RbacModule, + TypeOrmModule.forFeature([User, Role, Permission]), + UserModule, + ], + controllers: [AppController], + providers: [AppService], + exports: [], +}) +export class AppModule {} diff --git a/apps/services/cert/authorize/src/app.service.ts b/apps/services/cert/authorize/src/app.service.ts new file mode 100644 index 0000000..1f22f2a --- /dev/null +++ b/apps/services/cert/authorize/src/app.service.ts @@ -0,0 +1,6 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; + +@Injectable() +export class AppService {} diff --git a/apps/services/cert/authorize/src/bcrypt/bcrypt.service.ts b/apps/services/cert/authorize/src/bcrypt/bcrypt.service.ts new file mode 100644 index 0000000..09281f0 --- /dev/null +++ b/apps/services/cert/authorize/src/bcrypt/bcrypt.service.ts @@ -0,0 +1,16 @@ +import * as bcrypt from 'bcrypt'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class BcryptService { + async hashPassword(password: string): Promise { + return bcrypt.hash(password, await bcrypt.genSalt(10)); + } + + async comparePassword( + password: string, + hashedPassword: string, + ): Promise { + return bcrypt.compare(password, hashedPassword); + } +} diff --git a/apps/services/cert/authorize/src/main.ts b/apps/services/cert/authorize/src/main.ts new file mode 100644 index 0000000..c39ffab --- /dev/null +++ b/apps/services/cert/authorize/src/main.ts @@ -0,0 +1,20 @@ +import { MicroserviceOptions, Transport } from '@nestjs/microservices'; +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app.module'; + +async function bootstrap() { + const app = await NestFactory.createMicroservice( + AppModule, + { + transport: Transport.NATS, + options: { + servers: ['nats://localhost:4222'], // 可以指定链接到多个nats的消息队列 + maxReconnectAttempts: 5, + reconnectTimeWait: 1000, + }, + }, + ); + + await app.listen(); +} +bootstrap(); diff --git a/apps/services/cert/authorize/src/nacos/nacos.module.ts b/apps/services/cert/authorize/src/nacos/nacos.module.ts new file mode 100644 index 0000000..d9daedc --- /dev/null +++ b/apps/services/cert/authorize/src/nacos/nacos.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; +import { NacosService } from './nacos.service'; + +@Module({ + providers: [NacosService], + exports: [NacosService], +}) +export class NacosModule {} diff --git a/apps/services/cert/authorize/src/nacos/nacos.service.ts b/apps/services/cert/authorize/src/nacos/nacos.service.ts new file mode 100644 index 0000000..4a2e7f9 --- /dev/null +++ b/apps/services/cert/authorize/src/nacos/nacos.service.ts @@ -0,0 +1,108 @@ +// nacos.service.ts +import { + Injectable, + OnApplicationBootstrap, + OnApplicationShutdown, +} from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { NacosConfigClient, NacosNamingClient } from 'nacos'; // ts +import * as os from 'os'; + +@Injectable() +export class NacosService + implements OnApplicationBootstrap, OnApplicationShutdown +{ + private nacosNamingClient: NacosNamingClient; + private nacosConfigClient: NacosConfigClient; + serviceName: string; + instance: { ip: string; port: number }; + group: string; + dataId: string; + constructor(private configService: ConfigService) { + this.nacosNamingClient = new NacosNamingClient({ + logger: console, + serverList: configService.get('NACOS_ADDR'), + namespace: configService.get('NACOS_NAMESPACE'), + }); + this.nacosConfigClient = new NacosConfigClient({ + namespace: configService.get('NACOS_NAMESPACE'), + serverAddr: configService.get('NACOS_ADDR'), + }); + this.serviceName = configService.get('NACOS_SERVICE_NAME'); + this.dataId = configService.get('NACOS_DATAID'); + this.group = configService.get('NACOS_GROUP'); + this.instance = { + ip: this.getServerIP(), + port: configService.get('PORT'), + }; + } + + /** + * nestjs应用被关闭前 + * @param {string} signal 'SIGTERM' | 'SIGINT' | 'SIGHUP' | 'SIGBREAK' + */ + onApplicationShutdown(signal?: string) { + if (signal) { + const { serviceName, instance, group } = this; + this.nacosNamingClient.deregisterInstance(serviceName, instance, group); + this.nacosConfigClient.close(); + } + } + + /** + * 应用完全启动&微服务也被成功启动 + */ + onApplicationBootstrap() { + const { serviceName, instance } = this; + this.nacosNamingClient.registerInstance(serviceName, instance); + } + + /** + * 先于 onApplicationBootstrap + */ + async onModuleInit() { + this.nacosNamingClient.ready(); + } + + /** + * 从nacos获取最新的配置信息 + */ + async getConfig() { + const { dataId, group } = this; + const configFromNacos = await this.nacosConfigClient.getConfig( + dataId, + group, + ); + return configFromNacos; + } + + /** + * 订阅配置中心,当远程修改nacos的配置时,触发 + */ + async subscribeConfiguration() { + const { dataId, group } = this; + this.nacosConfigClient.subscribe( + { + dataId, + group, + }, + (content) => console.log('content', content), + ); + } + + getServerIP(): string { + const networkInterfaces = os.networkInterfaces(); + for (const name of Object.keys(networkInterfaces)) { + for (const iface of networkInterfaces[name]) { + // 跳过IPv6和内部地址 + if ('IPv4' !== iface.family || iface.internal !== false) { + continue; + } + + // 返回第一个找到的IPv4地址 + return iface.address; + } + } + return 'localhost'; // 如果找不到外部IPv4地址,返回localhost + } +} diff --git a/apps/services/cert/authorize/src/rbac/entity/permission.entity.ts b/apps/services/cert/authorize/src/rbac/entity/permission.entity.ts new file mode 100644 index 0000000..7a8d93c --- /dev/null +++ b/apps/services/cert/authorize/src/rbac/entity/permission.entity.ts @@ -0,0 +1,21 @@ +import { Entity, Column, PrimaryColumn } from 'typeorm'; + +@Entity() +export class Permission { + @PrimaryColumn() + id: string; + /** + * 权限名 + */ + @Column({ unique: true }) + name: string; + + @Column() + description: string; + + /** + * 资源,隔开 + */ + @Column() + resources: string; +} diff --git a/apps/services/cert/authorize/src/rbac/entity/role.entity.ts b/apps/services/cert/authorize/src/rbac/entity/role.entity.ts new file mode 100644 index 0000000..6132c43 --- /dev/null +++ b/apps/services/cert/authorize/src/rbac/entity/role.entity.ts @@ -0,0 +1,48 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + ManyToMany, + JoinTable, + JoinColumn, +} from 'typeorm'; +import { User } from './user.entity'; +import { Permission } from './permission.entity'; + +@Entity() +export class Role { + @PrimaryGeneratedColumn() + id: number; + + /** + * 角色名(en) + */ + @Column({ unique: true }) + name: string; + + /** + * 角色名(zh-CN) + */ + @Column() + alias: string; + + /** + * 角色是否启用 + */ + @Column({ default: true }) + isEnabled: boolean; + + /** + * 角色描述 + */ + @Column() + description: string; + + @ManyToMany(() => User, (user) => user.roles) + @JoinColumn() + users: User[]; + + @ManyToMany(() => Permission, { cascade: true }) + @JoinTable() + permissions: Permission[]; +} diff --git a/apps/services/cert/authorize/src/rbac/entity/user.entity.ts b/apps/services/cert/authorize/src/rbac/entity/user.entity.ts new file mode 100644 index 0000000..9bf2531 --- /dev/null +++ b/apps/services/cert/authorize/src/rbac/entity/user.entity.ts @@ -0,0 +1,41 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + ManyToMany, + JoinTable, + CreateDateColumn, + UpdateDateColumn, +} from 'typeorm'; +import { Role } from './role.entity'; + +@Entity() +export class User { + @PrimaryGeneratedColumn() + id: number; + + @Column({ unique: true }) + username: string; + + @Column() + password: string; + + @Column({ default: '' }) + phoneNumber: string; + + @CreateDateColumn({ type: 'timestamp' }) + createTime: Date; + + @UpdateDateColumn({ type: 'timestamp' }) + updateTime: Date; + + /** + * 用户是否可用 + */ + @Column({ default: true }) + isEnabled: boolean; + + @ManyToMany(() => Role, { cascade: true }) + @JoinTable() + roles: Role[]; +} diff --git a/apps/services/cert/authorize/src/rbac/rbac.module.ts b/apps/services/cert/authorize/src/rbac/rbac.module.ts new file mode 100644 index 0000000..13ee21f --- /dev/null +++ b/apps/services/cert/authorize/src/rbac/rbac.module.ts @@ -0,0 +1,26 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { User } from './entity/user.entity'; +import { Role } from './entity/role.entity'; +import { Permission } from './entity/permission.entity'; +import { RbacService } from './rbac.service'; + +@Module({ + imports: [ + TypeOrmModule.forRoot({ + type: 'mysql', + host: 'localhost', + port: 3306, + username: 'root', + password: 'root', + database: 'rbac', + entities: [__dirname + '/**/*.entity{.ts,.js}'], + synchronize: true, + timezone: 'Asia/Shanghai', // 这里设置了时区 + }), + TypeOrmModule.forFeature([User, Role, Permission]), + ], + providers: [RbacService], + exports: [RbacService], +}) +export class RbacModule {} diff --git a/apps/services/cert/authorize/src/rbac/rbac.service.ts b/apps/services/cert/authorize/src/rbac/rbac.service.ts new file mode 100644 index 0000000..ddae464 --- /dev/null +++ b/apps/services/cert/authorize/src/rbac/rbac.service.ts @@ -0,0 +1,177 @@ +// rbac.service.ts +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { In, Not, QueryRunner, Repository, getConnection } from 'typeorm'; +import { Role } from './entity/role.entity'; +import { Permission } from './entity/permission.entity'; +import { User } from './entity/user.entity'; +import { minimatch } from 'minimatch'; + +interface PermissionItem { + id: string; + name: string; + description?: string; + resources: string[]; +} + +@Injectable() +export class RbacService { + constructor( + @InjectRepository(Permission) + private permissionRepository: Repository, + @InjectRepository(User) private userRepository: Repository, + @InjectRepository(Role) private roleRepository: Repository, + ) {} + + async initSuperAdminRole() { + const exsit = await this.roleRepository.findOne({ + where: { name: 'superadmin' }, + }); + if (!exsit) { + await this.roleRepository.save({ + name: 'superadmin', + alias: '超级管理员', + description: 'god', + }); + } + } + + /** + * 初始化超级管理的账户 + */ + async initSuperAdminAccount() { + const superadminRole = await this.roleRepository.findOne({ + where: { name: 'superadmin' }, + }); + if (!superadminRole) + return await this.userRepository.save({ + username: 'admin', + password: 'admin', + roles: [superadminRole], + }); + } + + async createRole(payload: Role) { + const { name, alias, description } = payload; + const exsit = await this.roleRepository.findOne({ where: { name } }); + if (exsit) return { message: '用户已存在' }; + const result = await this.roleRepository.save({ name, alias, description }); + return result; + } + + async findAllRole() { + const roleWithPermissions = await this.roleRepository.find({ + where: { name: Not('superadmin') }, + relations: ['permissions'], + }); + const allPermissions = await this.permissionRepository.find({ + select: ['id', 'name', 'description', 'resources'], + }); + // 查询角色下的用户 + for (let i = 0; i < roleWithPermissions.length; i++) { + const { id: roleId } = roleWithPermissions[i]; + roleWithPermissions[i].users = await this.userRepository + .createQueryBuilder('user') + .select([ + 'user.id', + 'user.username', + 'user.isEnabled', + 'user.phoneNumber', + 'user.createTime', + ]) + .innerJoinAndSelect('user.roles', 'role', 'role.id = :roleId', { + roleId, + }) + .getMany(); + } + return { roleWithPermissions, allPermissions }; + } + + /** + * 初始化permission表 + * 0. 清空role_perission关联标的相关信息 + * 1. 清空旧的权限表信息 + * 2. 更新最新的permissions + */ + async initPermission(permissions: PermissionItem[]) { + const records = permissions.map((i) => ({ + ...i, + name: i.name, + resources: i.resources.join(','), + })); + await this.permissionRepository.save(records); + } + + async findRolePermission(roleId: number) { + //查询粗roleId关联的permission + return await this.roleRepository.findOne({ + where: { id: roleId }, + relations: ['permissions'], + }); + } + + async updateRolePermissions(payload: any) { + const { roleId, permissionIds } = payload; + const role = await this.roleRepository.findOne({ + where: { id: roleId }, + relations: ['permissions'], + }); + const newPermissions = await this.permissionRepository.find({ + where: { id: In(permissionIds) }, + }); + role.permissions = newPermissions; + return await this.roleRepository.save(role); + } + + /** + * 删除角色 + * 1.删除用户有这个role的关联 + * 2.删除role和permission的关联 + * 3.删除这个role + */ + async removeRole(r: Role) { + await this.roleRepository + .createQueryBuilder() + .delete() + .from('user_roles_role') + .where('roleId = :roleId', { roleId: r.id }) + .execute(); + const role = await this.roleRepository.findOne({ where: { id: r.id } }); + if (role) return await this.roleRepository.remove(role); + } + + async updateRole({ roleId, ...rest }) { + await this.roleRepository.save({ id: roleId, ...rest }); + const role = await this.roleRepository.findOne({ + where: { id: roleId }, + relations: { permissions: true }, + }); + role.permissions = rest.isEnabled ? role.permissions : []; + return await this.roleRepository.save(role); + } + + async findAllUser() { + return await this.userRepository.find({ + relations: { roles: true }, + select: ['id', 'username', 'phoneNumber', 'createTime', 'isEnabled'], + }); + } + + async roleAuthorize(user, url) { + // 查询角色对应的resource + const raw = await this.userRepository + .createQueryBuilder('user') + .leftJoinAndSelect('user.roles', 'role') + .leftJoinAndSelect('role.permissions', 'permission') + .where('user.username = :username', { username: user.username }) + .select('permission.resources') + .getRawMany(); + const permissions = raw.map((r) => r.permission_resources).filter(Boolean); + console.log( + `本次请求的用户: ${user.username},可访问资源: ${permissions.join(', ')}`, + ); + // 判断角色的permission的resource是否包含url + const allow = permissions.some((path: string) => minimatch(url, path)); + return allow; + } +} diff --git a/apps/services/cert/authorize/src/user/user.controller.ts b/apps/services/cert/authorize/src/user/user.controller.ts new file mode 100644 index 0000000..1f6ddff --- /dev/null +++ b/apps/services/cert/authorize/src/user/user.controller.ts @@ -0,0 +1,65 @@ +import { Controller } from '@nestjs/common'; +import { EventPattern } from '@nestjs/microservices'; +import { UserService } from './user.service'; +import { BcryptService } from '../bcrypt/bcrypt.service'; + +@Controller() +export class UserController { + constructor( + private readonly userService: UserService, + private readonly bcryptService: BcryptService, + ) {} + /** + * 用户账号、密码、是否可用 + */ + @EventPattern({ cmd: 'cert.user.account' }) + async findUser( + payload, + ): Promise<{ isLegal: boolean; msg?: string; data?: any }> { + const { username, password } = payload; + const user = await this.userService.findUser({ username }); + if (!user) return { isLegal: false, msg: '用户不存在' }; + if (!user.isEnabled) return { isLegal: false, msg: '用户被封禁' }; + const correctPass = await this.bcryptService.comparePassword( + password, + user.password, + ); + if (!correctPass) return { isLegal: false, msg: '密码错误' }; + return { isLegal: true, data: user }; + } + + @EventPattern({ cmd: 'cert.user.encrypt' }) + async encrypt(plainText: string) { + return await this.bcryptService.hashPassword(plainText); + } + + @EventPattern({ cmd: 'cert.encrypt.compare' }) + async compare(plainText: string, hash: string) { + return await this.bcryptService.comparePassword(plainText, hash); + } + + @EventPattern({ cmd: 'cert.user.create' }) + async createUser(payload) { + return await this.userService.create(payload); + } + + @EventPattern({ cmd: 'cert.user.update' }) + async updateUser(payload) { + const { password, ...rest } = payload; + const updateFields = password + ? { password: await this.bcryptService.hashPassword(password), ...rest } + : { ...rest }; + return await this.userService.update(updateFields); + } + + @EventPattern({ cmd: 'cert.user.delete' }) + async deleteUser(userIds: number[]) { + return await this.userService.delete(userIds); + } + + @EventPattern({ cmd: 'cert.user.find.annotator' }) + async findAnnotators() { + const annotators = await this.userService.findAnnotators(); + return { data: annotators }; + } +} diff --git a/apps/services/cert/authorize/src/user/user.module.ts b/apps/services/cert/authorize/src/user/user.module.ts new file mode 100644 index 0000000..37ad21c --- /dev/null +++ b/apps/services/cert/authorize/src/user/user.module.ts @@ -0,0 +1,28 @@ +import { Module } from '@nestjs/common'; +import { UserController } from './user.controller'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { User } from '../rbac/entity/user.entity'; +import { Role } from '../rbac/entity/role.entity'; +import { Permission } from '../rbac/entity/permission.entity'; +import { UserService } from './user.service'; +import { BcryptService } from '../bcrypt/bcrypt.service'; + +@Module({ + imports: [ + TypeOrmModule.forRoot({ + type: 'mysql', + host: 'localhost', + port: 3306, + username: 'root', + password: 'root', + database: 'rbac', + entities: [__dirname + '/**/*.entity{.ts,.js}'], + synchronize: true, + timezone: 'Asia/Shanghai', // 这里设置了时区 + }), + TypeOrmModule.forFeature([User, Role, Permission]), + ], + controllers: [UserController], + providers: [UserService, BcryptService], +}) +export class UserModule {} diff --git a/apps/services/cert/authorize/src/user/user.service.ts b/apps/services/cert/authorize/src/user/user.service.ts new file mode 100644 index 0000000..b442b09 --- /dev/null +++ b/apps/services/cert/authorize/src/user/user.service.ts @@ -0,0 +1,85 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { User } from '../rbac/entity/user.entity'; +import { In, Repository } from 'typeorm'; +import { Role } from '../rbac/entity/role.entity'; +import { BcryptService } from '../bcrypt/bcrypt.service'; + +@Injectable() +export class UserService { + constructor( + @InjectRepository(User) private readonly userRepository: Repository, + @InjectRepository(Role) private readonly roleRepository: Repository, + private readonly bcryptService: BcryptService, + ) {} + + async findAnnotators() { + const annotators = await this.userRepository + .createQueryBuilder('user') + .select(['user.id', 'user.username']) + .leftJoin('user.roles', 'role') + .addSelect('role.name') + .where('role.name = :roleName', { roleName: 'dmp_annotator' }) + .andWhere('user.isEnabled = :isEnabled', { isEnabled: true }) + .getMany(); + return annotators; + } + + async findUser({ username }) { + return await this.userRepository.findOne({ + where: { username }, + select: ['id', 'isEnabled', 'phoneNumber', 'password'], + relations: ['roles'], + }); + } + + async create(payload: any) { + const { username, password, phoneNumber, roles: selectRoles } = payload; + // 判断用户名是否存在 + const user = await this.userRepository.findOne({ where: { username } }); + const roles = await this.roleRepository.find({ + where: { + id: In(selectRoles.map((r) => r.id)), + }, + }); + // 如果username存在 + if (user) return false; + const cipher = await this.bcryptService.hashPassword(password); + return await this.userRepository.save({ + username, + password: cipher, + phoneNumber, + roles, + }); + } + + async update(fields: User) { + try { + const { id, roles: roleIds } = fields; + const user = await this.userRepository.findOne({ + where: { id }, + relations: ['roles'], + }); + const roles = await this.roleRepository.find({ + where: { + id: In(roleIds), + }, + }); + const updateUser = { ...user, ...fields, roles }; + const result = await this.userRepository.save(updateUser); + if (result) return { id: user.id }; + } catch (error) { + throw new Error(error); + } + } + + async delete(userIds: number[]) { + const users = await this.userRepository.find({ + where: { id: In(userIds) }, + relations: { roles: true }, + }); + users.forEach((user) => (user.roles = [])); + await this.userRepository.save(users); + return await this.userRepository.remove(users); + } +} diff --git a/apps/services/cert/authorize/tsconfig.build.json b/apps/services/cert/authorize/tsconfig.build.json new file mode 100644 index 0000000..64f86c6 --- /dev/null +++ b/apps/services/cert/authorize/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] +} diff --git a/apps/services/cert/authorize/tsconfig.json b/apps/services/cert/authorize/tsconfig.json new file mode 100644 index 0000000..adb614c --- /dev/null +++ b/apps/services/cert/authorize/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "es2017", + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": false, + "noImplicitAny": false, + "strictBindCallApply": false, + "forceConsistentCasingInFileNames": false, + "noFallthroughCasesInSwitch": false + } +} diff --git a/apps/services/cert/gateway/.env.dev b/apps/services/cert/gateway/.env.dev new file mode 100644 index 0000000..5f5cd32 --- /dev/null +++ b/apps/services/cert/gateway/.env.dev @@ -0,0 +1,8 @@ +PORT=12144 +# nacos中注册服务的名称 +NACOS_SERVICE_NAME=cert-gateway +NACOS_ADDR=127.0.0.1:8848 +NACOS_NAMESPACE=56a3b295-f319-4ced-82b5-0df2e98cc541 +# nacos配置中心 +NACOS_DATAID='test' +NACOS_GROUP='DEFAULT_GROUP' \ No newline at end of file diff --git a/apps/services/cert/gateway/.env.prod b/apps/services/cert/gateway/.env.prod new file mode 100644 index 0000000..bb8ea3d --- /dev/null +++ b/apps/services/cert/gateway/.env.prod @@ -0,0 +1 @@ +PORT=23333 \ No newline at end of file diff --git a/apps/services/cert/gateway/.eslintrc.js b/apps/services/cert/gateway/.eslintrc.js new file mode 100644 index 0000000..259de13 --- /dev/null +++ b/apps/services/cert/gateway/.eslintrc.js @@ -0,0 +1,25 @@ +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.json', + tsconfigRootDir: __dirname, + sourceType: 'module', + }, + plugins: ['@typescript-eslint/eslint-plugin'], + extends: [ + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + root: true, + env: { + node: true, + jest: true, + }, + ignorePatterns: ['.eslintrc.js'], + rules: { + '@typescript-eslint/interface-name-prefix': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-explicit-any': 'off', + }, +}; diff --git a/apps/services/cert/gateway/.gitignore b/apps/services/cert/gateway/.gitignore new file mode 100644 index 0000000..22f55ad --- /dev/null +++ b/apps/services/cert/gateway/.gitignore @@ -0,0 +1,35 @@ +# compiled output +/dist +/node_modules + +# Logs +logs +*.log +npm-debug.log* +pnpm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# OS +.DS_Store + +# Tests +/coverage +/.nyc_output + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json \ No newline at end of file diff --git a/apps/services/cert/gateway/.prettierrc b/apps/services/cert/gateway/.prettierrc new file mode 100644 index 0000000..dcb7279 --- /dev/null +++ b/apps/services/cert/gateway/.prettierrc @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "trailingComma": "all" +} \ No newline at end of file diff --git a/apps/services/cert/gateway/Dockerfile b/apps/services/cert/gateway/Dockerfile new file mode 100644 index 0000000..1b274a6 --- /dev/null +++ b/apps/services/cert/gateway/Dockerfile @@ -0,0 +1,7 @@ +FROM node:16.19-alpine +RUN npm install -g pnpm +RUN mkdir -p /www/wwwroot/aorta/auth +WORKDIR /www/wwwroot/aorta/auth +ADD . /www/wwwroot/aorta/auth +RUN pnpm install +CMD pnpm run build && pnpm run start:prod \ No newline at end of file diff --git a/apps/services/cert/gateway/README.md b/apps/services/cert/gateway/README.md new file mode 100644 index 0000000..f5aa86c --- /dev/null +++ b/apps/services/cert/gateway/README.md @@ -0,0 +1,73 @@ +

+ Nest Logo +

+ +[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 +[circleci-url]: https://circleci.com/gh/nestjs/nest + +

A progressive Node.js framework for building efficient and scalable server-side applications.

+

+NPM Version +Package License +NPM Downloads +CircleCI +Coverage +Discord +Backers on Open Collective +Sponsors on Open Collective + + Support us + +

+ + +## Description + +[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. + +## Installation + +```bash +$ pnpm install +``` + +## Running the app + +```bash +# development +$ pnpm run start + +# watch mode +$ pnpm run start:dev + +# production mode +$ pnpm run start:prod +``` + +## Test + +```bash +# unit tests +$ pnpm run test + +# e2e tests +$ pnpm run test:e2e + +# test coverage +$ pnpm run test:cov +``` + +## Support + +Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). + +## Stay in touch + +- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) +- Website - [https://nestjs.com](https://nestjs.com/) +- Twitter - [@nestframework](https://twitter.com/nestframework) + +## License + +Nest is [MIT licensed](LICENSE). diff --git a/apps/services/cert/gateway/nest-cli.json b/apps/services/cert/gateway/nest-cli.json new file mode 100644 index 0000000..f9aa683 --- /dev/null +++ b/apps/services/cert/gateway/nest-cli.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/nest-cli", + "collection": "@nestjs/schematics", + "sourceRoot": "src", + "compilerOptions": { + "deleteOutDir": true + } +} diff --git a/apps/services/cert/gateway/package.json b/apps/services/cert/gateway/package.json new file mode 100644 index 0000000..ef2bc60 --- /dev/null +++ b/apps/services/cert/gateway/package.json @@ -0,0 +1,51 @@ +{ + "name": "@tavi/cert-gateway", + "version": "1.0.0", + "scripts": { + "build": "nest build", + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", + "start": "nest start", + "start:dev": "cross-env NODE_ENV=dev nest start --watch", + "start:debug": "nest start --debug --watch", + "start:prod": "cross-env NODE_ENV=prod node dist/main", + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix" + }, + "dependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "reflect-metadata": "^0.1.13", + "@nestjs/config": "3.0.0", + "rxjs": "7.8.1", + "nats": "2.15.1", + "@nestjs/microservices": "10.0.5", + "nacos": "2.5.1", + "cross-env": "7.0.3", + "cookie-parser": "1.4.6", + "@nestjs/typeorm": "10.0.0", + "typeorm": "0.3.17", + "class-validator": "0.14.0", + "class-transformer": "0.5.1", + "uuid": "9.0.0" + }, + "devDependencies": { + "@nestjs/cli": "^10.0.0", + "@nestjs/schematics": "^10.0.0", + "@nestjs/testing": "^10.0.0", + "@types/express": "^4.17.17", + "@types/node": "^20.3.1", + "@types/supertest": "^2.0.12", + "@typescript-eslint/eslint-plugin": "^5.59.11", + "@typescript-eslint/parser": "^5.59.11", + "eslint": "^8.42.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^4.2.1", + "prettier": "^2.8.8", + "source-map-support": "^0.5.21", + "supertest": "^6.3.3", + "ts-loader": "^9.4.3", + "ts-node": "^10.9.1", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.1.3" + } +} \ No newline at end of file diff --git a/apps/services/cert/gateway/src/admin/admin.controller.ts b/apps/services/cert/gateway/src/admin/admin.controller.ts new file mode 100644 index 0000000..0fc8bff --- /dev/null +++ b/apps/services/cert/gateway/src/admin/admin.controller.ts @@ -0,0 +1,123 @@ +import { Body, Controller, Get, Inject, Param, Post } from '@nestjs/common'; +import { + AdminSignDto, + CreateRoleDto, + CreateUserDto, + FindRoleDto, + ForbidRoleDto, + RoleDto, + UpdateRolePermissionsDto, + UpdateUserDto, +} from './admin.dto'; +import { ClientProxy } from '@nestjs/microservices'; +import { firstValueFrom } from 'rxjs'; +import { rbacConfiguration } from 'src/resource.table'; + +@Controller('admin') +export class AdminController { + constructor(@Inject('Client') private client: ClientProxy) {} + + @Get('find/permission/resource') + async findRbacConfiguration(): Promise { + return { code: 'ok', data: rbacConfiguration }; + } + + @Post('role/create') + async createRole(@Body() createRoleDto: CreateRoleDto) { + const pattern = { cmd: 'cert.create.role' }; + const result = await firstValueFrom( + this.client.send(pattern, createRoleDto), + ); + return { code: 'ok', data: result }; + } + + @Post('role/remove') + async removeRole(@Body() role: RoleDto) { + const pattern = { cmd: 'cert.remove.role' }; + const result = await firstValueFrom(this.client.send(pattern, role)); + return { code: 'ok', data: result }; + } + + @Post('role/update') + async updateRole(@Body() forbidRoleDto: ForbidRoleDto) { + const pattern = { cmd: 'cert.update.role' }; + const payload = forbidRoleDto; + const result = await firstValueFrom(this.client.send(pattern, payload)); + return { code: 'ok', data: result }; + } + + @Get('find/role/all') + async findAllRolePermissions() { + const pattern = { cmd: 'cert.find.role.all' }; + const result = await firstValueFrom(this.client.send(pattern, [])); + return { code: 'ok', data: result }; + } + + @Post('role/permissions/find') + async findRolePermission(@Body() findRoleDto: FindRoleDto): Promise { + const pattern = { cmd: 'cert.find.role.permission' }; + const payload = findRoleDto.id; + // 角色在role-permission关联表中已存在的权限 + const { permissions } = await firstValueFrom( + this.client.send(pattern, payload), + ); + const roleOwnPermissions = permissions.map((i) => ({ + id: i.id, + name: i.name, + })); + // 结构化 + const allPermissions = rbacConfiguration + .map((i) => i.permissions) + .flat() + .map((i) => ({ name: i.name, id: i.id })); + + return { code: 'ok', data: { roleOwnPermissions, allPermissions } }; + } + + @Post('role/permissions/update') + async updateRolePermissions( + @Body() updateRolePermissionsDto: UpdateRolePermissionsDto, + ) { + const pattern = { cmd: 'cert.update.role.permissions' }; + const { roleId, permissionIds } = updateRolePermissionsDto; + const payload = { roleId, permissionIds }; + const result = await firstValueFrom(this.client.send(pattern, payload)); + return { code: 'ok', data: result }; + } + + @Post('user/create') + async createUser(@Body() createUserDto: CreateUserDto) { + const pattern = { cmd: 'cert.user.create' }; + const payload = createUserDto; + const result = await firstValueFrom(this.client.send(pattern, payload)); + return { code: 'ok', data: result }; + } + + @Get('user/find/all') + async userSelect() { + const pattern = { cmd: 'cert.find.all.user' }; + const payload = []; + const result = await firstValueFrom(this.client.send(pattern, payload)); + return { code: 'ok', data: result }; + } + + @Post('user/update') + async userUpdate(@Body() user: UpdateUserDto) { + const pattern = { cmd: 'cert.user.update' }; + const payload = user; + const result = await firstValueFrom(this.client.send(pattern, payload)); + // 删除token + await firstValueFrom( + this.client.send({ cmd: 'cert.token.deprecated' }, payload), + ); + return { code: 'ok', data: result }; + } + + @Post('user/delete') + async userDelete(@Body() userIds: number[]) { + const pattern = { cmd: 'cert.user.delete' }; + const payload = userIds; + const result = await firstValueFrom(this.client.send(pattern, payload)); + return { code: 'ok', data: result }; + } +} diff --git a/apps/services/cert/gateway/src/admin/admin.dto.ts b/apps/services/cert/gateway/src/admin/admin.dto.ts new file mode 100644 index 0000000..5c6bd44 --- /dev/null +++ b/apps/services/cert/gateway/src/admin/admin.dto.ts @@ -0,0 +1,60 @@ +import { IsString, Min, Max } from 'class-validator'; + +export class AdminSignDto { + @IsString() + username: string; + + @IsString() + @Min(6, { message: '密码长度小于6' }) + @Max(20, { message: '密码长度不能超过20' }) + password: string; +} + +export class ResourceDto { + name: string; + isEnabled: boolean; + methodType: string; + description: string; +} + +export class CreateRoleDto { + name: string; + alias: string; + description: string; +} + +export class FindRoleDto { + id: number; +} + +export class UpdateRolePermissionsDto { + permissionIds: string[]; + roleId: number; +} + +export class ForbidRoleDto { + username: string; + roleId: number; + isEnabled: boolean; +} + +export class CreateUserDto { + username: string; + password: string; + phoneNumber: string | number; + roles: number[] | string[]; +} + +export class UpdateUserDto { + id: number; + password?: string; + username: string; + roles?: number[]; +} + +export class RoleDto { + id?: number; + name: string; + alias: string; + isEnabled?: boolean; +} diff --git a/apps/services/cert/gateway/src/admin/admin.module.ts b/apps/services/cert/gateway/src/admin/admin.module.ts new file mode 100644 index 0000000..412111f --- /dev/null +++ b/apps/services/cert/gateway/src/admin/admin.module.ts @@ -0,0 +1,23 @@ +import { Module } from '@nestjs/common'; +import { AdminController } from './admin.controller'; +import { AdminService } from './admin.service'; +import { ClientsModule, Transport } from '@nestjs/microservices'; + +@Module({ + imports: [ + ClientsModule.register([ + { + name: 'Client', + transport: Transport.NATS, + options: { + servers: ['nats://localhost:4222'], + maxReconnectAttempts: 5, + reconnectTimeWait: 1000, + }, + }, + ]), + ], + controllers: [AdminController], + providers: [AdminService], +}) +export class AdminModule {} diff --git a/apps/services/cert/gateway/src/admin/admin.service.ts b/apps/services/cert/gateway/src/admin/admin.service.ts new file mode 100644 index 0000000..796f9fd --- /dev/null +++ b/apps/services/cert/gateway/src/admin/admin.service.ts @@ -0,0 +1,4 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class AdminService {} diff --git a/apps/services/cert/gateway/src/app.controller.ts b/apps/services/cert/gateway/src/app.controller.ts new file mode 100644 index 0000000..da28874 --- /dev/null +++ b/apps/services/cert/gateway/src/app.controller.ts @@ -0,0 +1,29 @@ +import { Controller, Get, Headers, Inject, Req } from '@nestjs/common'; +import { AppService } from './app.service'; +import { ClientProxy } from '@nestjs/microservices'; +import { Request } from 'express'; +import { firstValueFrom } from 'rxjs'; + +@Controller() +export class AppController { + constructor( + private readonly appService: AppService, + @Inject('Client') private client: ClientProxy, + ) {} + + /** + * token用户信息查询 + */ + @Get('/auth/user') + async auth(@Req() request: Request) { + const { tokenKeyInCookie } = await firstValueFrom( + this.client.send({ cmd: 'cert.token.config' }, []), + ); + const tokenCipher = request.cookies[tokenKeyInCookie]; + if (!tokenCipher) return { code: 1, msg: '登录状态失效,请重新登录' }; + const result = await firstValueFrom( + this.client.send({ cmd: 'cert.token.decode' }, tokenCipher), + ); + return { code: 0, data: result }; + } +} diff --git a/apps/services/cert/gateway/src/app.module.ts b/apps/services/cert/gateway/src/app.module.ts new file mode 100644 index 0000000..76fa6a5 --- /dev/null +++ b/apps/services/cert/gateway/src/app.module.ts @@ -0,0 +1,49 @@ +import { ClientsModule, Transport } from '@nestjs/microservices'; +import { NacosModule } from './nacos/nacos.module'; +import { AppController } from './app.controller'; +import { ConfigModule } from '@nestjs/config'; +import { AppService } from './app.service'; +import { + MiddlewareConsumer, + Module, + NestModule, + OnModuleInit, +} from '@nestjs/common'; +import { TraceIdMiddleware } from './middleware/trace.middleware'; +import { AdminModule } from './admin/admin.module'; + +@Module({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + envFilePath: `.env.${process.env.NODE_ENV}`, + }), + ClientsModule.register([ + { + name: 'Client', + transport: Transport.NATS, + options: { + servers: ['nats://localhost:4222'], + maxReconnectAttempts: 5, + reconnectTimeWait: 1000, + }, + }, + ]), + NacosModule, + AdminModule, + ], + controllers: [AppController], + providers: [AppService], +}) +export class AppModule implements NestModule, OnModuleInit { + constructor(private readonly appService: AppService) {} + + configure(consumer: MiddlewareConsumer) { + consumer.apply(TraceIdMiddleware).forRoutes('*'); + } + + async onModuleInit() { + await this.appService.roleInitialization(); + await this.appService.permissionResourceInitialization(); + } +} diff --git a/apps/services/cert/gateway/src/app.service.ts b/apps/services/cert/gateway/src/app.service.ts new file mode 100644 index 0000000..f2713bf --- /dev/null +++ b/apps/services/cert/gateway/src/app.service.ts @@ -0,0 +1,30 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { ClientProxy } from '@nestjs/microservices'; +import { rbacConfiguration } from './resource.table'; +import { firstValueFrom } from 'rxjs'; + +@Injectable() +export class AppService { + constructor(@Inject('Client') private client: ClientProxy) {} + + /** + * 初始化权限资源permission表 + */ + async permissionResourceInitialization() { + console.log('初始化资源权限'); + const pattern = { cmd: 'cert.init.permission.resource' }; + const payload = rbacConfiguration.map((i) => i.permissions).flat(); + const result = await firstValueFrom(this.client.emit(pattern, payload)); + return { code: 'ok', data: result }; + } + + /** + * 初始化角色资源&超级管理员账号 + */ + async roleInitialization() { + const pattern = { cmd: 'cert.init.role.admin' }; + const payload = []; + const result = await firstValueFrom(this.client.emit(pattern, payload)); + return { code: 'ok', data: result }; + } +} diff --git a/apps/services/cert/gateway/src/filter/exceptions.filter.ts b/apps/services/cert/gateway/src/filter/exceptions.filter.ts new file mode 100644 index 0000000..afff334 --- /dev/null +++ b/apps/services/cert/gateway/src/filter/exceptions.filter.ts @@ -0,0 +1,33 @@ +import { + ExceptionFilter, + Catch, + ArgumentsHost, + HttpException, + HttpStatus, +} from '@nestjs/common'; + +@Catch() +export class AllExceptionsFilter implements ExceptionFilter { + catch(exception: unknown, host: ArgumentsHost) { + const ctx = host.switchToHttp(); + const response = ctx.getResponse(); + const request = ctx.getRequest(); + + const status = + exception instanceof HttpException + ? exception.getStatus() + : HttpStatus.INTERNAL_SERVER_ERROR; + + const message = + exception instanceof HttpException + ? exception.getResponse() + : 'Internal server error'; + + response.status(status).json({ + statusCode: status, + timestamp: new Date().toISOString(), + path: request.url, + message: message, + }); + } +} diff --git a/apps/services/cert/gateway/src/main.ts b/apps/services/cert/gateway/src/main.ts new file mode 100644 index 0000000..8fc1cca --- /dev/null +++ b/apps/services/cert/gateway/src/main.ts @@ -0,0 +1,28 @@ +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app.module'; +import * as cookieParser from 'cookie-parser'; +import { ConfigService } from '@nestjs/config'; +import { ValidationPipe } from '@nestjs/common'; +import { AllExceptionsFilter } from './filter/exceptions.filter'; + +async function bootstrap() { + const app = await NestFactory.create(AppModule); + // 开启全局验证 + const configService = app.get(ConfigService); + const port = configService.get('PORT'); + app.use(cookieParser()); + app.useGlobalPipes(new ValidationPipe()); + app.useGlobalFilters(new AllExceptionsFilter()); + app.setGlobalPrefix('cert'); + await app.listen(port); + // 控制输出项目的全部接口 + const router = app.getHttpServer()._events.request._router; + const routerList = router.stack + .map((item) => ({ + name: item.route?.path, + methodType: item.route?.stack[0].method, + })) + .filter((i) => !!i.name && !!i.methodType); + console.log(routerList); +} +bootstrap(); diff --git a/apps/services/cert/gateway/src/middleware/trace.middleware.ts b/apps/services/cert/gateway/src/middleware/trace.middleware.ts new file mode 100644 index 0000000..29402ad --- /dev/null +++ b/apps/services/cert/gateway/src/middleware/trace.middleware.ts @@ -0,0 +1,14 @@ +import { Injectable, NestMiddleware } from '@nestjs/common'; +import { NextFunction, Request, Response } from 'express'; +import { v4 } from 'uuid'; + +@Injectable() +export class TraceIdMiddleware implements NestMiddleware { + use(req: Request, res: Response, next: NextFunction) { + // Generate a random traceId + const traceId = v4(); + (req as any).traceId = traceId; + res.set('X-Trace-Id', traceId); + next(); + } +} diff --git a/apps/services/cert/gateway/src/nacos/nacos.module.ts b/apps/services/cert/gateway/src/nacos/nacos.module.ts new file mode 100644 index 0000000..d9daedc --- /dev/null +++ b/apps/services/cert/gateway/src/nacos/nacos.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; +import { NacosService } from './nacos.service'; + +@Module({ + providers: [NacosService], + exports: [NacosService], +}) +export class NacosModule {} diff --git a/apps/services/cert/gateway/src/nacos/nacos.service.ts b/apps/services/cert/gateway/src/nacos/nacos.service.ts new file mode 100644 index 0000000..4a2e7f9 --- /dev/null +++ b/apps/services/cert/gateway/src/nacos/nacos.service.ts @@ -0,0 +1,108 @@ +// nacos.service.ts +import { + Injectable, + OnApplicationBootstrap, + OnApplicationShutdown, +} from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { NacosConfigClient, NacosNamingClient } from 'nacos'; // ts +import * as os from 'os'; + +@Injectable() +export class NacosService + implements OnApplicationBootstrap, OnApplicationShutdown +{ + private nacosNamingClient: NacosNamingClient; + private nacosConfigClient: NacosConfigClient; + serviceName: string; + instance: { ip: string; port: number }; + group: string; + dataId: string; + constructor(private configService: ConfigService) { + this.nacosNamingClient = new NacosNamingClient({ + logger: console, + serverList: configService.get('NACOS_ADDR'), + namespace: configService.get('NACOS_NAMESPACE'), + }); + this.nacosConfigClient = new NacosConfigClient({ + namespace: configService.get('NACOS_NAMESPACE'), + serverAddr: configService.get('NACOS_ADDR'), + }); + this.serviceName = configService.get('NACOS_SERVICE_NAME'); + this.dataId = configService.get('NACOS_DATAID'); + this.group = configService.get('NACOS_GROUP'); + this.instance = { + ip: this.getServerIP(), + port: configService.get('PORT'), + }; + } + + /** + * nestjs应用被关闭前 + * @param {string} signal 'SIGTERM' | 'SIGINT' | 'SIGHUP' | 'SIGBREAK' + */ + onApplicationShutdown(signal?: string) { + if (signal) { + const { serviceName, instance, group } = this; + this.nacosNamingClient.deregisterInstance(serviceName, instance, group); + this.nacosConfigClient.close(); + } + } + + /** + * 应用完全启动&微服务也被成功启动 + */ + onApplicationBootstrap() { + const { serviceName, instance } = this; + this.nacosNamingClient.registerInstance(serviceName, instance); + } + + /** + * 先于 onApplicationBootstrap + */ + async onModuleInit() { + this.nacosNamingClient.ready(); + } + + /** + * 从nacos获取最新的配置信息 + */ + async getConfig() { + const { dataId, group } = this; + const configFromNacos = await this.nacosConfigClient.getConfig( + dataId, + group, + ); + return configFromNacos; + } + + /** + * 订阅配置中心,当远程修改nacos的配置时,触发 + */ + async subscribeConfiguration() { + const { dataId, group } = this; + this.nacosConfigClient.subscribe( + { + dataId, + group, + }, + (content) => console.log('content', content), + ); + } + + getServerIP(): string { + const networkInterfaces = os.networkInterfaces(); + for (const name of Object.keys(networkInterfaces)) { + for (const iface of networkInterfaces[name]) { + // 跳过IPv6和内部地址 + if ('IPv4' !== iface.family || iface.internal !== false) { + continue; + } + + // 返回第一个找到的IPv4地址 + return iface.address; + } + } + return 'localhost'; // 如果找不到外部IPv4地址,返回localhost + } +} diff --git a/apps/services/cert/gateway/src/resource.table.ts b/apps/services/cert/gateway/src/resource.table.ts new file mode 100644 index 0000000..5bc36b0 --- /dev/null +++ b/apps/services/cert/gateway/src/resource.table.ts @@ -0,0 +1,53 @@ +interface PermissionItem { + id: string; + name: string; + description?: string; + resources: string[]; +} + +interface RbacConfigurationItem { + moduleName: string; + updateTime?: string; + permissions: PermissionItem[]; +} + +/** + * 管理平台资源权限模板,写入permission表 + */ +export const rbacConfiguration: RbacConfigurationItem[] = [ + { + moduleName: '基本', + updateTime: '2023年7月25日 09点40分', + permissions: [ + { + id: 'aorta-web', + name: '主动脉根部', + description: 'aorta登录', + resources: ['/aorta/**'], //! 匹配规则是基于 globbing 的,这种模式匹配在 Unix 和 Unix-like 系统中用于文件名的模式匹配,并且被许多编程语言和库所采用。 + }, + { + id: 'dmp', + name: '数据管理平台', + description: 'dmp登录', + resources: ['/dmp/**'], + }, + ], + }, + { + moduleName: '用户相关', + permissions: [ + { + id: 'frontAuth', + name: '前台登录认证_new', + description: '...', + resources: ['/cert/auth'], + }, + { + id: 'adminAuth', + name: '管理平台登录', + description: '...', + resources: ['/cert/admin/sign'], + }, + ], + }, +]; diff --git a/apps/services/cert/gateway/tsconfig.build.json b/apps/services/cert/gateway/tsconfig.build.json new file mode 100644 index 0000000..64f86c6 --- /dev/null +++ b/apps/services/cert/gateway/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] +} diff --git a/apps/services/cert/gateway/tsconfig.json b/apps/services/cert/gateway/tsconfig.json new file mode 100644 index 0000000..95f5641 --- /dev/null +++ b/apps/services/cert/gateway/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "ES2021", + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": false, + "noImplicitAny": false, + "strictBindCallApply": false, + "forceConsistentCasingInFileNames": false, + "noFallthroughCasesInSwitch": false + } +} diff --git a/apps/services/dmp/gateway/.env.dev b/apps/services/dmp/gateway/.env.dev new file mode 100644 index 0000000..663b73d --- /dev/null +++ b/apps/services/dmp/gateway/.env.dev @@ -0,0 +1,8 @@ +# 全局url前缀 +GLOBAL_PREFIX=dmp +PORT=9012 +MYSQL_HOST=localhost +MYSQL_PORT=3306 +MYSQL_USERNAME=root +MYSQL_PASSWORD=root +MYSQL_DATABASE=report diff --git a/apps/services/dmp/gateway/.env.prod b/apps/services/dmp/gateway/.env.prod new file mode 100644 index 0000000..05095db --- /dev/null +++ b/apps/services/dmp/gateway/.env.prod @@ -0,0 +1 @@ +PORT=19008 \ No newline at end of file diff --git a/apps/services/dmp/gateway/.eslintrc.js b/apps/services/dmp/gateway/.eslintrc.js new file mode 100644 index 0000000..259de13 --- /dev/null +++ b/apps/services/dmp/gateway/.eslintrc.js @@ -0,0 +1,25 @@ +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.json', + tsconfigRootDir: __dirname, + sourceType: 'module', + }, + plugins: ['@typescript-eslint/eslint-plugin'], + extends: [ + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + root: true, + env: { + node: true, + jest: true, + }, + ignorePatterns: ['.eslintrc.js'], + rules: { + '@typescript-eslint/interface-name-prefix': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-explicit-any': 'off', + }, +}; diff --git a/apps/services/dmp/gateway/.gitignore b/apps/services/dmp/gateway/.gitignore new file mode 100644 index 0000000..22f55ad --- /dev/null +++ b/apps/services/dmp/gateway/.gitignore @@ -0,0 +1,35 @@ +# compiled output +/dist +/node_modules + +# Logs +logs +*.log +npm-debug.log* +pnpm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# OS +.DS_Store + +# Tests +/coverage +/.nyc_output + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json \ No newline at end of file diff --git a/apps/services/dmp/gateway/.prettierrc b/apps/services/dmp/gateway/.prettierrc new file mode 100644 index 0000000..dcb7279 --- /dev/null +++ b/apps/services/dmp/gateway/.prettierrc @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "trailingComma": "all" +} \ No newline at end of file diff --git a/apps/services/dmp/gateway/README.md b/apps/services/dmp/gateway/README.md new file mode 100644 index 0000000..f5aa86c --- /dev/null +++ b/apps/services/dmp/gateway/README.md @@ -0,0 +1,73 @@ +

+ Nest Logo +

+ +[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 +[circleci-url]: https://circleci.com/gh/nestjs/nest + +

A progressive Node.js framework for building efficient and scalable server-side applications.

+

+NPM Version +Package License +NPM Downloads +CircleCI +Coverage +Discord +Backers on Open Collective +Sponsors on Open Collective + + Support us + +

+ + +## Description + +[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. + +## Installation + +```bash +$ pnpm install +``` + +## Running the app + +```bash +# development +$ pnpm run start + +# watch mode +$ pnpm run start:dev + +# production mode +$ pnpm run start:prod +``` + +## Test + +```bash +# unit tests +$ pnpm run test + +# e2e tests +$ pnpm run test:e2e + +# test coverage +$ pnpm run test:cov +``` + +## Support + +Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). + +## Stay in touch + +- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) +- Website - [https://nestjs.com](https://nestjs.com/) +- Twitter - [@nestframework](https://twitter.com/nestframework) + +## License + +Nest is [MIT licensed](LICENSE). diff --git a/apps/services/dmp/gateway/nest-cli.json b/apps/services/dmp/gateway/nest-cli.json new file mode 100644 index 0000000..f9aa683 --- /dev/null +++ b/apps/services/dmp/gateway/nest-cli.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/nest-cli", + "collection": "@nestjs/schematics", + "sourceRoot": "src", + "compilerOptions": { + "deleteOutDir": true + } +} diff --git a/apps/services/dmp/gateway/package.json b/apps/services/dmp/gateway/package.json new file mode 100644 index 0000000..a0e062c --- /dev/null +++ b/apps/services/dmp/gateway/package.json @@ -0,0 +1,52 @@ +{ + "name": "@tavi/dmp-gateway", + "version": "1.0.0", + "scripts": { + "build": "nest build", + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", + "start": "nest start", + "start:dev": "cross-env NODE_ENV=dev nest start --watch", + "start:debug": "nest start --debug --watch", + "start:prod": "cross-env NODE_ENV=prod node dist/main", + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix" + }, + "dependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "reflect-metadata": "^0.1.13", + "@nestjs/config": "3.0.0", + "rxjs": "7.8.1", + "nats": "2.15.1", + "@nestjs/microservices": "10.0.5", + "nacos": "2.5.1", + "cross-env": "7.0.3", + "cookie-parser": "1.4.6", + "@nestjs/typeorm": "10.0.0", + "typeorm": "0.3.17", + "class-validator": "0.14.0", + "class-transformer": "0.5.1", + "uuid": "9.0.0", + "dayjs": "1.11.9" + }, + "devDependencies": { + "@nestjs/cli": "^10.0.0", + "@nestjs/schematics": "^10.0.0", + "@nestjs/testing": "^10.0.0", + "@types/express": "^4.17.17", + "@types/node": "^20.3.1", + "@types/supertest": "^2.0.12", + "@typescript-eslint/eslint-plugin": "^5.59.11", + "@typescript-eslint/parser": "^5.59.11", + "eslint": "^8.42.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^4.2.1", + "prettier": "^2.8.8", + "source-map-support": "^0.5.21", + "supertest": "^6.3.3", + "ts-loader": "^9.4.3", + "ts-node": "^10.9.1", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.1.3" + } +} \ No newline at end of file diff --git a/apps/services/dmp/gateway/src/app.controller.ts b/apps/services/dmp/gateway/src/app.controller.ts new file mode 100644 index 0000000..1c0e55a --- /dev/null +++ b/apps/services/dmp/gateway/src/app.controller.ts @@ -0,0 +1,12 @@ +import { Controller, Get } from '@nestjs/common'; +import { AppService } from './app.service'; + +@Controller() +export class AppController { + constructor(private readonly appService: AppService) {} + + @Get('test') + getHello(): string { + return this.appService.getHello(); + } +} diff --git a/apps/services/dmp/gateway/src/app.module.ts b/apps/services/dmp/gateway/src/app.module.ts new file mode 100644 index 0000000..393366f --- /dev/null +++ b/apps/services/dmp/gateway/src/app.module.ts @@ -0,0 +1,49 @@ +import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; +import { ConfigModule } from '@nestjs/config'; +import { ClientsModule, Transport } from '@nestjs/microservices'; +import { APP_FILTER, APP_GUARD } from '@nestjs/core'; +import { AuthGuard } from './guard/auth.guard'; +import { ForbiddenExceptionFilter } from './filter/forbid.filter'; +import { AuthController } from './auth/auth.controller'; +import { UserModule } from './user/user.module'; +import * as cookieParser from 'cookie-parser'; + +@Module({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + envFilePath: `.env.${process.env.NODE_ENV}`, + }), + ClientsModule.register([ + { + name: 'Client', + transport: Transport.NATS, + options: { + servers: ['nats://localhost:4222'], + maxReconnectAttempts: 5, + reconnectTimeWait: 1000, + }, + }, + ]), + UserModule, + ], + controllers: [AppController, AuthController], + providers: [ + AppService, + { + provide: APP_GUARD, + useClass: AuthGuard, + }, + { + provide: APP_FILTER, + useClass: ForbiddenExceptionFilter, + }, + ], +}) +export class AppModule implements NestModule { + configure(consumer: MiddlewareConsumer) { + consumer.apply(cookieParser()).forRoutes('*'); + } +} diff --git a/apps/services/dmp/gateway/src/app.service.ts b/apps/services/dmp/gateway/src/app.service.ts new file mode 100644 index 0000000..927d7cc --- /dev/null +++ b/apps/services/dmp/gateway/src/app.service.ts @@ -0,0 +1,8 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class AppService { + getHello(): string { + return 'Hello World!'; + } +} diff --git a/apps/services/dmp/gateway/src/auth/auth.controller.ts b/apps/services/dmp/gateway/src/auth/auth.controller.ts new file mode 100644 index 0000000..677602b --- /dev/null +++ b/apps/services/dmp/gateway/src/auth/auth.controller.ts @@ -0,0 +1,53 @@ +import { Body, Controller, Inject, Post, Req, Res } from '@nestjs/common'; +import { ClientProxy } from '@nestjs/microservices'; +import { UserLoginDto } from './auth.dto'; +import { firstValueFrom } from 'rxjs'; +import { Response, Request } from 'express'; + +@Controller('auth') +export class AuthController { + constructor(@Inject('Client') private readonly client: ClientProxy) {} + + @Post('signIn') + async auth( + @Req() request: Request, + @Body() userLoginDto: UserLoginDto, + @Res({ passthrough: true }) res: Response, + ) { + const { username, password } = userLoginDto; + const { isLegal, data, msg } = await firstValueFrom( + this.client.send({ cmd: 'cert.user.account' }, { username, password }), + ); + // 日志 + await firstValueFrom( + this.client.send( + { cmd: 'logger.user.signIn' }, + { + platform: 'dmp', + username, + finger: request.headers['x-finger'] as string, + finger2: request.headers['x-finger2'] as string, + isLegal, + }, + ), + ); + if (isLegal) { + // 签发token,签用户的角色,前端UI路由鉴权 + const { roles } = data; + const { token } = await firstValueFrom( + this.client.send({ cmd: 'cert.token.create' }, { username, roles }), + ); + const { tokenKeyInCookie, expires } = await firstValueFrom( + this.client.send({ cmd: 'cert.token.config' }, []), + ); + res.cookie(tokenKeyInCookie, token, { + maxAge: expires * 1000, + httpOnly: true, + }); + const { password, ...rest } = data; + return { code: 0, data: rest, msg: '登陆成功' }; + } else { + return { code: 1, msg }; + } + } +} diff --git a/apps/services/dmp/gateway/src/auth/auth.dto.ts b/apps/services/dmp/gateway/src/auth/auth.dto.ts new file mode 100644 index 0000000..5dedea2 --- /dev/null +++ b/apps/services/dmp/gateway/src/auth/auth.dto.ts @@ -0,0 +1,4 @@ +export class UserLoginDto { + username: string; + password: string; +} diff --git a/apps/services/dmp/gateway/src/filter/forbid.filter.ts b/apps/services/dmp/gateway/src/filter/forbid.filter.ts new file mode 100644 index 0000000..df7d81a --- /dev/null +++ b/apps/services/dmp/gateway/src/filter/forbid.filter.ts @@ -0,0 +1,25 @@ +import { + ExceptionFilter, + Catch, + ArgumentsHost, + ForbiddenException, +} from '@nestjs/common'; +import { Response } from 'express'; + +@Catch(ForbiddenException) +export class ForbiddenExceptionFilter implements ExceptionFilter { + catch(exception: ForbiddenException, host: ArgumentsHost) { + const ctx = host.switchToHttp(); + const response = ctx.getResponse(); + const request = ctx.getRequest(); + const status = exception.getStatus(); + response.status(status).json({ + statusCode: status, + timestamp: new Date().toISOString(), + path: request.url, + msg: exception.message, + }); + // 你可以设置一个重定向地址 + // response.redirect('/'); + } +} diff --git a/apps/services/dmp/gateway/src/guard/auth.guard.ts b/apps/services/dmp/gateway/src/guard/auth.guard.ts new file mode 100644 index 0000000..c7f81e5 --- /dev/null +++ b/apps/services/dmp/gateway/src/guard/auth.guard.ts @@ -0,0 +1,75 @@ +import { + Injectable, + CanActivate, + ExecutionContext, + ForbiddenException, + Inject, +} from '@nestjs/common'; +import { ClientProxy } from '@nestjs/microservices'; +import { firstValueFrom } from 'rxjs'; +import { Request } from 'express'; + +@Injectable() +export class AuthGuard implements CanActivate { + constructor(@Inject('Client') private readonly client: ClientProxy) {} + + async canActivate(context: ExecutionContext): Promise { + const request: Request = context.switchToHttp().getRequest(); + + // 登录接口 + if ('/dmp/auth/signIn' === request.url) { + const { username } = request.body; + const { allow } = await this.rolePermissionAllow( + { username }, + request.url, + ); + if (!allow) throw new ForbiddenException('无权限访问'); + return true; + } + + // 获取token的配置 + const { tokenKeyInCookie, tokenResignIn, expires } = await firstValueFrom( + this.client.send({ cmd: 'cert.token.config' }, []), + ); + const tokenCipher = request.cookies[tokenKeyInCookie]; + if (!tokenCipher) throw new ForbiddenException('您没有执行此操作的权限'); + + // 1.验证token是否合法 + const { tokenValid, payload } = await firstValueFrom( + this.client.send({ cmd: 'cert.token.decode' }, tokenCipher), + ); + if (!tokenValid) throw new ForbiddenException('您没有执行此操作的权限'); + + // 2.token续签 + const { exp } = payload; + const tokenExpiredSoon = tokenResignIn * 1000 > exp * 1000 - Date.now(); + if (tokenExpiredSoon) { + const { username } = payload; + const { token: newToken } = await firstValueFrom( + this.client.send({ cmd: 'cert.token.create' }, { username }), + ); + request.res.cookie(tokenKeyInCookie, newToken, { + maxAge: expires * 1000, + httpOnly: true, + }); + } + + // 3.验证角色授权 + const { allow } = await this.rolePermissionAllow(payload, request.url); + if (!allow) throw new ForbiddenException('无权限访问'); + return true; + } + + /** + * 用户是否有权限 + */ + async rolePermissionAllow(payload: { username: string }, requestUrl: string) { + const { allow } = await firstValueFrom( + this.client.send( + { cmd: 'cert.role.authorize' }, + { user: payload, url: requestUrl }, + ), + ); + return { allow }; + } +} diff --git a/apps/services/dmp/gateway/src/main.ts b/apps/services/dmp/gateway/src/main.ts new file mode 100644 index 0000000..30d42e1 --- /dev/null +++ b/apps/services/dmp/gateway/src/main.ts @@ -0,0 +1,26 @@ +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app.module'; +import * as cookieParser from 'cookie-parser'; +import { ConfigService } from '@nestjs/config'; +import { ValidationPipe } from '@nestjs/common'; + +async function bootstrap() { + const app = await NestFactory.create(AppModule); + // 开启全局验证 + const configService = app.get(ConfigService); + const port = configService.get('PORT'); + app.use(cookieParser()); + app.useGlobalPipes(new ValidationPipe()); + app.setGlobalPrefix(configService.get('GLOBAL_PREFIX')); + await app.listen(port); + // 控制输出项目的全部接口 + const router = app.getHttpServer()._events.request._router; + const routerList = router.stack + .map((item) => ({ + name: item.route?.path, + methodType: item.route?.stack[0].method, + })) + .filter((i) => !!i.name && !!i.methodType); + console.log(routerList); +} +bootstrap(); diff --git a/apps/services/dmp/gateway/src/user/user.controller.ts b/apps/services/dmp/gateway/src/user/user.controller.ts new file mode 100644 index 0000000..6c44b62 --- /dev/null +++ b/apps/services/dmp/gateway/src/user/user.controller.ts @@ -0,0 +1,16 @@ +import { Controller, Get, Inject } from '@nestjs/common'; +import { ClientProxy } from '@nestjs/microservices'; +import { firstValueFrom } from 'rxjs'; + +@Controller('user') +export class UserController { + constructor(@Inject('Client') private readonly client: ClientProxy) {} + + @Get('find/annotator') + async findAnnotator() { + const { data } = await firstValueFrom( + this.client.send({ cmd: 'cert.user.find.annotator' }, {}), + ); + return { data, code: 0 }; + } +} diff --git a/apps/services/dmp/gateway/src/user/user.module.ts b/apps/services/dmp/gateway/src/user/user.module.ts new file mode 100644 index 0000000..2cf8b4d --- /dev/null +++ b/apps/services/dmp/gateway/src/user/user.module.ts @@ -0,0 +1,22 @@ +import { Module } from '@nestjs/common'; +import { UserController } from './user.controller'; +import { ClientsModule, Transport } from '@nestjs/microservices'; + +@Module({ + imports: [ + ClientsModule.register([ + { + name: 'Client', + transport: Transport.NATS, + options: { + servers: ['nats://localhost:4222'], + maxReconnectAttempts: 5, + reconnectTimeWait: 1000, + }, + }, + ]), + ], + controllers: [UserController], + providers: [], +}) +export class UserModule {} diff --git a/apps/services/dmp/gateway/tsconfig.build.json b/apps/services/dmp/gateway/tsconfig.build.json new file mode 100644 index 0000000..64f86c6 --- /dev/null +++ b/apps/services/dmp/gateway/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] +} diff --git a/apps/services/dmp/gateway/tsconfig.json b/apps/services/dmp/gateway/tsconfig.json new file mode 100644 index 0000000..adb614c --- /dev/null +++ b/apps/services/dmp/gateway/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "es2017", + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": false, + "noImplicitAny": false, + "strictBindCallApply": false, + "forceConsistentCasingInFileNames": false, + "noFallthroughCasesInSwitch": false + } +} diff --git a/apps/services/logger/.env.dev b/apps/services/logger/.env.dev new file mode 100644 index 0000000..caa7eb7 --- /dev/null +++ b/apps/services/logger/.env.dev @@ -0,0 +1,8 @@ +PORT=31121 +# nacos中注册服务的名称 +NACOS_SERVICE_NAME=logger +NACOS_ADDR=127.0.0.1:8848 +NACOS_NAMESPACE=56a3b295-f319-4ced-82b5-0df2e98cc541 +# nacos配置中心 +NACOS_DATAID='test' +NACOS_GROUP='DEFAULT_GROUP' \ No newline at end of file diff --git a/apps/services/logger/.env.prod b/apps/services/logger/.env.prod new file mode 100644 index 0000000..e69de29 diff --git a/apps/services/logger/.eslintrc.js b/apps/services/logger/.eslintrc.js new file mode 100644 index 0000000..259de13 --- /dev/null +++ b/apps/services/logger/.eslintrc.js @@ -0,0 +1,25 @@ +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.json', + tsconfigRootDir: __dirname, + sourceType: 'module', + }, + plugins: ['@typescript-eslint/eslint-plugin'], + extends: [ + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + root: true, + env: { + node: true, + jest: true, + }, + ignorePatterns: ['.eslintrc.js'], + rules: { + '@typescript-eslint/interface-name-prefix': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-explicit-any': 'off', + }, +}; diff --git a/apps/services/logger/.gitignore b/apps/services/logger/.gitignore new file mode 100644 index 0000000..22f55ad --- /dev/null +++ b/apps/services/logger/.gitignore @@ -0,0 +1,35 @@ +# compiled output +/dist +/node_modules + +# Logs +logs +*.log +npm-debug.log* +pnpm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# OS +.DS_Store + +# Tests +/coverage +/.nyc_output + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json \ No newline at end of file diff --git a/apps/services/logger/.prettierrc b/apps/services/logger/.prettierrc new file mode 100644 index 0000000..dcb7279 --- /dev/null +++ b/apps/services/logger/.prettierrc @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "trailingComma": "all" +} \ No newline at end of file diff --git a/apps/services/logger/README.md b/apps/services/logger/README.md new file mode 100644 index 0000000..f5aa86c --- /dev/null +++ b/apps/services/logger/README.md @@ -0,0 +1,73 @@ +

+ Nest Logo +

+ +[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 +[circleci-url]: https://circleci.com/gh/nestjs/nest + +

A progressive Node.js framework for building efficient and scalable server-side applications.

+

+NPM Version +Package License +NPM Downloads +CircleCI +Coverage +Discord +Backers on Open Collective +Sponsors on Open Collective + + Support us + +

+ + +## Description + +[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. + +## Installation + +```bash +$ pnpm install +``` + +## Running the app + +```bash +# development +$ pnpm run start + +# watch mode +$ pnpm run start:dev + +# production mode +$ pnpm run start:prod +``` + +## Test + +```bash +# unit tests +$ pnpm run test + +# e2e tests +$ pnpm run test:e2e + +# test coverage +$ pnpm run test:cov +``` + +## Support + +Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). + +## Stay in touch + +- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) +- Website - [https://nestjs.com](https://nestjs.com/) +- Twitter - [@nestframework](https://twitter.com/nestframework) + +## License + +Nest is [MIT licensed](LICENSE). diff --git a/apps/services/logger/nest-cli.json b/apps/services/logger/nest-cli.json new file mode 100644 index 0000000..f9aa683 --- /dev/null +++ b/apps/services/logger/nest-cli.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/nest-cli", + "collection": "@nestjs/schematics", + "sourceRoot": "src", + "compilerOptions": { + "deleteOutDir": true + } +} diff --git a/apps/services/logger/package.json b/apps/services/logger/package.json new file mode 100644 index 0000000..f4acbb8 --- /dev/null +++ b/apps/services/logger/package.json @@ -0,0 +1,56 @@ +{ + "name": "@tavi/logger", + "version": "0.0.1", + "description": "", + "author": "", + "private": true, + "license": "UNLICENSED", + "scripts": { + "build": "nest build", + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", + "start": "nest start", + "start:dev": "cross-env NODE_ENV=dev nest start --watch", + "start:debug": "nest start --debug --watch", + "start:prod": "cross-env NODE_ENV=dev node dist/main", + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix" + }, + "dependencies": { + "@nestjs/common": "10.1.0", + "@nestjs/core": "10.1.0", + "@nestjs/platform-express": "10.1.0", + "reflect-metadata": "^0.1.13", + "@nestjs/config": "3.0.0", + "rxjs": "7.8.1", + "nats": "2.15.1", + "@nestjs/microservices": "10.0.5", + "nacos": "2.5.1", + "cross-env": "7.0.3", + "cookie-parser": "1.4.6", + "@casl/ability": "6.5.0", + "typeorm": "0.3.17", + "@nestjs/typeorm": "10.0.0", + "bcrypt": "5.1.0", + "minimatch": "9.0.3", + "dayjs": "1.11.9", + "flatted": "3.2.7", + "crypto-js": "4.1.1", + "@tavi/util": "workspace:*" + }, + "devDependencies": { + "@nestjs/cli": "^9.0.0", + "@nestjs/schematics": "^9.0.0", + "@types/express": "^4.17.13", + "@types/node": "18.16.12", + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^8.0.1", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-prettier": "^4.0.0", + "prettier": "^2.3.2", + "source-map-support": "^0.5.20", + "ts-loader": "^9.2.3", + "ts-node": "^10.0.0", + "tsconfig-paths": "4.2.0", + "typescript": "^5.0.0" + } +} \ No newline at end of file diff --git a/apps/services/logger/src/app.controller.ts b/apps/services/logger/src/app.controller.ts new file mode 100644 index 0000000..29ec5c6 --- /dev/null +++ b/apps/services/logger/src/app.controller.ts @@ -0,0 +1,27 @@ +import { Controller } from '@nestjs/common'; +import { AppService } from './app.service'; +import { EventPattern } from '@nestjs/microservices'; +import * as dayjs from 'dayjs'; +import { SymmetricCrypto } from '@tavi/util'; + +interface UserSignLoggerDto { + platform: string; + username: string; + finger: string; + finger2: string; + isLegal: boolean; +} + +@Controller() +export class AppController { + constructor(private readonly appService: AppService) {} + + @EventPattern({ cmd: 'logger.user.signIn' }) + async userSignIn(payload: UserSignLoggerDto) { + const dateTime = dayjs().format('YYYY-MM-DD HH:mm:ss'); + const { finger2, ...rest } = payload; + const browserInfo = new SymmetricCrypto().decrypt(finger2); + console.log({ ...rest, dateTime, browserInfo }); + return 1; + } +} diff --git a/apps/services/logger/src/app.module.ts b/apps/services/logger/src/app.module.ts new file mode 100644 index 0000000..d95e8bb --- /dev/null +++ b/apps/services/logger/src/app.module.ts @@ -0,0 +1,20 @@ +import { Module } from '@nestjs/common'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; +import { NacosModule } from './nacos/nacos.module'; +import { ConfigModule } from '@nestjs/config'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +@Module({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + envFilePath: `.env.${process.env.NODE_ENV}`, + }), + NacosModule, + ], + controllers: [AppController], + providers: [AppService], + exports: [], +}) +export class AppModule {} diff --git a/apps/services/logger/src/app.service.ts b/apps/services/logger/src/app.service.ts new file mode 100644 index 0000000..1f22f2a --- /dev/null +++ b/apps/services/logger/src/app.service.ts @@ -0,0 +1,6 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; + +@Injectable() +export class AppService {} diff --git a/apps/services/logger/src/app.util.ts b/apps/services/logger/src/app.util.ts new file mode 100644 index 0000000..9735f22 --- /dev/null +++ b/apps/services/logger/src/app.util.ts @@ -0,0 +1,21 @@ +import * as CryptoJS from 'crypto-js'; +import { parse } from 'flatted'; + +export class SymmetricCrypto { + private key: string; + + constructor(key: string) { + this.key = key; + } + + decrypt(encryptedData: string): object | null { + try { + const bytes = CryptoJS.AES.decrypt(encryptedData, this.key); + const decryptedData = bytes.toString(CryptoJS.enc.Utf8); + return parse(decryptedData); + } catch (error) { + console.error('Decryption failed:', error); + return null; + } + } +} diff --git a/apps/services/logger/src/main.ts b/apps/services/logger/src/main.ts new file mode 100644 index 0000000..14a0dc7 --- /dev/null +++ b/apps/services/logger/src/main.ts @@ -0,0 +1,19 @@ +import { MicroserviceOptions, Transport } from '@nestjs/microservices'; +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app.module'; + +async function bootstrap() { + const app = await NestFactory.createMicroservice( + AppModule, + { + transport: Transport.NATS, + options: { + servers: ['nats://localhost:4222'], // 可以指定链接到多个nats的消息队列 + maxReconnectAttempts: 5, + reconnectTimeWait: 1000, + }, + }, + ); + await app.listen(); +} +bootstrap(); diff --git a/apps/services/logger/src/nacos/nacos.module.ts b/apps/services/logger/src/nacos/nacos.module.ts new file mode 100644 index 0000000..d9daedc --- /dev/null +++ b/apps/services/logger/src/nacos/nacos.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; +import { NacosService } from './nacos.service'; + +@Module({ + providers: [NacosService], + exports: [NacosService], +}) +export class NacosModule {} diff --git a/apps/services/logger/src/nacos/nacos.service.ts b/apps/services/logger/src/nacos/nacos.service.ts new file mode 100644 index 0000000..4a2e7f9 --- /dev/null +++ b/apps/services/logger/src/nacos/nacos.service.ts @@ -0,0 +1,108 @@ +// nacos.service.ts +import { + Injectable, + OnApplicationBootstrap, + OnApplicationShutdown, +} from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { NacosConfigClient, NacosNamingClient } from 'nacos'; // ts +import * as os from 'os'; + +@Injectable() +export class NacosService + implements OnApplicationBootstrap, OnApplicationShutdown +{ + private nacosNamingClient: NacosNamingClient; + private nacosConfigClient: NacosConfigClient; + serviceName: string; + instance: { ip: string; port: number }; + group: string; + dataId: string; + constructor(private configService: ConfigService) { + this.nacosNamingClient = new NacosNamingClient({ + logger: console, + serverList: configService.get('NACOS_ADDR'), + namespace: configService.get('NACOS_NAMESPACE'), + }); + this.nacosConfigClient = new NacosConfigClient({ + namespace: configService.get('NACOS_NAMESPACE'), + serverAddr: configService.get('NACOS_ADDR'), + }); + this.serviceName = configService.get('NACOS_SERVICE_NAME'); + this.dataId = configService.get('NACOS_DATAID'); + this.group = configService.get('NACOS_GROUP'); + this.instance = { + ip: this.getServerIP(), + port: configService.get('PORT'), + }; + } + + /** + * nestjs应用被关闭前 + * @param {string} signal 'SIGTERM' | 'SIGINT' | 'SIGHUP' | 'SIGBREAK' + */ + onApplicationShutdown(signal?: string) { + if (signal) { + const { serviceName, instance, group } = this; + this.nacosNamingClient.deregisterInstance(serviceName, instance, group); + this.nacosConfigClient.close(); + } + } + + /** + * 应用完全启动&微服务也被成功启动 + */ + onApplicationBootstrap() { + const { serviceName, instance } = this; + this.nacosNamingClient.registerInstance(serviceName, instance); + } + + /** + * 先于 onApplicationBootstrap + */ + async onModuleInit() { + this.nacosNamingClient.ready(); + } + + /** + * 从nacos获取最新的配置信息 + */ + async getConfig() { + const { dataId, group } = this; + const configFromNacos = await this.nacosConfigClient.getConfig( + dataId, + group, + ); + return configFromNacos; + } + + /** + * 订阅配置中心,当远程修改nacos的配置时,触发 + */ + async subscribeConfiguration() { + const { dataId, group } = this; + this.nacosConfigClient.subscribe( + { + dataId, + group, + }, + (content) => console.log('content', content), + ); + } + + getServerIP(): string { + const networkInterfaces = os.networkInterfaces(); + for (const name of Object.keys(networkInterfaces)) { + for (const iface of networkInterfaces[name]) { + // 跳过IPv6和内部地址 + if ('IPv4' !== iface.family || iface.internal !== false) { + continue; + } + + // 返回第一个找到的IPv4地址 + return iface.address; + } + } + return 'localhost'; // 如果找不到外部IPv4地址,返回localhost + } +} diff --git a/apps/services/logger/tsconfig.build.json b/apps/services/logger/tsconfig.build.json new file mode 100644 index 0000000..64f86c6 --- /dev/null +++ b/apps/services/logger/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] +} diff --git a/apps/services/logger/tsconfig.json b/apps/services/logger/tsconfig.json new file mode 100644 index 0000000..adb614c --- /dev/null +++ b/apps/services/logger/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "es2017", + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": false, + "noImplicitAny": false, + "strictBindCallApply": false, + "forceConsistentCasingInFileNames": false, + "noFallthroughCasesInSwitch": false + } +} diff --git a/apps/services/readme.md b/apps/services/readme.md new file mode 100644 index 0000000..50ed4fe --- /dev/null +++ b/apps/services/readme.md @@ -0,0 +1,21 @@ +# 发布订阅EventPattern + +> @MessagePattern: 基于rpc比较喜欢用,一个菠萝一个坑 + +```ts +// 网关 +@Get('/hello') +async getHello(): Promise { + const pattern = { cmd: 'sum' }; + const payload = [1, 2]; + // this.client.emit(pattern,payload)没有返回值 + const it = await this.client.send(pattern, payload); + return `收到返回值: ${it}`; +} + +// 服务 +@EventPattern({ cmd: 'sum' }) +sum(data: number[]): number { + return (data || []).reduce((a, b) => a + b); +} +``` \ No newline at end of file diff --git a/construct.drawio b/construct.drawio new file mode 100644 index 0000000..5a242ee --- /dev/null +++ b/construct.drawio @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..407c9d9 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,91 @@ +version: '3.1' +services: + + nats: + image: nats + container_name: tavi-nats + restart: always + command: -m 5000 + ports: + - "4222:4222" + - "6222:6222" + - "8222:8222" + + mysql: + image: mysql:5.7 + container_name: tavi-mysql + restart: always + environment: + MYSQL_ROOT_PASSWORD: root + ports: + - "3306:3306" + + nacos: + image: nacos/nacos-server + container_name: tavi-nacos + restart: always + environment: + MODE: standalone + ports: + - "8848:8848" + + redis: + image: redis:alpine + container_name: tavi-redis + restart: always + environment: + TZ: Asia/Shanghai + command: --requirepass redis + ports: + - "6379:6379" + + postgres: + image: postgres:13.1 + container_name: tavi-postgres + restart: always + ports: + - "5432:5432" + volumes: + # postgrel->data 挂载出来 + - ./orthancOHIF/pg_data/data:/var/lib/postgresql/data + environment: + - PGDATA=/var/lib/postgresql/data + - POSTGRES_DB=tavi-orthanc + - POSTGRES_USER=orthanc + - POSTGRES_PASSWORD=orthanc + - TZ=Asia/Shanghai + + pacs: + image: osimis/orthanc:20.11.2 + container_name: tavi-orthanc + depends_on: + - postgres + restart: always + ports: + - "8042:8042" + - "4242:4242" + volumes: + # 挂载orthanc.json配置 + - ./orthancOHIF/config/orthanc.json:/etc/orthanc/orthanc.json:ro + # 不使用 postgre 存储 dicom,挂载出来到 ${ORTHANC_DB_MNT},更健康 + - ./orthancOHIF/orthanc_db:/var/lib/orthanc/db + environment: + - DICOM_WEB_PLUGIN_ENABLED=true + - POSTGRESQL_PLUGIN_ENABLED=true + - TZ=Asia/Shanghai + command: /etc/orthanc/orthanc.json + + ohifv3: + image: ohif/viewer + container_name: tavi-ohif + restart: always + ports: + - "3000:80" + environment: + - APP_CONFIG:/usr/share/nginx/html/app-config.js + volumes: + - ./orthancOHIF/ohifv3/ohif.conf:/etc/nginx/conf.d/default.conf:ro + - ./orthancOHIF/ohifv3/app-config.js:/usr/share/nginx/html/app-config.js:ro + - ./orthancOHIF/ohifv3/logo.png:/usr/share/nginx/html/logo.png:ro + depends_on: + - pacs diff --git a/orthancOHIF/.env b/orthancOHIF/.env new file mode 100644 index 0000000..ab7ec1f --- /dev/null +++ b/orthancOHIF/.env @@ -0,0 +1,22 @@ +# +# Orthanc 相关 +# + +# 挂载 orthanc.json 配置文件 +ORTHANC_CONFIG=./config/orthanc.json +# 挂载 到本地的 dicom 文件存储,需要关闭数据库插件存储,在 orthanc.json 配置 PostgreSQL->EnableStorage 设为 false +ORTHANC_DB_MNT=./orthanc_db + +# +# PostgreSQL 配置 +# + +# 数据库文件 挂在到本地位置 +POSTGRES_DATA_MNT=./pg_data/data +# 数据库文件 在容器里的路径 +PGDATA=/var/lib/postgresql/data +POSTGRES_DB=orthanc +POSTGRES_PORT=5432 +POSTGRES_USER=orthanc +POSTGRES_PASSWORD=orthanc + diff --git a/orthancOHIF/config/orthanc.json b/orthancOHIF/config/orthanc.json new file mode 100644 index 0000000..088e9ce --- /dev/null +++ b/orthancOHIF/config/orthanc.json @@ -0,0 +1,97 @@ +{ + "Name": "DICOM PACS", + "StorageDirectory": "/var/lib/orthanc/db", + "IndexDirectory": "", + "StorageCompression": false, + "MaximumStorageSize": 0, + "MaximumPatientCount": 0, + "LuaScripts": [], + "Plugins": [ + "/usr/share/orthanc/plugins" + ], + "ConcurrentJobs": 0, + "HttpServerEnabled": true, + "HttpPort": 8042, + "HttpDescribeErrors": true, + "HttpCompressionEnabled": true, + "DicomServerEnabled": true, + "DicomAet": "DICOM-ORTHANC", + "DicomCheckCalledAet": false, + "DicomPort": 4242, + "DefaultEncoding": "Utf8", + "DeflatedTransferSyntaxAccepted": true, + "JpegTransferSyntaxAccepted": true, + "Jpeg2000TransferSyntaxAccepted": true, + "JpegLosslessTransferSyntaxAccepted": true, + "JpipTransferSyntaxAccepted": true, + "Mpeg2TransferSyntaxAccepted": true, + "RleTransferSyntaxAccepted": true, + "UnknownSopClassAccepted": false, + "DicomScpTimeout": 30, + "RemoteAccessAllowed": true, + "SslEnabled": false, + "SslCertificate": "certificate.pem", + "AuthenticationEnabled": false, + "RegisteredUsers": {}, + "DicomModalities": {}, + "DicomModalitiesInDatabase": false, + "DicomAlwaysAllowEcho": true, + "DicomAlwaysAllowStore": true, + "DicomCheckModalityHost": false, + "DicomScuTimeout": 10, + "OrthancPeers": {}, + "OrthancPeersInDatabase": false, + "HttpProxy": "", + "HttpVerbose": false, + "HttpTimeout": 60, + "HttpsVerifyPeers": true, + "HttpsCACertificates": "", + "UserMetadata": {}, + "UserContentType": {}, + "StableAge": 60, + "StrictAetComparison": false, + "StoreMD5ForAttachments": true, + "LimitFindResults": 0, + "LimitFindInstances": 0, + "LimitJobs": 20, + "LogExportedResources": false, + "KeepAlive": true, + "TcpNoDelay": true, + "HttpThreadsCount": 50, + "StoreDicom": true, + "DicomAssociationCloseDelay": 5, + "QueryRetrieveSize": 100, + "CaseSensitivePN": false, + "LoadPrivateDictionary": true, + "Locale": "en_US.UTF-8", + "Dictionary": {}, + "SynchronousCMove": true, + "JobsHistorySize": 10, + "SaveJobs": true, + "OverwriteInstances": false, + "MediaArchiveSize": 1, + "StorageAccessOnFind": "Always", + "MetricsEnabled": true, + "ExecuteLuaEnabled": false, + "HttpRequestTimeout": 30, + "DicomWeb": { + "Enable": true, + "Root": "/dicom-web/", + "EnableWado": true, + "WadoRoot": "/wado", + "Ssl": false, + "QidoCaseSensitive": true, + "Host": "localhost", + "StudiesMetadata": "Full", + "SeriesMetadata": "Full" + }, + "PostgreSQL": { + "EnableIndex": true, + "EnableStorage": false, + "Host": "postgres", + "Port": 5432, + "Database": "orthanc", + "Username": "orthanc", + "Password": "orthanc" + } +} \ No newline at end of file diff --git a/orthancOHIF/docker-compose.yml b/orthancOHIF/docker-compose.yml new file mode 100644 index 0000000..135f8ab --- /dev/null +++ b/orthancOHIF/docker-compose.yml @@ -0,0 +1,53 @@ +version: "3.6" + +services: + postgres: + image: postgres:13.1 + container_name: postgres + restart: always + ports: + - "5432:5432" + volumes: + # postgrel->data 挂载出来 + - ${POSTGRES_DATA_MNT}:${PGDATA} + environment: + - PGDATA=${PGDATA} + - POSTGRES_DB=${POSTGRES_DB} + - POSTGRES_USER=${POSTGRES_USER} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + - TZ=Asia/Shanghai + + pacs: + image: osimis/orthanc:20.11.2 + container_name: orthanc + depends_on: + - postgres + restart: always + ports: + - "8042:8042" + - "4242:4242" + volumes: + # 挂载orthanc.json配置 + - ${ORTHANC_CONFIG}:/etc/orthanc/orthanc.json:ro + # 不使用 postgre 存储 dicom,挂载出来到 ${ORTHANC_DB_MNT},更健康 + - ${ORTHANC_DB_MNT}:/var/lib/orthanc/db + environment: + - DICOM_WEB_PLUGIN_ENABLED=true + - POSTGRESQL_PLUGIN_ENABLED=true + - TZ=Asia/Shanghai + command: /etc/orthanc/orthanc.json + + ohifv3: + image: ohif/viewer + container_name: ohif + restart: always + ports: + - "3000:80" + environment: + - APP_CONFIG:/usr/share/nginx/html/app-config.js + volumes: + - ./ohifv3/ohif.conf:/etc/nginx/conf.d/default.conf:ro + - ./ohifv3/app-config.js:/usr/share/nginx/html/app-config.js:ro + - ./ohifv3/logo.png:/usr/share/nginx/html/logo.png:ro + depends_on: + - pacs diff --git a/orthancOHIF/ohifv3/app-config.js b/orthancOHIF/ohifv3/app-config.js new file mode 100644 index 0000000..28f2e59 --- /dev/null +++ b/orthancOHIF/ohifv3/app-config.js @@ -0,0 +1,141 @@ +window.config = { + routerBasename: '/', + extensions: [], + showStudyList: true, + filterQueryParam: false, + servers: { + dicomWeb: [ + { + name: 'Orthanc', + wadoUriRoot: '/orthanc/wado', + qidoRoot: '/orthanc/dicom-web', + wadoRoot: '/orthanc/dicom-web', + qidoSupportsIncludeField: true, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + enableStudyLazyLoad: true, + supportsFuzzyMatching: true, + }, + ], + }, + whiteLabeling: { + /* Used to replace the default Logo */ + createLogoComponentFn: function (React) { + return React.createElement('a', { + target: '_self', + rel: 'noopener noreferrer', + className: 'header-brand', + href: '/', + style: { + display: 'block', + background: 'url(/logo.png)', + backgroundSize: 'contain', + backgroundRepeat: 'no-repeat', + width: '200px', + }, + }); + }, + }, + // Extensions should be able to suggest default values for these? + // Or we can require that these be explicitly set + hotkeys: [ + // ~ Global + { + commandName: 'incrementActiveViewport', + label: 'Next Viewport', + keys: ['right'], + }, + { + commandName: 'decrementActiveViewport', + label: 'Previous Viewport', + keys: ['left'], + }, + // Supported Keys: https://craig.is/killing/mice + // ~ Cornerstone Extension + { commandName: 'rotateViewportCW', label: 'Rotate Right', keys: ['r'] }, + { commandName: 'rotateViewportCCW', label: 'Rotate Left', keys: ['l'] }, + { commandName: 'invertViewport', label: 'Invert', keys: ['i'] }, + { + commandName: 'flipViewportVertical', + label: 'Flip Horizontally', + keys: ['h'], + }, + { + commandName: 'flipViewportHorizontal', + label: 'Flip Vertically', + keys: ['v'], + }, + { commandName: 'scaleUpViewport', label: 'Zoom In', keys: ['+'] }, + { commandName: 'scaleDownViewport', label: 'Zoom Out', keys: ['-'] }, + { commandName: 'fitViewportToWindow', label: 'Zoom to Fit', keys: ['='] }, + { commandName: 'resetViewport', label: 'Reset', keys: ['space'] }, + // clearAnnotations + { commandName: 'nextImage', label: 'Next Image', keys: ['down'] }, + { commandName: 'previousImage', label: 'Previous Image', keys: ['up'] }, + // firstImage + // lastImage + { + commandName: 'previousViewportDisplaySet', + label: 'Previous Series', + keys: ['pagedown'], + }, + { + commandName: 'nextViewportDisplaySet', + label: 'Next Series', + keys: ['pageup'], + }, + // ~ Cornerstone Tools + { commandName: 'setZoomTool', label: 'Zoom', keys: ['z'] }, + // ~ Window level presets + { + commandName: 'windowLevelPreset1', + label: 'W/L Preset 1', + keys: ['1'], + }, + { + commandName: 'windowLevelPreset2', + label: 'W/L Preset 2', + keys: ['2'], + }, + { + commandName: 'windowLevelPreset3', + label: 'W/L Preset 3', + keys: ['3'], + }, + { + commandName: 'windowLevelPreset4', + label: 'W/L Preset 4', + keys: ['4'], + }, + { + commandName: 'windowLevelPreset5', + label: 'W/L Preset 5', + keys: ['5'], + }, + { + commandName: 'windowLevelPreset6', + label: 'W/L Preset 6', + keys: ['6'], + }, + { + commandName: 'windowLevelPreset7', + label: 'W/L Preset 7', + keys: ['7'], + }, + { + commandName: 'windowLevelPreset8', + label: 'W/L Preset 8', + keys: ['8'], + }, + { + commandName: 'windowLevelPreset9', + label: 'W/L Preset 9', + keys: ['9'], + }, + ], + cornerstoneExtensionConfig: {}, + + // studyListFunctionsEnabled is set to true to enable DICOM uploading + studyListFunctionsEnabled: true + +}; \ No newline at end of file diff --git a/orthancOHIF/ohifv3/logo.png b/orthancOHIF/ohifv3/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1af344bb05669e7b7e0e3f3cc7b546b39fbce4c4 GIT binary patch literal 22335 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
IuMB+=tNQ`hssc2yFOB%8%|UTH?xJV1V| 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 literal 0 HcmV?d00001 diff --git a/orthancOHIF/ohifv3/ohif.conf b/orthancOHIF/ohifv3/ohif.conf new file mode 100644 index 0000000..d25248f --- /dev/null +++ b/orthancOHIF/ohifv3/ohif.conf @@ -0,0 +1,22 @@ +server { + listen 80; + # set client body size to 500M, this is to allow uploading of DICOMs, throws '413 request entity too large nginx' error otherwise # + client_max_body_size 500M; + location / { + root /usr/share/nginx/html; + index index.html index.htm; + try_files $uri $uri/ /index.html; + } + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + + # https://book.orthanc-server.com/faq/nginx.html#nginx + location /orthanc/ { + proxy_pass http://pacs:8042; + proxy_set_header HOST $host; + proxy_set_header X-Real-IP $remote_addr; + rewrite /orthanc(.*) $1 break; + } +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..415794d --- /dev/null +++ b/package.json @@ -0,0 +1,34 @@ +{ + "name": "@tavi-universe", + "version": "1.0.0", + "scripts": { + "dev:all": "chmod 777 ./terminal.sh && ./terminal.sh", + "mock": "pnpm run --filter @tavi/mock mock", + "dev:logger": "pnpm run --filter @tavi/logger start:dev", + "dev:dmp-web": "pnpm run --filter @tavi/dmp-web dev", + "dev:dmp-gateway": "pnpm run --filter @tavi/dmp-gateway start:dev", + "dev:aorta": "pnpm run --filter @tavi/aorta dev", + "dev:aorta-gateway": "pnpm run --filter @tavi/aorta-gateway start:dev", + "build:aorta": "pnpm run --filter @tavi/aorta build", + "analyze:aorta": "pnpm run --filter @tavi/aorta build:analyze", + "dev:cert-web": "pnpm run --filter @tavi/cert-web dev", + "dev:cert-gateway": "pnpm run --filter @tavi/cert-gateway start:dev", + "dev:authenticate": "pnpm run --filter @tavi/authenticate start:dev", + "dev:authorize": "pnpm run --filter @tavi/authorize start:dev", + "dev:report": "pnpm run --filter @tavi/report start:dev", + "dev:report-api": "pnpm run --filter @tavi/report-api start:dev", + "dev:report-web": "pnpm run --filter @tavi/report-web dev", + "build:report-web": "pnpm run --filter @tavi/report-web build", + "build:report-api": "pnpm run --filter @tavi/report-api build", + "build:util": "pnpm run --filter @tavi/util build", + "build:i18n": "pnpm run --filter @tavi/i18n build", + "build:oss": "pnpm run --filter @tavi/oss build", + "build:hook": "pnpm run --filter @tavi/hook build", + "changeset": "changeset", + "pkg:version": "changeset version", + "pkg:publish": "changeset publish" + }, + "devDependencies": { + "@changesets/cli": "^2.26.2" + } +} \ No newline at end of file diff --git a/packages/hook/package.json b/packages/hook/package.json new file mode 100644 index 0000000..e3b5396 --- /dev/null +++ b/packages/hook/package.json @@ -0,0 +1,28 @@ +{ + "name": "@tavi/hook", + "version": "1.0.0", + "main": "dist/index.esm.js", + "types": "dist/types/index.d.ts", + "type": "module", + "scripts": { + "build": "rollup -c" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^24.1.0", + "@rollup/plugin-node-resolve": "^15.0.2", + "rollup": "^3.21.5", + "rollup-plugin-typescript2": "^0.34.1", + "typescript": "^5.0.2", + "@types/node": "18.16.3", + "@types/react": "^18.0.28", + "@types/react-dom": "^18.0.11", + "@types/react-router-dom": "5.3.3" + }, + "dependencies": { + "typescript": "^5.0.4", + "axios": "1.4.0", + "react": "18.2.0", + "react-dom": "18.2.0", + "react-router-dom": "6.11.2" + } +} \ No newline at end of file diff --git a/packages/hook/rollup.config.js b/packages/hook/rollup.config.js new file mode 100644 index 0000000..42fd0dc --- /dev/null +++ b/packages/hook/rollup.config.js @@ -0,0 +1,25 @@ +import typescript from "rollup-plugin-typescript2"; +import resolve from "@rollup/plugin-node-resolve"; +import commonjs from "@rollup/plugin-commonjs"; + + +export default { + input: "src/index.ts", + output: [ + { + file: "dist/index.esm.js", + format: "es", + globals: { + react: 'React', + } + } + ], + external: ['react'], + plugins: [ + typescript({ + useTsconfigDeclarationDir: true, + }), + resolve(), + commonjs(), + ], +}; \ No newline at end of file diff --git a/packages/hook/src/index.ts b/packages/hook/src/index.ts new file mode 100644 index 0000000..1b3cf67 --- /dev/null +++ b/packages/hook/src/index.ts @@ -0,0 +1 @@ +export { useAxios } from "./useAxios"; diff --git a/packages/hook/src/useAxios.tsx b/packages/hook/src/useAxios.tsx new file mode 100644 index 0000000..cf059e0 --- /dev/null +++ b/packages/hook/src/useAxios.tsx @@ -0,0 +1,40 @@ +import { AxiosInstance, Method } from "axios"; +import { useEffect, useState } from "react"; + +interface IProps { + url: string; + method?: Extract; + requestConfig?: any; + axiosInstance: AxiosInstance; +} + +export function useAxios(props: IProps) { + const { axiosInstance, url, method = "get", requestConfig = {} } = props; + // 创建一个取消源 + const [data, setData] = useState(); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(); + + useEffect(() => { + const controller = new AbortController(); + + const fetchData = async () => { + try { + const response = await axiosInstance[method](url, { + ...requestConfig, + signal: controller.signal, + }); + setData(response.data); + } catch (error) { + setError(error); + } finally { + setLoading(false); + } + }; + + if (url) fetchData(); + return () => controller.abort(); + }, [axiosInstance, method, url]); + + return { data, error, loading }; +} diff --git a/packages/hook/tsconfig.json b/packages/hook/tsconfig.json new file mode 100644 index 0000000..983e531 --- /dev/null +++ b/packages/hook/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + // build 输出的目标版本 + "target": "ESNext", + // 模块引入 + "module": "ESNext", + // 从项目中的TypeScript和JavaScript文件生成.d.ts文件。 + "declaration": true, + // 指定TypeScript如何从给定的模块说明符中查找文件。 + "moduleResolution": "node", + // 指定TypeScript如何从给定的模块说明符中查找文件。 + "declarationDir": "./dist/types", + "jsx": "react-jsx" + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules", + "**/*.spec.ts" + ] +} \ No newline at end of file diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md new file mode 100644 index 0000000..551f01e --- /dev/null +++ b/packages/i18n/CHANGELOG.md @@ -0,0 +1,32 @@ +# @tavi/i18n + +## 1.5.0 + +### Minor Changes + +- test3 + +## 1.4.0 + +### Minor Changes + +- update test + +## 1.3.0 + +### Minor Changes + +- test2 + +## 1.2.0 + +### Minor Changes + +- test + +## 1.1.0 + +### Minor Changes + +- 1.0.1 +- 1.0.0 diff --git a/packages/i18n/package.json b/packages/i18n/package.json new file mode 100644 index 0000000..74ef347 --- /dev/null +++ b/packages/i18n/package.json @@ -0,0 +1,33 @@ +{ + "name": "@tavi/i18n", + "version": "1.5.0", + "main": "dist/index.js", + "types": "dist/types/index.d.ts", + "type": "module", + "scripts": { + "build": "rollup -c" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^24.1.0", + "@rollup/plugin-node-resolve": "^15.0.2", + "rollup-plugin-terser": "7.0.2", + "rollup": "^3.21.5", + "rollup-plugin-typescript2": "^0.34.1", + "typescript": "^5.0.2", + "@types/node": "18.16.3", + "@types/react": "^18.0.28", + "@types/react-dom": "^18.0.11", + "@types/react-router-dom": "5.3.3", + "rollup-plugin-node-polyfills": "0.2.1" + }, + "dependencies": { + "typescript": "^5.0.4", + "i18next": "22.5.0", + "react-i18next": "12.3.1", + "i18next-browser-languagedetector": "7.0.1", + "i18next-http-backend": "2.2.1", + "react": "18.2.0", + "react-dom": "18.2.0", + "react-router-dom": "6.11.2" + } +} \ No newline at end of file diff --git a/packages/i18n/rollup.config.js b/packages/i18n/rollup.config.js new file mode 100644 index 0000000..9e5388e --- /dev/null +++ b/packages/i18n/rollup.config.js @@ -0,0 +1,24 @@ +import typescript from "rollup-plugin-typescript2"; +import resolve from '@rollup/plugin-node-resolve'; +import commonjs from '@rollup/plugin-commonjs'; +import { terser } from "rollup-plugin-terser"; + +export default { + input: "src/index.ts", + output: [ + { + file: "dist/index.js", + format: "esm", + sourcemap: true, + } + ], + external: ['i18next', 'react-i18next', 'i18next-browser-languagedetector', 'i18next-http-backend'], + plugins: [ + typescript({ + useTsconfigDeclarationDir: true, + }), + resolve({ preferBuiltins: true }), + commonjs(), + terser() + ], +}; \ No newline at end of file diff --git a/packages/i18n/src/index.ts b/packages/i18n/src/index.ts new file mode 100644 index 0000000..b2d5c68 --- /dev/null +++ b/packages/i18n/src/index.ts @@ -0,0 +1,48 @@ +import i18n from "i18next"; +import { initReactI18next, useTranslation } from "react-i18next"; +import LanguageDetector from "i18next-browser-languagedetector"; +import Backend from "i18next-http-backend"; + +interface i18nProps { + /** + * 读取i18n translation.json的文件根目录,打包后,翻译json指向 dist/locales + * @default /locales/{{lng}}/{{ns}}.json + */ + loadPath?: string; + /** + * 如果用户语言翻译无效,默认使用的语言 + * @default zhCN + */ + fallbackLng?: string; + /** + * 是否控制台输出i18n信息 + * @default false + */ + debug?: boolean; +} + +export const useI18n = (p?: i18nProps) => { + const { + loadPath = "/locales/{{lng}}/{{ns}}.json", + fallbackLng = "zhCN", + debug = false, + } = p; + i18n + .use(Backend) + // 检测用户当前使用的语言 + // 文档: https://github.com/i18next/i18next-browser-languageDetector + .use(LanguageDetector) + // 注入 react-i18next 实例 + .use(initReactI18next) + // 初始化 i18next + // 配置参数的文档: https://www.i18next.com/overview/configuration-options + .init({ + debug, // 控制台输出信息 + fallbackLng, // 如果用户语言的翻译不可用,请使用的语言。 + interpolation: { escapeValue: false }, + backend: { loadPath }, + }); + return { i18n }; +}; + +export { useTranslation }; diff --git a/packages/i18n/tsconfig.json b/packages/i18n/tsconfig.json new file mode 100644 index 0000000..983e531 --- /dev/null +++ b/packages/i18n/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + // build 输出的目标版本 + "target": "ESNext", + // 模块引入 + "module": "ESNext", + // 从项目中的TypeScript和JavaScript文件生成.d.ts文件。 + "declaration": true, + // 指定TypeScript如何从给定的模块说明符中查找文件。 + "moduleResolution": "node", + // 指定TypeScript如何从给定的模块说明符中查找文件。 + "declarationDir": "./dist/types", + "jsx": "react-jsx" + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules", + "**/*.spec.ts" + ] +} \ No newline at end of file diff --git a/packages/mock/package.json b/packages/mock/package.json new file mode 100644 index 0000000..b888f09 --- /dev/null +++ b/packages/mock/package.json @@ -0,0 +1,11 @@ +{ + "name": "@tavi/mock", + "version": "1.0.0", + "description": "mock服务,方便开发调试", + "scripts": { + "mock": "serve public/" + }, + "devDependencies": { + "serve": "14.2.0" + } +} \ No newline at end of file diff --git a/packages/mock/public/report_patient.json b/packages/mock/public/report_patient.json new file mode 100644 index 0000000..1c57da2 --- /dev/null +++ b/packages/mock/public/report_patient.json @@ -0,0 +1,3 @@ +{ + "hello": "this is mock" +} \ No newline at end of file diff --git a/packages/oss/package.json b/packages/oss/package.json new file mode 100644 index 0000000..c5c8236 --- /dev/null +++ b/packages/oss/package.json @@ -0,0 +1,23 @@ +{ + "name": "@tavi/oss", + "version": "1.0.0", + "main": "dist/index.cjs", + "module": "dist/index.esm.js", + "types": "dist/types/index.d.ts", + "type": "module", + "scripts": { + "build": "rollup -c" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^24.1.0", + "@rollup/plugin-node-resolve": "^15.0.2", + "rollup": "^3.21.5", + "rollup-plugin-typescript2": "^0.34.1", + "typescript": "^5.0.2", + "tslib": "2.6.0", + "@types/node": "20.3.3" + }, + "dependencies": { + "minio": "7.1.1" + } +} \ No newline at end of file diff --git a/packages/oss/rollup.config.js b/packages/oss/rollup.config.js new file mode 100644 index 0000000..41821b6 --- /dev/null +++ b/packages/oss/rollup.config.js @@ -0,0 +1,24 @@ +import typescript from "rollup-plugin-typescript2"; +import resolve from "@rollup/plugin-node-resolve"; +import commonjs from "@rollup/plugin-commonjs"; + +export default { + input: 'src/index.ts', + output: [ + { + file: "dist/index.esm.js", + format: "es", + }, + { + file: "dist/index.cjs", + format: "cjs", + } + ], + plugins: [ + typescript({ + useTsconfigDeclarationDir: true, + }), + resolve(), + commonjs(), + ], +}; \ No newline at end of file diff --git a/packages/oss/src/index.ts b/packages/oss/src/index.ts new file mode 100644 index 0000000..22fbf10 --- /dev/null +++ b/packages/oss/src/index.ts @@ -0,0 +1 @@ +export { MinioOSS } from "./minio"; diff --git a/packages/oss/src/minio/index.ts b/packages/oss/src/minio/index.ts new file mode 100644 index 0000000..1540447 --- /dev/null +++ b/packages/oss/src/minio/index.ts @@ -0,0 +1,58 @@ +const Minio = require("minio"); +const util = require("util"); + +type PutObject = { + /* + * 文件Buffer + */ + file: Buffer; + /** + * 存储桶中文件的名称 + */ + objectName: string; + /** + * minio存储桶名称 + */ + bucketName: string; +}; + +type GetObject = { + /** + * 存储桶中文件的名称 + */ + objectName: string; + /** + * minio存储桶名称 + */ + bucketName: string; +}; + +type Client = { + endPoint: string; + port: number; + useSSL: boolean; + accessKey: string; + secretKey: string; +}; +export class MinioOSS { + config: Client; + /** + * minio的client + */ + client: any; + constructor(p: Client) { + this.config = p; + this.client = new Minio.Client(p); + } + /** + * 上传文件 + */ + public put(p: PutObject) { + const { file, objectName, bucketName } = p; + return new Promise((resolve, reject) => { + this.client.putObject(bucketName, objectName, file, (err, etag) => { + !err ? resolve({ ...etag, code: "uploaded" }) : reject(err); + }); + }); + } +} diff --git a/packages/oss/tsconfig.json b/packages/oss/tsconfig.json new file mode 100644 index 0000000..faadd41 --- /dev/null +++ b/packages/oss/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "module": "ESNext", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "es2020", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": false, + "noImplicitAny": false, + // 指定TypeScript如何从给定的模块说明符中查找文件。 + "moduleResolution": "node", + // 指定TypeScript如何从给定的模块说明符中查找文件。 + "declarationDir": "./dist/types" + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules", + "**/*.spec.ts" + ] +} \ No newline at end of file diff --git a/packages/util/package.json b/packages/util/package.json new file mode 100644 index 0000000..7d8f05d --- /dev/null +++ b/packages/util/package.json @@ -0,0 +1,34 @@ +{ + "name": "@tavi/util", + "version": "1.0.0", + "module": "dist/index.esm.mjs", + "main": "dist/index.js", + "types": "dist/types/index.d.ts", + "scripts": { + "build": "rollup -c --bundleConfigAsCjs" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^24.1.0", + "@rollup/plugin-node-resolve": "^15.0.2", + "rollup": "^3.21.5", + "rollup-plugin-typescript2": "^0.34.1", + "typescript": "^5.0.2", + "@types/node": "18.16.3", + "@types/react": "^18.0.28", + "@types/react-dom": "^18.0.11", + "@types/react-router-dom": "5.3.3", + "tslib": "2.6.0" + }, + "dependencies": { + "typescript": "^5.0.4", + "axios": "1.4.0", + "react": "18.2.0", + "react-dom": "18.2.0", + "react-router-dom": "6.11.2", + "html2canvas": "1.4.1", + "jspdf": "2.5.1", + "@fingerprintjs/fingerprintjs": "4.0.1", + "flatted": "3.2.7", + "crypto-js": "4.1.1" + } +} \ No newline at end of file diff --git a/packages/util/rollup.config.js b/packages/util/rollup.config.js new file mode 100644 index 0000000..98a1cd2 --- /dev/null +++ b/packages/util/rollup.config.js @@ -0,0 +1,28 @@ +import typescript from "rollup-plugin-typescript2"; +import resolve from "@rollup/plugin-node-resolve"; +import commonjs from "@rollup/plugin-commonjs"; + + +export default { + input: "src/index.ts", + output: [ + { + file: "dist/index.js", + format: "cjs", + inlineDynamicImports: true + }, + { + file: "dist/index.esm.mjs", + format: "esm", + inlineDynamicImports: true + } + ], + external: ['crypto-js', 'flatted', 'html2canvas', 'jspdf'], + plugins: [ + typescript({ + useTsconfigDeclarationDir: true + }), + resolve(), + commonjs(), + ], +}; \ No newline at end of file diff --git a/packages/util/src/SymmetricCrypto.ts b/packages/util/src/SymmetricCrypto.ts new file mode 100644 index 0000000..d4cf1d9 --- /dev/null +++ b/packages/util/src/SymmetricCrypto.ts @@ -0,0 +1,26 @@ +import * as CryptoJS from "crypto-js"; +import { parse, stringify } from "flatted"; + +export class SymmetricCrypto { + private key: string; + + constructor(key?: string) { + this.key = key ?? "x-finger2"; + } + + encrypt(data: Record): string { + const flattedData = stringify(data); + return CryptoJS.AES.encrypt(flattedData, this.key).toString(); + } + + decrypt(encryptedData: string): object | null { + try { + const bytes = CryptoJS.AES.decrypt(encryptedData, this.key); + const decryptedData = bytes.toString(CryptoJS.enc.Utf8); + return parse(decryptedData); + } catch (error) { + console.error("Decryption failed:", error); + return null; + } + } +} diff --git a/packages/util/src/biz.code.ts b/packages/util/src/biz.code.ts new file mode 100644 index 0000000..eea1e72 --- /dev/null +++ b/packages/util/src/biz.code.ts @@ -0,0 +1,8 @@ +export enum BizCode { + OK = 0, + FAIL, +} + +export enum BizMsg { + OK = "成功", +} diff --git a/packages/util/src/dom2.ts b/packages/util/src/dom2.ts new file mode 100644 index 0000000..c51d54c --- /dev/null +++ b/packages/util/src/dom2.ts @@ -0,0 +1,102 @@ +import html2canvas from "html2canvas"; +import { jsPDF } from "jspdf"; + +export interface Dom2Img { + /** + * 需要截图的dom元素 + */ + element: HTMLElement; + /** + * 清晰度控制 + * @default 4 + */ + scale?: number; +} + +/** + * dom转图片 + * 250ms - 350ms之间,平均 300ms/张图 + */ +export const dom2Img = async (p: Dom2Img) => { + const { element, scale = 4 } = p; + const canvas = await html2canvas(element, { scale, useCORS: true }); + return canvas.toDataURL("image/png"); +}; + +export interface Dom2PDF { + /** + * 需要截图的dom元素,多个elements传入dom的数组 + */ + elements: HTMLElement[]; + /** + * 清晰度控制,影响导出速度 + * @default 4 + */ + scale?: number; + /** + * 方向 + */ + orientation?: "p" | "portrait" | "l" | "landscape"; + /** + * jspdf目标尺寸 + * @default a4 + */ + format?: "a4" | string | number[]; + /** + * jspdf单位 + * @default mm + */ + unit?: "pt" | "px" | "in" | "mm" | "cm" | "ex" | "em" | "pc"; + /** + * 压缩pdf + * @default true + */ + compress?: boolean; + /** + * 生成进度 + * @param {number} pageNum 已生成的页码 + * @param {number} totalPage 全部页码 + */ + onProgress?: (pageNum: number, totalPage: number) => void; +} + +/** + * dom转pdf高清,默认开启压缩,compression = FAST + */ +export const dom2PDF = async (p: Dom2PDF): Promise => { + const { + elements, + scale = 4, + format = "a4", + unit = "mm", + orientation = "p", + compress = true, + } = p; + const pdf = new jsPDF({ orientation, unit, format, compress }); + for (let i = 0; i < elements.length; i++) { + const imgData = await dom2Img({ element: elements[i], scale }); + const { width, height } = pdf.getImageProperties(imgData); + const pdfWidth = pdf.internal.pageSize.getWidth(); + const pdfHeight = (height * pdfWidth) / width; + /** + * scale=4 + png + 默认情况下,耗时 ≈ 2500ms + * 1.FAST 耗时 ≈ 1400ms + * 2.scale=3 耗时 ≈ 850ms + */ + console.time("fast"); + pdf.addImage( + imgData, + "PNG", + 0, + 0, + pdfWidth, + pdfHeight, + `page-${i + 1}`, + "FAST" + ); + console.timeEnd("fast"); + if (i !== elements.length - 1) pdf.addPage(); + p.onProgress && p.onProgress(i + 1, elements.length); + } + return pdf; +}; diff --git a/packages/util/src/finger.ts b/packages/util/src/finger.ts new file mode 100644 index 0000000..990b7d7 --- /dev/null +++ b/packages/util/src/finger.ts @@ -0,0 +1,10 @@ +import FingerprintJS from "@fingerprintjs/fingerprintjs"; + +/** + * 生成浏览器指纹 + */ +export const getFingerprint = async () => { + const fp = await FingerprintJS.load(); + const result = await fp.get(); + return result.visitorId; // This is the visitor's unique fingerprint +}; diff --git a/packages/util/src/index.ts b/packages/util/src/index.ts new file mode 100644 index 0000000..e63e4f2 --- /dev/null +++ b/packages/util/src/index.ts @@ -0,0 +1,7 @@ +export { Dom2Img, dom2PDF, dom2Img } from "./dom2"; +export { BizCode, BizMsg } from "./biz.code"; +export { getFingerprint } from "./finger"; + +export * as REG from "./regexp"; +export { SDK_Logger } from "./logger"; +export { SymmetricCrypto } from "./SymmetricCrypto"; diff --git a/packages/util/src/logger.ts b/packages/util/src/logger.ts new file mode 100644 index 0000000..cfcd4ee --- /dev/null +++ b/packages/util/src/logger.ts @@ -0,0 +1,40 @@ +interface SDK_INIT_TYPE { + app_id: string; + tracking_attr?: string; +} + +declare global { + interface Window { + sdk_logger: SDK_Logger; + } +} + +export class SDK_Logger { + app_id: string; + tracking_attr: string; + constructor(p: SDK_INIT_TYPE) { + this.app_id = p.app_id; + this.tracking_attr = p?.tracking_attr ?? "data-tracking-id"; + this.initialize(); + } + + initialize() { + console.log(`SDK_Logger init successfully, using appid: ${this.app_id}`); + } + + /** + * 事件冒泡查找点击元素的trackingId + * @param {HTMLElement} target 被查找的目标元素 + * @param {number} maxLevels 最大向上查找的层级 + * @returns + */ + findTrackingId(target: HTMLElement | null, maxLevels = 5) { + const { tracking_attr } = this; + let t = target; + while (t && maxLevels-- && !t.hasAttribute(tracking_attr)) + t = t.parentElement; + return t && t.hasAttribute(tracking_attr) + ? t.getAttribute(tracking_attr) + : ""; + } +} diff --git a/packages/util/src/regexp.ts b/packages/util/src/regexp.ts new file mode 100644 index 0000000..c818f5c --- /dev/null +++ b/packages/util/src/regexp.ts @@ -0,0 +1,8 @@ +// 手机号 +export const phoneNumber = /^1(3|4|5|6|7|8|9)\d{9}$/; + +// 大写、小写、字母、特殊字符 都有 +export const password = /(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[\W_]).{6,20}/; + +// 不可全为空格和换行,允许字符前面和后面为空 +export const notNull = /^[\s\S]*.*[^\s][\s\S]*$/; diff --git a/packages/util/tsconfig.json b/packages/util/tsconfig.json new file mode 100644 index 0000000..dfa7d18 --- /dev/null +++ b/packages/util/tsconfig.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + // build 输出的目标版本 + "target": "es2017", + "lib": [ + "es2015", + "es2016", + "es2017", + "dom", + ], + // 模块引入 + "module": "ESNext", + // 从项目中的TypeScript和JavaScript文件生成.d.ts文件。 + "declaration": true, + // 指定TypeScript如何从给定的模块说明符中查找文件。 + "moduleResolution": "node", + // 指定TypeScript如何从给定的模块说明符中查找文件。 + "declarationDir": "./dist/types", + "baseUrl": ".", + "paths": { + "tslib": [ + "path/to/node_modules/tslib/tslib.d.ts" + ] + } + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules", + "**/*.spec.ts" + ] +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..f2afdc9 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,13830 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@changesets/cli': + specifier: ^2.26.2 + version: 2.26.2 + + apps/aorta: + dependencies: + '@tavi/i18n': + specifier: ^1.5.0 + version: link:../../packages/i18n + '@tavi/util': + specifier: 1.0.0 + version: link:../../packages/util + antd: + specifier: 5.6.4 + version: 5.6.4(react-dom@18.2.0)(react@18.2.0) + axios: + specifier: 1.3.6 + version: 1.3.6 + js-cookie: + specifier: 3.0.5 + version: 3.0.5 + mitt: + specifier: 3.0.1 + version: 3.0.1 + mobx: + specifier: 6.9.0 + version: 6.9.0 + mobx-react-lite: + specifier: 3.4.3 + version: 3.4.3(mobx@6.9.0)(react-dom@18.2.0)(react@18.2.0) + react: + specifier: 18.2.0 + version: 18.2.0 + react-dom: + specifier: 18.2.0 + version: 18.2.0(react@18.2.0) + react-icons: + specifier: 4.10.1 + version: 4.10.1(react@18.2.0) + react-router: + specifier: 6.14.1 + version: 6.14.1(react@18.2.0) + react-router-dom: + specifier: 6.14.1 + version: 6.14.1(react-dom@18.2.0)(react@18.2.0) + devDependencies: + '@babel/core': + specifier: ^7.21.8 + version: 7.21.8 + '@babel/plugin-proposal-decorators': + specifier: ^7.21.0 + version: 7.21.0(@babel/core@7.21.8) + '@babel/preset-env': + specifier: ^7.21.5 + version: 7.21.5(@babel/core@7.21.8) + '@babel/preset-react': + specifier: ^7.18.6 + version: 7.18.6(@babel/core@7.21.8) + '@babel/preset-typescript': + specifier: ^7.21.5 + version: 7.21.5(@babel/core@7.21.8) + '@pmmmwh/react-refresh-webpack-plugin': + specifier: ^0.5.10 + version: 0.5.10(react-refresh@0.14.0)(webpack-dev-server@4.13.3)(webpack@5.75.0) + '@types/js-cookie': + specifier: 3.0.3 + version: 3.0.3 + '@types/node': + specifier: 18.16.3 + version: 18.16.3 + '@types/react': + specifier: ^18.0.28 + version: 18.2.14 + '@types/react-dom': + specifier: ^18.0.11 + version: 18.2.6 + '@types/react-router': + specifier: 5.1.20 + version: 5.1.20 + '@types/react-router-dom': + specifier: 5.3.3 + version: 5.3.3 + babel-loader: + specifier: ^9.1.2 + version: 9.1.2(@babel/core@7.21.8)(webpack@5.75.0) + compression-webpack-plugin: + specifier: ^10.0.0 + version: 10.0.0(webpack@5.75.0) + copy-webpack-plugin: + specifier: ^11.0.0 + version: 11.0.0(webpack@5.75.0) + core-js: + specifier: ^3.30.1 + version: 3.30.1 + cross-env: + specifier: ^6.0.0 + version: 6.0.0 + css-loader: + specifier: ^6.7.3 + version: 6.7.3(webpack@5.75.0) + css-minimizer-webpack-plugin: + specifier: ^5.0.0 + version: 5.0.0(webpack@5.75.0) + dotenv: + specifier: ^16.0.3 + version: 16.0.3 + friendly-errors-webpack-plugin: + specifier: ^1.7.0 + version: 1.7.0(webpack@5.75.0) + glob-all: + specifier: ^3.3.1 + version: 3.3.1 + html-webpack-plugin: + specifier: ^5.5.1 + version: 5.5.1(webpack@5.75.0) + less: + specifier: ^4.1.3 + version: 4.1.3 + less-loader: + specifier: ^11.1.0 + version: 11.1.0(less@4.1.3)(webpack@5.75.0) + mini-css-extract-plugin: + specifier: ^2.7.5 + version: 2.7.5(webpack@5.75.0) + prettier: + specifier: ^2.8.8 + version: 2.8.8 + purgecss-webpack-plugin: + specifier: ^5.0.0 + version: 5.0.0(webpack@5.75.0) + react-refresh: + specifier: ^0.14.0 + version: 0.14.0 + speed-measure-webpack-plugin: + specifier: ^1.5.0 + version: 1.5.0(webpack@5.75.0) + style-loader: + specifier: ^3.3.2 + version: 3.3.2(webpack@5.75.0) + terser-webpack-plugin: + specifier: ^5.3.7 + version: 5.3.7(webpack@5.75.0) + ts-node: + specifier: ^10.9.1 + version: 10.9.1(@types/node@18.16.3)(typescript@5.1.3) + typescript: + specifier: ^5.0.4 + version: 5.1.3 + webpack: + specifier: 5.75.0 + version: 5.75.0(webpack-cli@5.0.2) + webpack-bundle-analyzer: + specifier: ^4.8.0 + version: 4.8.0 + webpack-cli: + specifier: ^5.0.2 + version: 5.0.2(webpack-bundle-analyzer@4.8.0)(webpack-dev-server@4.13.3)(webpack@5.75.0) + webpack-dev-server: + specifier: ^4.13.3 + version: 4.13.3(webpack-cli@5.0.2)(webpack@5.75.0) + webpack-merge: + specifier: ^5.8.0 + version: 5.8.0 + webpackbar: + specifier: ^5.0.2 + version: 5.0.2(webpack@5.75.0) + + apps/cert: + dependencies: + '@ant-design/icons': + specifier: 5.2.5 + version: 5.2.5(react-dom@18.2.0)(react@18.2.0) + antd: + specifier: 5.8.2 + version: 5.8.2(react-dom@18.2.0)(react@18.2.0) + axios: + specifier: 1.4.0 + version: 1.4.0 + mobx: + specifier: 6.9.0 + version: 6.9.0 + mobx-react-lite: + specifier: 3.4.3 + version: 3.4.3(mobx@6.9.0)(react-dom@18.2.0)(react@18.2.0) + react: + specifier: ^18.2.0 + version: 18.2.0 + react-dom: + specifier: ^18.2.0 + version: 18.2.0(react@18.2.0) + react-icons: + specifier: 4.10.1 + version: 4.10.1(react@18.2.0) + react-router: + specifier: 6.14.2 + version: 6.14.2(react@18.2.0) + react-router-dom: + specifier: 6.14.2 + version: 6.14.2(react-dom@18.2.0)(react@18.2.0) + devDependencies: + '@types/react': + specifier: ^18.2.14 + version: 18.2.14 + '@types/react-dom': + specifier: ^18.2.6 + version: 18.2.6 + '@types/react-router': + specifier: 5.1.20 + version: 5.1.20 + '@types/react-router-dom': + specifier: 5.3.3 + version: 5.3.3 + '@typescript-eslint/eslint-plugin': + specifier: ^5.61.0 + version: 5.61.0(@typescript-eslint/parser@5.61.0)(eslint@8.44.0)(typescript@5.1.3) + '@typescript-eslint/parser': + specifier: ^5.61.0 + version: 5.61.0(eslint@8.44.0)(typescript@5.1.3) + '@vitejs/plugin-react': + specifier: ^4.0.1 + version: 4.0.1(vite@4.4.0) + eslint: + specifier: ^8.44.0 + version: 8.44.0 + eslint-plugin-react-hooks: + specifier: ^4.6.0 + version: 4.6.0(eslint@8.44.0) + eslint-plugin-react-refresh: + specifier: ^0.4.1 + version: 0.4.1(eslint@8.44.0) + typescript: + specifier: ^5.0.2 + version: 5.1.3 + vite: + specifier: ^4.4.0 + version: 4.4.0 + + apps/dmp: + dependencies: + '@ant-design/icons': + specifier: 5.2.5 + version: 5.2.5(react-dom@18.2.0)(react@18.2.0) + '@tavi/util': + specifier: workspace:* + version: link:../../packages/util + antd: + specifier: 5.8.3 + version: 5.8.3(react-dom@18.2.0)(react@18.2.0) + axios: + specifier: 1.4.0 + version: 1.4.0 + dicom-parser: + specifier: 1.8.21 + version: 1.8.21 + mobx: + specifier: 6.9.0 + version: 6.9.0 + mobx-react-lite: + specifier: 3.4.3 + version: 3.4.3(mobx@6.9.0)(react-dom@18.2.0)(react@18.2.0) + path-to-regexp: + specifier: 6.2.1 + version: 6.2.1 + react: + specifier: 18.2.0 + version: 18.2.0 + react-dom: + specifier: 18.2.0 + version: 18.2.0(react@18.2.0) + react-icons: + specifier: 4.10.1 + version: 4.10.1(react@18.2.0) + react-router: + specifier: 6.14.2 + version: 6.14.2(react@18.2.0) + react-router-dom: + specifier: 6.14.2 + version: 6.14.2(react-dom@18.2.0)(react@18.2.0) + devDependencies: + '@types/react': + specifier: 18.2.14 + version: 18.2.14 + '@types/react-dom': + specifier: 18.2.6 + version: 18.2.6 + '@types/react-router': + specifier: 5.1.20 + version: 5.1.20 + '@types/react-router-dom': + specifier: 5.3.3 + version: 5.3.3 + '@typescript-eslint/eslint-plugin': + specifier: ^5.61.0 + version: 5.61.0(@typescript-eslint/parser@5.61.0)(eslint@8.44.0)(typescript@5.1.3) + '@typescript-eslint/parser': + specifier: ^5.61.0 + version: 5.61.0(eslint@8.44.0)(typescript@5.1.3) + '@vitejs/plugin-react': + specifier: ^4.0.1 + version: 4.0.1(vite@4.4.0) + eslint: + specifier: ^8.44.0 + version: 8.44.0 + eslint-plugin-react-hooks: + specifier: ^4.6.0 + version: 4.6.0(eslint@8.44.0) + eslint-plugin-react-refresh: + specifier: ^0.4.1 + version: 0.4.1(eslint@8.44.0) + typescript: + specifier: ^5.0.2 + version: 5.1.3 + vite: + specifier: ^4.4.0 + version: 4.4.0 + + apps/services/aorta/gateway: + dependencies: + '@nestjs/common': + specifier: ^10.0.0 + version: 10.1.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/config': + specifier: 3.0.0 + version: 3.0.0(@nestjs/common@10.1.0)(reflect-metadata@0.1.13) + '@nestjs/core': + specifier: ^10.0.0 + version: 10.1.0(@nestjs/common@10.1.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@10.1.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/microservices': + specifier: 10.0.5 + version: 10.0.5(@nestjs/common@10.1.0)(@nestjs/core@10.1.0)(ioredis@5.3.2)(nats@2.15.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/platform-express': + specifier: ^10.0.0 + version: 10.1.0(@nestjs/common@10.1.0)(@nestjs/core@10.1.0) + '@tavi/oss': + specifier: workspace:* + version: link:../../../../packages/oss + '@tavi/util': + specifier: workspace:* + version: link:../../../../packages/util + cookie-parser: + specifier: 1.4.6 + version: 1.4.6 + cross-env: + specifier: 7.0.3 + version: 7.0.3 + minio: + specifier: 7.1.1 + version: 7.1.1 + nacos: + specifier: 2.5.1 + version: 2.5.1 + nats: + specifier: 2.15.1 + version: 2.15.1 + reflect-metadata: + specifier: ^0.1.13 + version: 0.1.13 + rxjs: + specifier: 7.8.1 + version: 7.8.1 + typeorm: + specifier: 0.3.16 + version: 0.3.16(ts-node@10.9.1) + devDependencies: + '@nestjs/cli': + specifier: ^10.0.0 + version: 10.0.0 + '@nestjs/schematics': + specifier: ^10.0.0 + version: 10.0.0(chokidar@3.5.3)(typescript@5.1.3) + '@nestjs/testing': + specifier: ^10.0.0 + version: 10.0.0(@nestjs/common@10.1.0)(@nestjs/core@10.1.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@10.1.0) + '@types/express': + specifier: ^4.17.17 + version: 4.17.17 + '@types/multer': + specifier: 1.4.7 + version: 1.4.7 + '@types/node': + specifier: ^20.3.1 + version: 20.3.3 + '@types/supertest': + specifier: ^2.0.12 + version: 2.0.12 + '@typescript-eslint/eslint-plugin': + specifier: ^5.59.11 + version: 5.61.0(@typescript-eslint/parser@5.61.0)(eslint@8.44.0)(typescript@5.1.3) + '@typescript-eslint/parser': + specifier: ^5.59.11 + version: 5.61.0(eslint@8.44.0)(typescript@5.1.3) + eslint: + specifier: ^8.42.0 + version: 8.44.0 + eslint-config-prettier: + specifier: ^8.8.0 + version: 8.8.0(eslint@8.44.0) + eslint-plugin-prettier: + specifier: ^4.2.1 + version: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.44.0)(prettier@2.8.8) + prettier: + specifier: ^2.8.8 + version: 2.8.8 + source-map-support: + specifier: ^0.5.21 + version: 0.5.21 + supertest: + specifier: ^6.3.3 + version: 6.3.3 + ts-loader: + specifier: ^9.4.3 + version: 9.4.3(typescript@5.1.3)(webpack@5.75.0) + ts-node: + specifier: ^10.9.1 + version: 10.9.1(@types/node@20.3.3)(typescript@5.1.3) + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 + typescript: + specifier: ^5.1.3 + version: 5.1.3 + + apps/services/aorta/report: + dependencies: + '@nestjs/axios': + specifier: 2.0.0 + version: 2.0.0(@nestjs/common@9.0.0)(axios@1.4.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/common': + specifier: ^9.0.0 + version: 9.0.0(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/config': + specifier: 2.3.2 + version: 2.3.2(@nestjs/common@9.0.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/core': + specifier: ^9.0.0 + version: 9.0.0(@nestjs/common@9.0.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@9.0.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/jwt': + specifier: 10.0.3 + version: 10.0.3(@nestjs/common@9.0.0) + '@nestjs/microservices': + specifier: 10.0.5 + version: 10.0.5(@nestjs/common@9.0.0)(@nestjs/core@9.0.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/platform-express': + specifier: ^9.0.0 + version: 9.0.0(@nestjs/common@9.0.0)(@nestjs/core@9.0.0) + '@tavi/oss': + specifier: workspace:* + version: link:../../../../packages/oss + cookie-parser: + specifier: 1.4.6 + version: 1.4.6 + cross-env: + specifier: 7.0.3 + version: 7.0.3 + js-yaml: + specifier: 4.1.0 + version: 4.1.0 + md5: + specifier: 2.3.0 + version: 2.3.0 + minio: + specifier: 7.1.1 + version: 7.1.1 + mysql2: + specifier: 3.3.3 + version: 3.3.3 + nacos: + specifier: 2.5.1 + version: 2.5.1 + reflect-metadata: + specifier: ^0.1.13 + version: 0.1.13 + rxjs: + specifier: 7.8.1 + version: 7.8.1 + typeorm: + specifier: 0.3.16 + version: 0.3.16(mysql2@3.3.3)(ts-node@10.9.1) + devDependencies: + '@nestjs/cli': + specifier: ^9.0.0 + version: 9.0.0 + '@nestjs/schematics': + specifier: ^9.0.0 + version: 9.0.0(typescript@5.1.3) + '@types/cookie-parser': + specifier: 1.4.3 + version: 1.4.3 + '@types/express': + specifier: ^4.17.13 + version: 4.17.17 + '@types/multer': + specifier: 1.4.7 + version: 1.4.7 + '@types/node': + specifier: 18.16.12 + version: 18.16.12 + '@typescript-eslint/eslint-plugin': + specifier: ^5.0.0 + version: 5.61.0(@typescript-eslint/parser@5.61.0)(eslint@8.44.0)(typescript@5.1.3) + '@typescript-eslint/parser': + specifier: ^5.0.0 + version: 5.61.0(eslint@8.44.0)(typescript@5.1.3) + eslint: + specifier: ^8.0.1 + version: 8.44.0 + eslint-config-prettier: + specifier: ^8.3.0 + version: 8.8.0(eslint@8.44.0) + eslint-plugin-prettier: + specifier: ^4.0.0 + version: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.44.0)(prettier@2.8.8) + prettier: + specifier: ^2.3.2 + version: 2.8.8 + source-map-support: + specifier: ^0.5.20 + version: 0.5.21 + ts-loader: + specifier: ^9.2.3 + version: 9.4.3(typescript@5.1.3)(webpack@5.75.0) + ts-node: + specifier: ^10.0.0 + version: 10.9.1(@types/node@18.16.12)(typescript@5.1.3) + tsconfig-paths: + specifier: 4.2.0 + version: 4.2.0 + typescript: + specifier: ^5.0.0 + version: 5.1.3 + + apps/services/cert/authenticate: + dependencies: + '@nestjs/common': + specifier: 10.1.0 + version: 10.1.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/config': + specifier: 3.0.0 + version: 3.0.0(@nestjs/common@10.1.0)(reflect-metadata@0.1.13) + '@nestjs/core': + specifier: 10.1.0 + version: 10.1.0(@nestjs/common@10.1.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@10.1.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/jwt': + specifier: 10.1.0 + version: 10.1.0(@nestjs/common@10.1.0) + '@nestjs/microservices': + specifier: 10.0.5 + version: 10.0.5(@nestjs/common@10.1.0)(@nestjs/core@10.1.0)(ioredis@5.3.2)(nats@2.15.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/passport': + specifier: 10.0.0 + version: 10.0.0(@nestjs/common@10.1.0)(passport@0.6.0) + '@nestjs/platform-express': + specifier: 10.1.0 + version: 10.1.0(@nestjs/common@10.1.0)(@nestjs/core@10.1.0) + cookie-parser: + specifier: 1.4.6 + version: 1.4.6 + cross-env: + specifier: 7.0.3 + version: 7.0.3 + ioredis: + specifier: 5.3.2 + version: 5.3.2 + nacos: + specifier: 2.5.1 + version: 2.5.1 + nats: + specifier: 2.15.1 + version: 2.15.1 + reflect-metadata: + specifier: ^0.1.13 + version: 0.1.13 + rxjs: + specifier: 7.8.1 + version: 7.8.1 + devDependencies: + '@nestjs/cli': + specifier: ^9.0.0 + version: 9.0.0 + '@nestjs/schematics': + specifier: ^9.0.0 + version: 9.0.0(typescript@5.1.3) + '@types/express': + specifier: ^4.17.13 + version: 4.17.17 + '@types/node': + specifier: 18.16.12 + version: 18.16.12 + '@typescript-eslint/eslint-plugin': + specifier: ^5.0.0 + version: 5.61.0(@typescript-eslint/parser@5.61.0)(eslint@8.44.0)(typescript@5.1.3) + '@typescript-eslint/parser': + specifier: ^5.0.0 + version: 5.61.0(eslint@8.44.0)(typescript@5.1.3) + eslint: + specifier: ^8.0.1 + version: 8.44.0 + eslint-config-prettier: + specifier: ^8.3.0 + version: 8.8.0(eslint@8.44.0) + eslint-plugin-prettier: + specifier: ^4.0.0 + version: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.44.0)(prettier@2.8.8) + prettier: + specifier: ^2.3.2 + version: 2.8.8 + source-map-support: + specifier: ^0.5.20 + version: 0.5.21 + ts-loader: + specifier: ^9.2.3 + version: 9.4.3(typescript@5.1.3)(webpack@5.75.0) + ts-node: + specifier: ^10.0.0 + version: 10.9.1(@types/node@18.16.12)(typescript@5.1.3) + tsconfig-paths: + specifier: 4.2.0 + version: 4.2.0 + typescript: + specifier: ^5.0.0 + version: 5.1.3 + + apps/services/cert/authorize: + dependencies: + '@casl/ability': + specifier: 6.5.0 + version: 6.5.0 + '@nestjs/common': + specifier: 10.1.0 + version: 10.1.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/config': + specifier: 3.0.0 + version: 3.0.0(@nestjs/common@10.1.0)(reflect-metadata@0.1.13) + '@nestjs/core': + specifier: 10.1.0 + version: 10.1.0(@nestjs/common@10.1.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@10.1.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/microservices': + specifier: 10.0.5 + version: 10.0.5(@nestjs/common@10.1.0)(@nestjs/core@10.1.0)(ioredis@5.3.2)(nats@2.15.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/platform-express': + specifier: 10.1.0 + version: 10.1.0(@nestjs/common@10.1.0)(@nestjs/core@10.1.0) + '@nestjs/typeorm': + specifier: 10.0.0 + version: 10.0.0(@nestjs/common@10.1.0)(@nestjs/core@10.1.0)(reflect-metadata@0.1.13)(rxjs@7.8.1)(typeorm@0.3.17) + bcrypt: + specifier: 5.1.0 + version: 5.1.0 + cookie-parser: + specifier: 1.4.6 + version: 1.4.6 + cross-env: + specifier: 7.0.3 + version: 7.0.3 + minimatch: + specifier: 9.0.3 + version: 9.0.3 + nacos: + specifier: 2.5.1 + version: 2.5.1 + nats: + specifier: 2.15.1 + version: 2.15.1 + reflect-metadata: + specifier: ^0.1.13 + version: 0.1.13 + rxjs: + specifier: 7.8.1 + version: 7.8.1 + typeorm: + specifier: 0.3.17 + version: 0.3.17(ts-node@10.9.1) + devDependencies: + '@nestjs/cli': + specifier: ^9.0.0 + version: 9.0.0 + '@nestjs/schematics': + specifier: ^9.0.0 + version: 9.0.0(typescript@5.1.3) + '@types/express': + specifier: ^4.17.13 + version: 4.17.17 + '@types/node': + specifier: 18.16.12 + version: 18.16.12 + '@typescript-eslint/eslint-plugin': + specifier: ^5.0.0 + version: 5.61.0(@typescript-eslint/parser@5.61.0)(eslint@8.44.0)(typescript@5.1.3) + '@typescript-eslint/parser': + specifier: ^5.0.0 + version: 5.61.0(eslint@8.44.0)(typescript@5.1.3) + eslint: + specifier: ^8.0.1 + version: 8.44.0 + eslint-config-prettier: + specifier: ^8.3.0 + version: 8.8.0(eslint@8.44.0) + eslint-plugin-prettier: + specifier: ^4.0.0 + version: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.44.0)(prettier@2.8.8) + prettier: + specifier: ^2.3.2 + version: 2.8.8 + source-map-support: + specifier: ^0.5.20 + version: 0.5.21 + ts-loader: + specifier: ^9.2.3 + version: 9.4.3(typescript@5.1.3)(webpack@5.75.0) + ts-node: + specifier: ^10.0.0 + version: 10.9.1(@types/node@18.16.12)(typescript@5.1.3) + tsconfig-paths: + specifier: 4.2.0 + version: 4.2.0 + typescript: + specifier: ^5.0.0 + version: 5.1.3 + + apps/services/cert/gateway: + dependencies: + '@nestjs/common': + specifier: ^10.0.0 + version: 10.1.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/config': + specifier: 3.0.0 + version: 3.0.0(@nestjs/common@10.1.0)(reflect-metadata@0.1.13) + '@nestjs/core': + specifier: ^10.0.0 + version: 10.1.0(@nestjs/common@10.1.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@10.1.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/microservices': + specifier: 10.0.5 + version: 10.0.5(@nestjs/common@10.1.0)(@nestjs/core@10.1.0)(ioredis@5.3.2)(nats@2.15.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/platform-express': + specifier: ^10.0.0 + version: 10.1.0(@nestjs/common@10.1.0)(@nestjs/core@10.1.0) + '@nestjs/typeorm': + specifier: 10.0.0 + version: 10.0.0(@nestjs/common@10.1.0)(@nestjs/core@10.1.0)(reflect-metadata@0.1.13)(rxjs@7.8.1)(typeorm@0.3.17) + class-transformer: + specifier: 0.5.1 + version: 0.5.1 + class-validator: + specifier: 0.14.0 + version: 0.14.0 + cookie-parser: + specifier: 1.4.6 + version: 1.4.6 + cross-env: + specifier: 7.0.3 + version: 7.0.3 + nacos: + specifier: 2.5.1 + version: 2.5.1 + nats: + specifier: 2.15.1 + version: 2.15.1 + reflect-metadata: + specifier: ^0.1.13 + version: 0.1.13 + rxjs: + specifier: 7.8.1 + version: 7.8.1 + typeorm: + specifier: 0.3.17 + version: 0.3.17(ts-node@10.9.1) + uuid: + specifier: 9.0.0 + version: 9.0.0 + devDependencies: + '@nestjs/cli': + specifier: ^10.0.0 + version: 10.0.0 + '@nestjs/schematics': + specifier: ^10.0.0 + version: 10.0.0(chokidar@3.5.3)(typescript@5.1.3) + '@nestjs/testing': + specifier: ^10.0.0 + version: 10.0.0(@nestjs/common@10.1.0)(@nestjs/core@10.1.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@10.1.0) + '@types/express': + specifier: ^4.17.17 + version: 4.17.17 + '@types/node': + specifier: ^20.3.1 + version: 20.3.3 + '@types/supertest': + specifier: ^2.0.12 + version: 2.0.12 + '@typescript-eslint/eslint-plugin': + specifier: ^5.59.11 + version: 5.61.0(@typescript-eslint/parser@5.61.0)(eslint@8.44.0)(typescript@5.1.3) + '@typescript-eslint/parser': + specifier: ^5.59.11 + version: 5.61.0(eslint@8.44.0)(typescript@5.1.3) + eslint: + specifier: ^8.42.0 + version: 8.44.0 + eslint-config-prettier: + specifier: ^8.8.0 + version: 8.8.0(eslint@8.44.0) + eslint-plugin-prettier: + specifier: ^4.2.1 + version: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.44.0)(prettier@2.8.8) + prettier: + specifier: ^2.8.8 + version: 2.8.8 + source-map-support: + specifier: ^0.5.21 + version: 0.5.21 + supertest: + specifier: ^6.3.3 + version: 6.3.3 + ts-loader: + specifier: ^9.4.3 + version: 9.4.3(typescript@5.1.3)(webpack@5.75.0) + ts-node: + specifier: ^10.9.1 + version: 10.9.1(@types/node@20.3.3)(typescript@5.1.3) + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 + typescript: + specifier: ^5.1.3 + version: 5.1.3 + + apps/services/dmp/gateway: + dependencies: + '@nestjs/common': + specifier: ^10.0.0 + version: 10.1.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/config': + specifier: 3.0.0 + version: 3.0.0(@nestjs/common@10.1.0)(reflect-metadata@0.1.13) + '@nestjs/core': + specifier: ^10.0.0 + version: 10.1.0(@nestjs/common@10.1.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@10.1.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/microservices': + specifier: 10.0.5 + version: 10.0.5(@nestjs/common@10.1.0)(@nestjs/core@10.1.0)(ioredis@5.3.2)(nats@2.15.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/platform-express': + specifier: ^10.0.0 + version: 10.1.0(@nestjs/common@10.1.0)(@nestjs/core@10.1.0) + '@nestjs/typeorm': + specifier: 10.0.0 + version: 10.0.0(@nestjs/common@10.1.0)(@nestjs/core@10.1.0)(reflect-metadata@0.1.13)(rxjs@7.8.1)(typeorm@0.3.17) + class-transformer: + specifier: 0.5.1 + version: 0.5.1 + class-validator: + specifier: 0.14.0 + version: 0.14.0 + cookie-parser: + specifier: 1.4.6 + version: 1.4.6 + cross-env: + specifier: 7.0.3 + version: 7.0.3 + dayjs: + specifier: 1.11.9 + version: 1.11.9 + nacos: + specifier: 2.5.1 + version: 2.5.1 + nats: + specifier: 2.15.1 + version: 2.15.1 + reflect-metadata: + specifier: ^0.1.13 + version: 0.1.13 + rxjs: + specifier: 7.8.1 + version: 7.8.1 + typeorm: + specifier: 0.3.17 + version: 0.3.17(ts-node@10.9.1) + uuid: + specifier: 9.0.0 + version: 9.0.0 + devDependencies: + '@nestjs/cli': + specifier: ^10.0.0 + version: 10.0.0 + '@nestjs/schematics': + specifier: ^10.0.0 + version: 10.0.0(chokidar@3.5.3)(typescript@5.1.3) + '@nestjs/testing': + specifier: ^10.0.0 + version: 10.0.0(@nestjs/common@10.1.0)(@nestjs/core@10.1.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@10.1.0) + '@types/express': + specifier: ^4.17.17 + version: 4.17.17 + '@types/node': + specifier: ^20.3.1 + version: 20.3.3 + '@types/supertest': + specifier: ^2.0.12 + version: 2.0.12 + '@typescript-eslint/eslint-plugin': + specifier: ^5.59.11 + version: 5.61.0(@typescript-eslint/parser@5.61.0)(eslint@8.44.0)(typescript@5.1.3) + '@typescript-eslint/parser': + specifier: ^5.59.11 + version: 5.61.0(eslint@8.44.0)(typescript@5.1.3) + eslint: + specifier: ^8.42.0 + version: 8.44.0 + eslint-config-prettier: + specifier: ^8.8.0 + version: 8.8.0(eslint@8.44.0) + eslint-plugin-prettier: + specifier: ^4.2.1 + version: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.44.0)(prettier@2.8.8) + prettier: + specifier: ^2.8.8 + version: 2.8.8 + source-map-support: + specifier: ^0.5.21 + version: 0.5.21 + supertest: + specifier: ^6.3.3 + version: 6.3.3 + ts-loader: + specifier: ^9.4.3 + version: 9.4.3(typescript@5.1.3)(webpack@5.75.0) + ts-node: + specifier: ^10.9.1 + version: 10.9.1(@types/node@20.3.3)(typescript@5.1.3) + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 + typescript: + specifier: ^5.1.3 + version: 5.1.3 + + apps/services/logger: + dependencies: + '@casl/ability': + specifier: 6.5.0 + version: 6.5.0 + '@nestjs/common': + specifier: 10.1.0 + version: 10.1.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/config': + specifier: 3.0.0 + version: 3.0.0(@nestjs/common@10.1.0)(reflect-metadata@0.1.13) + '@nestjs/core': + specifier: 10.1.0 + version: 10.1.0(@nestjs/common@10.1.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@10.1.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/microservices': + specifier: 10.0.5 + version: 10.0.5(@nestjs/common@10.1.0)(@nestjs/core@10.1.0)(ioredis@5.3.2)(nats@2.15.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/platform-express': + specifier: 10.1.0 + version: 10.1.0(@nestjs/common@10.1.0)(@nestjs/core@10.1.0) + '@nestjs/typeorm': + specifier: 10.0.0 + version: 10.0.0(@nestjs/common@10.1.0)(@nestjs/core@10.1.0)(reflect-metadata@0.1.13)(rxjs@7.8.1)(typeorm@0.3.17) + '@tavi/util': + specifier: workspace:* + version: link:../../../packages/util + bcrypt: + specifier: 5.1.0 + version: 5.1.0 + cookie-parser: + specifier: 1.4.6 + version: 1.4.6 + cross-env: + specifier: 7.0.3 + version: 7.0.3 + crypto-js: + specifier: 4.1.1 + version: 4.1.1 + dayjs: + specifier: 1.11.9 + version: 1.11.9 + flatted: + specifier: 3.2.7 + version: 3.2.7 + minimatch: + specifier: 9.0.3 + version: 9.0.3 + nacos: + specifier: 2.5.1 + version: 2.5.1 + nats: + specifier: 2.15.1 + version: 2.15.1 + reflect-metadata: + specifier: ^0.1.13 + version: 0.1.13 + rxjs: + specifier: 7.8.1 + version: 7.8.1 + typeorm: + specifier: 0.3.17 + version: 0.3.17(ts-node@10.9.1) + devDependencies: + '@nestjs/cli': + specifier: ^9.0.0 + version: 9.0.0 + '@nestjs/schematics': + specifier: ^9.0.0 + version: 9.0.0(typescript@5.1.3) + '@types/express': + specifier: ^4.17.13 + version: 4.17.17 + '@types/node': + specifier: 18.16.12 + version: 18.16.12 + '@typescript-eslint/eslint-plugin': + specifier: ^5.0.0 + version: 5.61.0(@typescript-eslint/parser@5.61.0)(eslint@8.44.0)(typescript@5.1.3) + '@typescript-eslint/parser': + specifier: ^5.0.0 + version: 5.61.0(eslint@8.44.0)(typescript@5.1.3) + eslint: + specifier: ^8.0.1 + version: 8.44.0 + eslint-config-prettier: + specifier: ^8.3.0 + version: 8.8.0(eslint@8.44.0) + eslint-plugin-prettier: + specifier: ^4.0.0 + version: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.44.0)(prettier@2.8.8) + prettier: + specifier: ^2.3.2 + version: 2.8.8 + source-map-support: + specifier: ^0.5.20 + version: 0.5.21 + ts-loader: + specifier: ^9.2.3 + version: 9.4.3(typescript@5.1.3)(webpack@5.75.0) + ts-node: + specifier: ^10.0.0 + version: 10.9.1(@types/node@18.16.12)(typescript@5.1.3) + tsconfig-paths: + specifier: 4.2.0 + version: 4.2.0 + typescript: + specifier: ^5.0.0 + version: 5.1.3 + + packages/hook: + dependencies: + axios: + specifier: 1.4.0 + version: 1.4.0 + react: + specifier: 18.2.0 + version: 18.2.0 + react-dom: + specifier: 18.2.0 + version: 18.2.0(react@18.2.0) + react-router-dom: + specifier: 6.11.2 + version: 6.11.2(react-dom@18.2.0)(react@18.2.0) + typescript: + specifier: ^5.0.4 + version: 5.1.3 + devDependencies: + '@rollup/plugin-commonjs': + specifier: ^24.1.0 + version: 24.1.0(rollup@3.21.5) + '@rollup/plugin-node-resolve': + specifier: ^15.0.2 + version: 15.0.2(rollup@3.21.5) + '@types/node': + specifier: 18.16.3 + version: 18.16.3 + '@types/react': + specifier: ^18.0.28 + version: 18.2.14 + '@types/react-dom': + specifier: ^18.0.11 + version: 18.2.6 + '@types/react-router-dom': + specifier: 5.3.3 + version: 5.3.3 + rollup: + specifier: ^3.21.5 + version: 3.21.5 + rollup-plugin-typescript2: + specifier: ^0.34.1 + version: 0.34.1(rollup@3.21.5)(typescript@5.1.3) + + packages/i18n: + dependencies: + i18next: + specifier: 22.5.0 + version: 22.5.0 + i18next-browser-languagedetector: + specifier: 7.0.1 + version: 7.0.1 + i18next-http-backend: + specifier: 2.2.1 + version: 2.2.1 + react: + specifier: 18.2.0 + version: 18.2.0 + react-dom: + specifier: 18.2.0 + version: 18.2.0(react@18.2.0) + react-i18next: + specifier: 12.3.1 + version: 12.3.1(i18next@22.5.0)(react-dom@18.2.0)(react@18.2.0) + react-router-dom: + specifier: 6.11.2 + version: 6.11.2(react-dom@18.2.0)(react@18.2.0) + typescript: + specifier: ^5.0.4 + version: 5.1.3 + devDependencies: + '@rollup/plugin-commonjs': + specifier: ^24.1.0 + version: 24.1.0(rollup@3.21.5) + '@rollup/plugin-node-resolve': + specifier: ^15.0.2 + version: 15.0.2(rollup@3.21.5) + '@types/node': + specifier: 18.16.3 + version: 18.16.3 + '@types/react': + specifier: ^18.0.28 + version: 18.2.14 + '@types/react-dom': + specifier: ^18.0.11 + version: 18.2.6 + '@types/react-router-dom': + specifier: 5.3.3 + version: 5.3.3 + rollup: + specifier: ^3.21.5 + version: 3.21.5 + rollup-plugin-node-polyfills: + specifier: 0.2.1 + version: 0.2.1 + rollup-plugin-terser: + specifier: 7.0.2 + version: 7.0.2(rollup@3.21.5) + rollup-plugin-typescript2: + specifier: ^0.34.1 + version: 0.34.1(rollup@3.21.5)(typescript@5.1.3) + + packages/mock: + devDependencies: + serve: + specifier: 14.2.0 + version: 14.2.0 + + packages/oss: + dependencies: + minio: + specifier: 7.1.1 + version: 7.1.1 + devDependencies: + '@rollup/plugin-commonjs': + specifier: ^24.1.0 + version: 24.1.0(rollup@3.21.5) + '@rollup/plugin-node-resolve': + specifier: ^15.0.2 + version: 15.0.2(rollup@3.21.5) + '@types/node': + specifier: 20.3.3 + version: 20.3.3 + rollup: + specifier: ^3.21.5 + version: 3.21.5 + rollup-plugin-typescript2: + specifier: ^0.34.1 + version: 0.34.1(rollup@3.21.5)(typescript@5.1.3) + tslib: + specifier: 2.6.0 + version: 2.6.0 + typescript: + specifier: ^5.0.2 + version: 5.1.3 + + packages/util: + dependencies: + '@fingerprintjs/fingerprintjs': + specifier: 4.0.1 + version: 4.0.1 + axios: + specifier: 1.4.0 + version: 1.4.0 + crypto-js: + specifier: 4.1.1 + version: 4.1.1 + flatted: + specifier: 3.2.7 + version: 3.2.7 + html2canvas: + specifier: 1.4.1 + version: 1.4.1 + jspdf: + specifier: 2.5.1 + version: 2.5.1 + react: + specifier: 18.2.0 + version: 18.2.0 + react-dom: + specifier: 18.2.0 + version: 18.2.0(react@18.2.0) + react-router-dom: + specifier: 6.11.2 + version: 6.11.2(react-dom@18.2.0)(react@18.2.0) + typescript: + specifier: ^5.0.4 + version: 5.1.3 + devDependencies: + '@rollup/plugin-commonjs': + specifier: ^24.1.0 + version: 24.1.0(rollup@3.21.5) + '@rollup/plugin-node-resolve': + specifier: ^15.0.2 + version: 15.0.2(rollup@3.21.5) + '@types/node': + specifier: 18.16.3 + version: 18.16.3 + '@types/react': + specifier: ^18.0.28 + version: 18.2.14 + '@types/react-dom': + specifier: ^18.0.11 + version: 18.2.6 + '@types/react-router-dom': + specifier: 5.3.3 + version: 5.3.3 + rollup: + specifier: ^3.21.5 + version: 3.21.5 + rollup-plugin-typescript2: + specifier: ^0.34.1 + version: 0.34.1(rollup@3.21.5)(typescript@5.1.3) + tslib: + specifier: 2.6.0 + version: 2.6.0 + +packages: + + /@aashutoshrathi/word-wrap@1.2.6: + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + engines: {node: '>=0.10.0'} + dev: true + + /@ampproject/remapping@2.2.1: + resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.18 + dev: true + + /@angular-devkit/core@14.0.5(chokidar@3.5.3): + resolution: {integrity: sha512-/CUGi6QLwh79FvsOY7M+1LQL3asZsbQW/WBd5f1iu5y7TLNqCwo+wOb0ZXLDNPw45vYBxFajtt3ob3U7qx3jNg==} + engines: {node: ^14.15.0 || >=16.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + chokidar: ^3.5.2 + peerDependenciesMeta: + chokidar: + optional: true + dependencies: + ajv: 8.11.0 + ajv-formats: 2.1.1(ajv@8.11.0) + chokidar: 3.5.3 + jsonc-parser: 3.0.0 + rxjs: 6.6.7 + source-map: 0.7.3 + dev: true + + /@angular-devkit/core@16.1.0(chokidar@3.5.3): + resolution: {integrity: sha512-mrWpuDvttmhrCGcLc68RIXKtTzUhkBTsE5ZZFZNO1+FSC+vO/ZpyCpPd6C+6coM68NfXYjHlms5XF6KbxeGn/Q==} + engines: {node: ^16.14.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + chokidar: ^3.5.2 + peerDependenciesMeta: + chokidar: + optional: true + dependencies: + ajv: 8.12.0 + ajv-formats: 2.1.1(ajv@8.12.0) + chokidar: 3.5.3 + jsonc-parser: 3.2.0 + rxjs: 7.8.1 + source-map: 0.7.4 + dev: true + + /@angular-devkit/schematics-cli@14.0.5(chokidar@3.5.3): + resolution: {integrity: sha512-S+u0KjglyI3jEZWwIuBvFjEwY3Zk5lCWfhet+95sFKJEjEYgF4Fuk8Mau/9cr55hIcpZqTQUvyxnS/VDoj4WLg==} + engines: {node: ^14.15.0 || >=16.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + hasBin: true + dependencies: + '@angular-devkit/core': 14.0.5(chokidar@3.5.3) + '@angular-devkit/schematics': 14.0.5(chokidar@3.5.3) + ansi-colors: 4.1.1 + inquirer: 8.2.4 + symbol-observable: 4.0.0 + yargs-parser: 21.0.1 + transitivePeerDependencies: + - chokidar + dev: true + + /@angular-devkit/schematics-cli@16.1.0(chokidar@3.5.3): + resolution: {integrity: sha512-siBpRDmMMV7NB+NvaDHeJ4doHoSkFwIywwFj8GXnBCtobyxrBl1EyG1cKK+FHRydYtyYIk8FEoOpJA9oE9S2hg==} + engines: {node: ^16.14.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + hasBin: true + dependencies: + '@angular-devkit/core': 16.1.0(chokidar@3.5.3) + '@angular-devkit/schematics': 16.1.0(chokidar@3.5.3) + ansi-colors: 4.1.3 + inquirer: 8.2.4 + symbol-observable: 4.0.0 + yargs-parser: 21.1.1 + transitivePeerDependencies: + - chokidar + dev: true + + /@angular-devkit/schematics@14.0.5(chokidar@3.5.3): + resolution: {integrity: sha512-sufxITBkn2MvgEREt9JQ3QCKHS+sue1WsVzLE+TWqG5MC/RPk0f9tQ5VoHk6ZTzDKUvOtSoc7G+n0RscQsyp5g==} + engines: {node: ^14.15.0 || >=16.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + dependencies: + '@angular-devkit/core': 14.0.5(chokidar@3.5.3) + jsonc-parser: 3.0.0 + magic-string: 0.26.1 + ora: 5.4.1 + rxjs: 6.6.7 + transitivePeerDependencies: + - chokidar + dev: true + + /@angular-devkit/schematics@16.1.0(chokidar@3.5.3): + resolution: {integrity: sha512-LM35PH9DT3eQRSZgrkk2bx1ZQjjVh8BCByTlr37/c+FnF9mNbeBsa1YkxrlsN/CwO+045OwEwRHnkM9Zcx0U/A==} + engines: {node: ^16.14.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + dependencies: + '@angular-devkit/core': 16.1.0(chokidar@3.5.3) + jsonc-parser: 3.2.0 + magic-string: 0.30.0 + ora: 5.4.1 + rxjs: 7.8.1 + transitivePeerDependencies: + - chokidar + dev: true + + /@ant-design/colors@7.0.0: + resolution: {integrity: sha512-iVm/9PfGCbC0dSMBrz7oiEXZaaGH7ceU40OJEfKmyuzR9R5CRimJYPlRiFtMQGQcbNMea/ePcoIebi4ASGYXtg==} + dependencies: + '@ctrl/tinycolor': 3.6.0 + dev: false + + /@ant-design/cssinjs@1.16.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-KKVB5Or6BDC1Bo3Y4KMlOkyQU0P+6GTodubrQ9YfrtXG1TgO4wpaEfg9I4ZA49R7M+Ij2KKNwb+5abvmXy6K8w==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + '@babel/runtime': 7.22.6 + '@emotion/hash': 0.8.0 + '@emotion/unitless': 0.7.5 + classnames: 2.3.2 + csstype: 3.1.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + stylis: 4.3.0 + dev: false + + /@ant-design/icons-svg@4.3.0: + resolution: {integrity: sha512-WOgvdH/1Wl8Z7VXigRbCa5djO14zxrNTzvrAQzhWiBQtEKT0uTc8K1ltjKZ8U1gPn/wXhMA8/jE39SJl0WNxSg==} + dev: false + + /@ant-design/icons@5.2.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-9Jc59v5fl5dzmxqLWtRev3dJwU7Ya9ZheoI6XmZjZiQ7PRtk77rC+Rbt7GJzAPPg43RQ4YO53RE1u8n+Et97vQ==} + engines: {node: '>=8'} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + '@ant-design/colors': 7.0.0 + '@ant-design/icons-svg': 4.3.0 + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + lodash.camelcase: 4.3.0 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@ant-design/react-slick@1.0.2(react@18.2.0): + resolution: {integrity: sha512-Wj8onxL/T8KQLFFiCA4t8eIRGpRR+UPgOdac2sYzonv+i0n3kXHmvHLLiOYL655DQx2Umii9Y9nNgL7ssu5haQ==} + peerDependencies: + react: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + json2mq: 0.2.0 + react: 18.2.0 + resize-observer-polyfill: 1.5.1 + throttle-debounce: 5.0.0 + dev: false + + /@babel/code-frame@7.22.5: + resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.22.5 + dev: true + + /@babel/compat-data@7.22.9: + resolution: {integrity: sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core@7.21.8: + resolution: {integrity: sha512-YeM22Sondbo523Sz0+CirSPnbj9bG3P0CdHcBZdqUuaeOaYEFbOLoGU7lebvGP6P5J/WE9wOn7u7C4J9HvS1xQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.22.5 + '@babel/generator': 7.22.9 + '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.21.8) + '@babel/helper-module-transforms': 7.22.9(@babel/core@7.21.8) + '@babel/helpers': 7.22.6 + '@babel/parser': 7.22.7 + '@babel/template': 7.22.5 + '@babel/traverse': 7.22.8 + '@babel/types': 7.22.5 + convert-source-map: 1.9.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/core@7.22.9: + resolution: {integrity: sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.22.5 + '@babel/generator': 7.22.9 + '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.22.9) + '@babel/helper-module-transforms': 7.22.9(@babel/core@7.22.9) + '@babel/helpers': 7.22.6 + '@babel/parser': 7.22.7 + '@babel/template': 7.22.5 + '@babel/traverse': 7.22.8 + '@babel/types': 7.22.5 + convert-source-map: 1.9.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/generator@7.22.9: + resolution: {integrity: sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.5 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.18 + jsesc: 2.5.2 + dev: true + + /@babel/helper-annotate-as-pure@7.22.5: + resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.5 + dev: true + + /@babel/helper-builder-binary-assignment-operator-visitor@7.22.5: + resolution: {integrity: sha512-m1EP3lVOPptR+2DwD125gziZNcmoNSHGmJROKoy87loWUQyJaVXDgpmruWqDARZSmtYQ+Dl25okU8+qhVzuykw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.5 + dev: true + + /@babel/helper-compilation-targets@7.22.9(@babel/core@7.21.8): + resolution: {integrity: sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': 7.22.9 + '@babel/core': 7.21.8 + '@babel/helper-validator-option': 7.22.5 + browserslist: 4.21.10 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: true + + /@babel/helper-compilation-targets@7.22.9(@babel/core@7.22.9): + resolution: {integrity: sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': 7.22.9 + '@babel/core': 7.22.9 + '@babel/helper-validator-option': 7.22.5 + browserslist: 4.21.10 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: true + + /@babel/helper-create-class-features-plugin@7.22.9(@babel/core@7.21.8): + resolution: {integrity: sha512-Pwyi89uO4YrGKxL/eNJ8lfEH55DnRloGPOseaA8NFNL6jAUnn+KccaISiFazCj5IolPPDjGSdzQzXVzODVRqUQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-function-name': 7.22.5 + '@babel/helper-member-expression-to-functions': 7.22.5 + '@babel/helper-optimise-call-expression': 7.22.5 + '@babel/helper-replace-supers': 7.22.9(@babel/core@7.21.8) + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + semver: 6.3.1 + dev: true + + /@babel/helper-create-regexp-features-plugin@7.22.9(@babel/core@7.21.8): + resolution: {integrity: sha512-+svjVa/tFwsNSG4NEy1h85+HQ5imbT92Q5/bgtS7P0GTQlP8WuFdqsiABmQouhiFGyV66oGxZFpeYHza1rNsKw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-annotate-as-pure': 7.22.5 + regexpu-core: 5.3.2 + semver: 6.3.1 + dev: true + + /@babel/helper-define-polyfill-provider@0.3.3(@babel/core@7.21.8): + resolution: {integrity: sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==} + peerDependencies: + '@babel/core': ^7.4.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.21.8) + '@babel/helper-plugin-utils': 7.22.5 + debug: 4.3.4 + lodash.debounce: 4.0.8 + resolve: 1.22.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-environment-visitor@7.22.5: + resolution: {integrity: sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-function-name@7.22.5: + resolution: {integrity: sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.5 + '@babel/types': 7.22.5 + dev: true + + /@babel/helper-hoist-variables@7.22.5: + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.5 + dev: true + + /@babel/helper-member-expression-to-functions@7.22.5: + resolution: {integrity: sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.5 + dev: true + + /@babel/helper-module-imports@7.22.5: + resolution: {integrity: sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.5 + dev: true + + /@babel/helper-module-transforms@7.22.9(@babel/core@7.21.8): + resolution: {integrity: sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-module-imports': 7.22.5 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.5 + dev: true + + /@babel/helper-module-transforms@7.22.9(@babel/core@7.22.9): + resolution: {integrity: sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-module-imports': 7.22.5 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.5 + dev: true + + /@babel/helper-optimise-call-expression@7.22.5: + resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.5 + dev: true + + /@babel/helper-plugin-utils@7.22.5: + resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-remap-async-to-generator@7.22.9(@babel/core@7.21.8): + resolution: {integrity: sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-wrap-function': 7.22.9 + dev: true + + /@babel/helper-replace-supers@7.22.9(@babel/core@7.21.8): + resolution: {integrity: sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-member-expression-to-functions': 7.22.5 + '@babel/helper-optimise-call-expression': 7.22.5 + dev: true + + /@babel/helper-simple-access@7.22.5: + resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.5 + dev: true + + /@babel/helper-skip-transparent-expression-wrappers@7.22.5: + resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.5 + dev: true + + /@babel/helper-split-export-declaration@7.22.6: + resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.5 + dev: true + + /@babel/helper-string-parser@7.22.5: + resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-identifier@7.22.5: + resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-option@7.22.5: + resolution: {integrity: sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-wrap-function@7.22.9: + resolution: {integrity: sha512-sZ+QzfauuUEfxSEjKFmi3qDSHgLsTPK/pEpoD/qonZKOtTPTLbf59oabPQ4rKekt9lFcj/hTZaOhWwFYrgjk+Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-function-name': 7.22.5 + '@babel/template': 7.22.5 + '@babel/types': 7.22.5 + dev: true + + /@babel/helpers@7.22.6: + resolution: {integrity: sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.5 + '@babel/traverse': 7.22.8 + '@babel/types': 7.22.5 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/highlight@7.22.5: + resolution: {integrity: sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.5 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@babel/parser@7.22.7: + resolution: {integrity: sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.22.5 + dev: true + + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-31Bb65aZaUwqCbWMnZPduIZxCBngHFlzyN6Dq6KAJjtx+lx6ohKHubc61OomYi7XwVD4Ol0XCVz4h+pYFR048g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/plugin-transform-optional-chaining': 7.22.6(@babel/core@7.21.8) + dev: true + + /@babel/plugin-proposal-async-generator-functions@7.20.7(@babel/core@7.21.8): + resolution: {integrity: sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-remap-async-to-generator': 7.22.9(@babel/core@7.21.8) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.21.8) + dev: true + + /@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.21.8): + resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-create-class-features-plugin': 7.22.9(@babel/core@7.21.8) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-proposal-class-static-block@7.21.0(@babel/core@7.21.8): + resolution: {integrity: sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-create-class-features-plugin': 7.22.9(@babel/core@7.21.8) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.21.8) + dev: true + + /@babel/plugin-proposal-decorators@7.21.0(@babel/core@7.21.8): + resolution: {integrity: sha512-MfgX49uRrFUTL/HvWtmx3zmpyzMMr4MTj3d527MLlr/4RTT9G/ytFFP7qet2uM2Ve03b+BkpWUpK+lRXnQ+v9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-create-class-features-plugin': 7.22.9(@babel/core@7.21.8) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-replace-supers': 7.22.9(@babel/core@7.21.8) + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/plugin-syntax-decorators': 7.22.5(@babel/core@7.21.8) + dev: true + + /@babel/plugin-proposal-dynamic-import@7.18.6(@babel/core@7.21.8): + resolution: {integrity: sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.21.8) + dev: true + + /@babel/plugin-proposal-export-namespace-from@7.18.9(@babel/core@7.21.8): + resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.21.8) + dev: true + + /@babel/plugin-proposal-json-strings@7.18.6(@babel/core@7.21.8): + resolution: {integrity: sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.21.8) + dev: true + + /@babel/plugin-proposal-logical-assignment-operators@7.20.7(@babel/core@7.21.8): + resolution: {integrity: sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.21.8) + dev: true + + /@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.21.8): + resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.21.8) + dev: true + + /@babel/plugin-proposal-numeric-separator@7.18.6(@babel/core@7.21.8): + resolution: {integrity: sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.21.8) + dev: true + + /@babel/plugin-proposal-object-rest-spread@7.20.7(@babel/core@7.21.8): + resolution: {integrity: sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.22.9 + '@babel/core': 7.21.8 + '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.21.8) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.21.8) + '@babel/plugin-transform-parameters': 7.22.5(@babel/core@7.21.8) + dev: true + + /@babel/plugin-proposal-optional-catch-binding@7.18.6(@babel/core@7.21.8): + resolution: {integrity: sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.21.8) + dev: true + + /@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.21.8): + resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.8) + dev: true + + /@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.21.8): + resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-create-class-features-plugin': 7.22.9(@babel/core@7.21.8) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-proposal-private-property-in-object@7.21.11(@babel/core@7.21.8): + resolution: {integrity: sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-create-class-features-plugin': 7.22.9(@babel/core@7.21.8) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.21.8) + dev: true + + /@babel/plugin-proposal-unicode-property-regex@7.18.6(@babel/core@7.21.8): + resolution: {integrity: sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==} + engines: {node: '>=4'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-create-regexp-features-plugin': 7.22.9(@babel/core@7.21.8) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.21.8): + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.21.8): + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.21.8): + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-decorators@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-avpUOBS7IU6al8MmF1XpAyj9QYeLPuSDJI5D4pVMSMdL7xQokKqJPYQC67RCT0aCTashUXPiGwMJ0DEXXCEmMA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.21.8): + resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.21.8): + resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-import-assertions@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.21.8): + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.21.8): + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.21.8): + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.21.8): + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.21.8): + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.21.8): + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.21.8): + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.21.8): + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.21.8): + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.21.8): + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-typescript@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-arrow-functions@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-async-to-generator@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-module-imports': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-remap-async-to-generator': 7.22.9(@babel/core@7.21.8) + dev: true + + /@babel/plugin-transform-block-scoped-functions@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-block-scoping@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-EcACl1i5fSQ6bt+YGuU/XGCeZKStLmyVGytWkpyhCLeQVA0eu6Wtiw92V+I1T/hnezUv7j74dA/Ro69gWcU+hg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-classes@7.22.6(@babel/core@7.21.8): + resolution: {integrity: sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.21.8) + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-function-name': 7.22.5 + '@babel/helper-optimise-call-expression': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-replace-supers': 7.22.9(@babel/core@7.21.8) + '@babel/helper-split-export-declaration': 7.22.6 + globals: 11.12.0 + dev: true + + /@babel/plugin-transform-computed-properties@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/template': 7.22.5 + dev: true + + /@babel/plugin-transform-destructuring@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-GfqcFuGW8vnEqTUBM7UtPd5A4q797LTvvwKxXTgRsFjoqaJiEg9deBG6kWeQYkVEL569NpnmpC0Pkr/8BLKGnQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-dotall-regex@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-create-regexp-features-plugin': 7.22.9(@babel/core@7.21.8) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-duplicate-keys@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-exponentiation-operator@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-for-of@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-function-name@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.21.8) + '@babel/helper-function-name': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-literals@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-member-expression-literals@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-modules-amd@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-module-transforms': 7.22.9(@babel/core@7.21.8) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-modules-commonjs@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-module-transforms': 7.22.9(@babel/core@7.21.8) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-simple-access': 7.22.5 + dev: true + + /@babel/plugin-transform-modules-systemjs@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-emtEpoaTMsOs6Tzz+nbmcePl6AKVtS1yC4YNAeMun9U8YCsgadPNxnOPQ8GhHFB2qdx+LZu9LgoC0Lthuu05DQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-module-transforms': 7.22.9(@babel/core@7.21.8) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-validator-identifier': 7.22.5 + dev: true + + /@babel/plugin-transform-modules-umd@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-module-transforms': 7.22.9(@babel/core@7.21.8) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-create-regexp-features-plugin': 7.22.9(@babel/core@7.21.8) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-new-target@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-object-super@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-replace-supers': 7.22.9(@babel/core@7.21.8) + dev: true + + /@babel/plugin-transform-optional-chaining@7.22.6(@babel/core@7.21.8): + resolution: {integrity: sha512-Vd5HiWml0mDVtcLHIoEU5sw6HOUW/Zk0acLs/SAeuLzkGNOPc9DB4nkUajemhCmTIz3eiaKREZn2hQQqF79YTg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.8) + dev: true + + /@babel/plugin-transform-parameters@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-property-literals@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-react-display-name@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-react-jsx-development@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/plugin-transform-react-jsx': 7.22.5(@babel/core@7.21.8) + dev: true + + /@babel/plugin-transform-react-jsx-self@7.22.5(@babel/core@7.22.9): + resolution: {integrity: sha512-nTh2ogNUtxbiSbxaT4Ds6aXnXEipHweN9YRgOX/oNXdf0cCrGn/+2LozFa3lnPV5D90MkjhgckCPBrsoSc1a7g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-react-jsx-source@7.22.5(@babel/core@7.22.9): + resolution: {integrity: sha512-yIiRO6yobeEIaI0RTbIr8iAK9FcBHLtZq0S89ZPjDLQXBA4xvghaKqI0etp/tF3htTM0sazJKKLz9oEiGRtu7w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-react-jsx@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-module-imports': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.21.8) + '@babel/types': 7.22.5 + dev: true + + /@babel/plugin-transform-react-pure-annotations@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-regenerator@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-rR7KePOE7gfEtNTh9Qw+iO3Q/e4DEsoQ+hdvM6QUDH7JRJ5qxq5AA52ZzBWbI5i9lfNuvySgOGP8ZN7LAmaiPw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + regenerator-transform: 0.15.1 + dev: true + + /@babel/plugin-transform-reserved-words@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-shorthand-properties@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-spread@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + dev: true + + /@babel/plugin-transform-sticky-regex@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-template-literals@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-typeof-symbol@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-typescript@7.22.9(@babel/core@7.21.8): + resolution: {integrity: sha512-BnVR1CpKiuD0iobHPaM1iLvcwPYN2uVFAqoLVSpEDKWuOikoCv5HbKLxclhKYUXlWkX86DoZGtqI4XhbOsyrMg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-create-class-features-plugin': 7.22.9(@babel/core@7.21.8) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.21.8) + dev: true + + /@babel/plugin-transform-unicode-escapes@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-biEmVg1IYB/raUO5wT1tgfacCef15Fbzhkx493D3urBI++6hpJ+RFG4SrWMn0NEZLfvilqKf3QDrRVZHo08FYg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-unicode-regex@7.22.5(@babel/core@7.21.8): + resolution: {integrity: sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-create-regexp-features-plugin': 7.22.9(@babel/core@7.21.8) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/preset-env@7.21.5(@babel/core@7.21.8): + resolution: {integrity: sha512-wH00QnTTldTbf/IefEVyChtRdw5RJvODT/Vb4Vcxq1AZvtXj6T0YeX0cAcXhI6/BdGuiP3GcNIL4OQbI2DVNxg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.22.9 + '@babel/core': 7.21.8 + '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.21.8) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-validator-option': 7.22.5 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-proposal-async-generator-functions': 7.20.7(@babel/core@7.21.8) + '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.21.8) + '@babel/plugin-proposal-class-static-block': 7.21.0(@babel/core@7.21.8) + '@babel/plugin-proposal-dynamic-import': 7.18.6(@babel/core@7.21.8) + '@babel/plugin-proposal-export-namespace-from': 7.18.9(@babel/core@7.21.8) + '@babel/plugin-proposal-json-strings': 7.18.6(@babel/core@7.21.8) + '@babel/plugin-proposal-logical-assignment-operators': 7.20.7(@babel/core@7.21.8) + '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.21.8) + '@babel/plugin-proposal-numeric-separator': 7.18.6(@babel/core@7.21.8) + '@babel/plugin-proposal-object-rest-spread': 7.20.7(@babel/core@7.21.8) + '@babel/plugin-proposal-optional-catch-binding': 7.18.6(@babel/core@7.21.8) + '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.21.8) + '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.21.8) + '@babel/plugin-proposal-private-property-in-object': 7.21.11(@babel/core@7.21.8) + '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.21.8) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.21.8) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.21.8) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.21.8) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.21.8) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.21.8) + '@babel/plugin-syntax-import-assertions': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.21.8) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.21.8) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.21.8) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.21.8) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.21.8) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.21.8) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.21.8) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.8) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.21.8) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.21.8) + '@babel/plugin-transform-arrow-functions': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-async-to-generator': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-block-scoped-functions': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-block-scoping': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-classes': 7.22.6(@babel/core@7.21.8) + '@babel/plugin-transform-computed-properties': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-destructuring': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-dotall-regex': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-duplicate-keys': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-exponentiation-operator': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-for-of': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-function-name': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-literals': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-member-expression-literals': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-modules-amd': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-modules-commonjs': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-modules-systemjs': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-modules-umd': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-new-target': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-object-super': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-parameters': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-property-literals': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-regenerator': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-reserved-words': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-shorthand-properties': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-spread': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-sticky-regex': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-template-literals': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-typeof-symbol': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-unicode-escapes': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-unicode-regex': 7.22.5(@babel/core@7.21.8) + '@babel/preset-modules': 0.1.6(@babel/core@7.21.8) + '@babel/types': 7.22.5 + babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.21.8) + babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.21.8) + babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.21.8) + core-js-compat: 3.32.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/preset-modules@0.1.6(@babel/core@7.21.8): + resolution: {integrity: sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg==} + peerDependencies: + '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.21.8) + '@babel/plugin-transform-dotall-regex': 7.22.5(@babel/core@7.21.8) + '@babel/types': 7.22.5 + esutils: 2.0.3 + dev: true + + /@babel/preset-react@7.18.6(@babel/core@7.21.8): + resolution: {integrity: sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-validator-option': 7.22.5 + '@babel/plugin-transform-react-display-name': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-react-jsx': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-react-jsx-development': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-react-pure-annotations': 7.22.5(@babel/core@7.21.8) + dev: true + + /@babel/preset-typescript@7.21.5(@babel/core@7.21.8): + resolution: {integrity: sha512-iqe3sETat5EOrORXiQ6rWfoOg2y68Cs75B9wNxdPW4kixJxh7aXQE1KPdWLDniC24T/6dSnguF33W9j/ZZQcmA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-validator-option': 7.22.5 + '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-modules-commonjs': 7.22.5(@babel/core@7.21.8) + '@babel/plugin-transform-typescript': 7.22.9(@babel/core@7.21.8) + dev: true + + /@babel/regjsgen@0.8.0: + resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} + dev: true + + /@babel/runtime@7.22.6: + resolution: {integrity: sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.11 + + /@babel/template@7.22.5: + resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.22.5 + '@babel/parser': 7.22.7 + '@babel/types': 7.22.5 + dev: true + + /@babel/traverse@7.22.8: + resolution: {integrity: sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.22.5 + '@babel/generator': 7.22.9 + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-function-name': 7.22.5 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/parser': 7.22.7 + '@babel/types': 7.22.5 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types@7.22.5: + resolution: {integrity: sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.22.5 + '@babel/helper-validator-identifier': 7.22.5 + to-fast-properties: 2.0.0 + dev: true + + /@casl/ability@6.5.0: + resolution: {integrity: sha512-3guc94ugr5ylZQIpJTLz0CDfwNi0mxKVECj1vJUPAvs+Lwunh/dcuUjwzc4MHM9D8JOYX0XUZMEPedpB3vIbOw==} + dependencies: + '@ucast/mongo2js': 1.3.4 + dev: false + + /@changesets/apply-release-plan@6.1.4: + resolution: {integrity: sha512-FMpKF1fRlJyCZVYHr3CbinpZZ+6MwvOtWUuO8uo+svcATEoc1zRDcj23pAurJ2TZ/uVz1wFHH6K3NlACy0PLew==} + dependencies: + '@babel/runtime': 7.22.6 + '@changesets/config': 2.3.1 + '@changesets/get-version-range-type': 0.3.2 + '@changesets/git': 2.0.0 + '@changesets/types': 5.2.1 + '@manypkg/get-packages': 1.1.3 + detect-indent: 6.1.0 + fs-extra: 7.0.1 + lodash.startcase: 4.4.0 + outdent: 0.5.0 + prettier: 2.8.8 + resolve-from: 5.0.0 + semver: 7.5.4 + dev: true + + /@changesets/assemble-release-plan@5.2.4: + resolution: {integrity: sha512-xJkWX+1/CUaOUWTguXEbCDTyWJFECEhmdtbkjhn5GVBGxdP/JwaHBIU9sW3FR6gD07UwZ7ovpiPclQZs+j+mvg==} + dependencies: + '@babel/runtime': 7.22.6 + '@changesets/errors': 0.1.4 + '@changesets/get-dependents-graph': 1.3.6 + '@changesets/types': 5.2.1 + '@manypkg/get-packages': 1.1.3 + semver: 7.5.4 + dev: true + + /@changesets/changelog-git@0.1.14: + resolution: {integrity: sha512-+vRfnKtXVWsDDxGctOfzJsPhaCdXRYoe+KyWYoq5X/GqoISREiat0l3L8B0a453B2B4dfHGcZaGyowHbp9BSaA==} + dependencies: + '@changesets/types': 5.2.1 + dev: true + + /@changesets/cli@2.26.2: + resolution: {integrity: sha512-dnWrJTmRR8bCHikJHl9b9HW3gXACCehz4OasrXpMp7sx97ECuBGGNjJhjPhdZNCvMy9mn4BWdplI323IbqsRig==} + hasBin: true + dependencies: + '@babel/runtime': 7.22.6 + '@changesets/apply-release-plan': 6.1.4 + '@changesets/assemble-release-plan': 5.2.4 + '@changesets/changelog-git': 0.1.14 + '@changesets/config': 2.3.1 + '@changesets/errors': 0.1.4 + '@changesets/get-dependents-graph': 1.3.6 + '@changesets/get-release-plan': 3.0.17 + '@changesets/git': 2.0.0 + '@changesets/logger': 0.0.5 + '@changesets/pre': 1.0.14 + '@changesets/read': 0.5.9 + '@changesets/types': 5.2.1 + '@changesets/write': 0.2.3 + '@manypkg/get-packages': 1.1.3 + '@types/is-ci': 3.0.0 + '@types/semver': 7.5.0 + ansi-colors: 4.1.3 + chalk: 2.4.2 + enquirer: 2.4.1 + external-editor: 3.1.0 + fs-extra: 7.0.1 + human-id: 1.0.2 + is-ci: 3.0.1 + meow: 6.1.1 + outdent: 0.5.0 + p-limit: 2.3.0 + preferred-pm: 3.0.3 + resolve-from: 5.0.0 + semver: 7.5.4 + spawndamnit: 2.0.0 + term-size: 2.2.1 + tty-table: 4.2.1 + dev: true + + /@changesets/config@2.3.1: + resolution: {integrity: sha512-PQXaJl82CfIXddUOppj4zWu+987GCw2M+eQcOepxN5s+kvnsZOwjEJO3DH9eVy+OP6Pg/KFEWdsECFEYTtbg6w==} + dependencies: + '@changesets/errors': 0.1.4 + '@changesets/get-dependents-graph': 1.3.6 + '@changesets/logger': 0.0.5 + '@changesets/types': 5.2.1 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + micromatch: 4.0.5 + dev: true + + /@changesets/errors@0.1.4: + resolution: {integrity: sha512-HAcqPF7snsUJ/QzkWoKfRfXushHTu+K5KZLJWPb34s4eCZShIf8BFO3fwq6KU8+G7L5KdtN2BzQAXOSXEyiY9Q==} + dependencies: + extendable-error: 0.1.7 + dev: true + + /@changesets/get-dependents-graph@1.3.6: + resolution: {integrity: sha512-Q/sLgBANmkvUm09GgRsAvEtY3p1/5OCzgBE5vX3vgb5CvW0j7CEljocx5oPXeQSNph6FXulJlXV3Re/v3K3P3Q==} + dependencies: + '@changesets/types': 5.2.1 + '@manypkg/get-packages': 1.1.3 + chalk: 2.4.2 + fs-extra: 7.0.1 + semver: 7.5.4 + dev: true + + /@changesets/get-release-plan@3.0.17: + resolution: {integrity: sha512-6IwKTubNEgoOZwDontYc2x2cWXfr6IKxP3IhKeK+WjyD6y3M4Gl/jdQvBw+m/5zWILSOCAaGLu2ZF6Q+WiPniw==} + dependencies: + '@babel/runtime': 7.22.6 + '@changesets/assemble-release-plan': 5.2.4 + '@changesets/config': 2.3.1 + '@changesets/pre': 1.0.14 + '@changesets/read': 0.5.9 + '@changesets/types': 5.2.1 + '@manypkg/get-packages': 1.1.3 + dev: true + + /@changesets/get-version-range-type@0.3.2: + resolution: {integrity: sha512-SVqwYs5pULYjYT4op21F2pVbcrca4qA/bAA3FmFXKMN7Y+HcO8sbZUTx3TAy2VXulP2FACd1aC7f2nTuqSPbqg==} + dev: true + + /@changesets/git@2.0.0: + resolution: {integrity: sha512-enUVEWbiqUTxqSnmesyJGWfzd51PY4H7mH9yUw0hPVpZBJ6tQZFMU3F3mT/t9OJ/GjyiM4770i+sehAn6ymx6A==} + dependencies: + '@babel/runtime': 7.22.6 + '@changesets/errors': 0.1.4 + '@changesets/types': 5.2.1 + '@manypkg/get-packages': 1.1.3 + is-subdir: 1.2.0 + micromatch: 4.0.5 + spawndamnit: 2.0.0 + dev: true + + /@changesets/logger@0.0.5: + resolution: {integrity: sha512-gJyZHomu8nASHpaANzc6bkQMO9gU/ib20lqew1rVx753FOxffnCrJlGIeQVxNWCqM+o6OOleCo/ivL8UAO5iFw==} + dependencies: + chalk: 2.4.2 + dev: true + + /@changesets/parse@0.3.16: + resolution: {integrity: sha512-127JKNd167ayAuBjUggZBkmDS5fIKsthnr9jr6bdnuUljroiERW7FBTDNnNVyJ4l69PzR57pk6mXQdtJyBCJKg==} + dependencies: + '@changesets/types': 5.2.1 + js-yaml: 3.14.1 + dev: true + + /@changesets/pre@1.0.14: + resolution: {integrity: sha512-dTsHmxQWEQekHYHbg+M1mDVYFvegDh9j/kySNuDKdylwfMEevTeDouR7IfHNyVodxZXu17sXoJuf2D0vi55FHQ==} + dependencies: + '@babel/runtime': 7.22.6 + '@changesets/errors': 0.1.4 + '@changesets/types': 5.2.1 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + dev: true + + /@changesets/read@0.5.9: + resolution: {integrity: sha512-T8BJ6JS6j1gfO1HFq50kU3qawYxa4NTbI/ASNVVCBTsKquy2HYwM9r7ZnzkiMe8IEObAJtUVGSrePCOxAK2haQ==} + dependencies: + '@babel/runtime': 7.22.6 + '@changesets/git': 2.0.0 + '@changesets/logger': 0.0.5 + '@changesets/parse': 0.3.16 + '@changesets/types': 5.2.1 + chalk: 2.4.2 + fs-extra: 7.0.1 + p-filter: 2.1.0 + dev: true + + /@changesets/types@4.1.0: + resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} + dev: true + + /@changesets/types@5.2.1: + resolution: {integrity: sha512-myLfHbVOqaq9UtUKqR/nZA/OY7xFjQMdfgfqeZIBK4d0hA6pgxArvdv8M+6NUzzBsjWLOtvApv8YHr4qM+Kpfg==} + dev: true + + /@changesets/write@0.2.3: + resolution: {integrity: sha512-Dbamr7AIMvslKnNYsLFafaVORx4H0pvCA2MHqgtNCySMe1blImEyAEOzDmcgKAkgz4+uwoLz7demIrX+JBr/Xw==} + dependencies: + '@babel/runtime': 7.22.6 + '@changesets/types': 5.2.1 + fs-extra: 7.0.1 + human-id: 1.0.2 + prettier: 2.8.8 + dev: true + + /@colors/colors@1.5.0: + resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} + engines: {node: '>=0.1.90'} + requiresBuild: true + dev: true + optional: true + + /@cspotcode/source-map-support@0.8.1: + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + /@ctrl/tinycolor@3.6.0: + resolution: {integrity: sha512-/Z3l6pXthq0JvMYdUFyX9j0MaCltlIn6mfh9jLyQwg5aPKxkyNa0PTHtU1AlFXLNk55ZuAeJRcpvq+tmLfKmaQ==} + engines: {node: '>=10'} + dev: false + + /@discoveryjs/json-ext@0.5.7: + resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} + engines: {node: '>=10.0.0'} + dev: true + + /@emotion/hash@0.8.0: + resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==} + dev: false + + /@emotion/unitless@0.7.5: + resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} + dev: false + + /@esbuild/android-arm64@0.18.17: + resolution: {integrity: sha512-9np+YYdNDed5+Jgr1TdWBsozZ85U1Oa3xW0c7TWqH0y2aGghXtZsuT8nYRbzOMcl0bXZXjOGbksoTtVOlWrRZg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.18.17: + resolution: {integrity: sha512-wHsmJG/dnL3OkpAcwbgoBTTMHVi4Uyou3F5mf58ZtmUyIKfcdA7TROav/6tCzET4A3QW2Q2FC+eFneMU+iyOxg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.18.17: + resolution: {integrity: sha512-O+FeWB/+xya0aLg23hHEM2E3hbfwZzjqumKMSIqcHbNvDa+dza2D0yLuymRBQQnC34CWrsJUXyH2MG5VnLd6uw==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.18.17: + resolution: {integrity: sha512-M9uJ9VSB1oli2BE/dJs3zVr9kcCBBsE883prage1NWz6pBS++1oNn/7soPNS3+1DGj0FrkSvnED4Bmlu1VAE9g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.18.17: + resolution: {integrity: sha512-XDre+J5YeIJDMfp3n0279DFNrGCXlxOuGsWIkRb1NThMZ0BsrWXoTg23Jer7fEXQ9Ye5QjrvXpxnhzl3bHtk0g==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.18.17: + resolution: {integrity: sha512-cjTzGa3QlNfERa0+ptykyxs5A6FEUQQF0MuilYXYBGdBxD3vxJcKnzDlhDCa1VAJCmAxed6mYhA2KaJIbtiNuQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.18.17: + resolution: {integrity: sha512-sOxEvR8d7V7Kw8QqzxWc7bFfnWnGdaFBut1dRUYtu+EIRXefBc/eIsiUiShnW0hM3FmQ5Zf27suDuHsKgZ5QrA==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.18.17: + resolution: {integrity: sha512-c9w3tE7qA3CYWjT+M3BMbwMt+0JYOp3vCMKgVBrCl1nwjAlOMYzEo+gG7QaZ9AtqZFj5MbUc885wuBBmu6aADQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.18.17: + resolution: {integrity: sha512-2d3Lw6wkwgSLC2fIvXKoMNGVaeY8qdN0IC3rfuVxJp89CRfA3e3VqWifGDfuakPmp90+ZirmTfye1n4ncjv2lg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.18.17: + resolution: {integrity: sha512-1DS9F966pn5pPnqXYz16dQqWIB0dmDfAQZd6jSSpiT9eX1NzKh07J6VKR3AoXXXEk6CqZMojiVDSZi1SlmKVdg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.18.17: + resolution: {integrity: sha512-EvLsxCk6ZF0fpCB6w6eOI2Fc8KW5N6sHlIovNe8uOFObL2O+Mr0bflPHyHwLT6rwMg9r77WOAWb2FqCQrVnwFg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.18.17: + resolution: {integrity: sha512-e0bIdHA5p6l+lwqTE36NAW5hHtw2tNRmHlGBygZC14QObsA3bD4C6sXLJjvnDIjSKhW1/0S3eDy+QmX/uZWEYQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.18.17: + resolution: {integrity: sha512-BAAilJ0M5O2uMxHYGjFKn4nJKF6fNCdP1E0o5t5fvMYYzeIqy2JdAP88Az5LHt9qBoUa4tDaRpfWt21ep5/WqQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.18.17: + resolution: {integrity: sha512-Wh/HW2MPnC3b8BqRSIme/9Zhab36PPH+3zam5pqGRH4pE+4xTrVLx2+XdGp6fVS3L2x+DrsIcsbMleex8fbE6g==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.18.17: + resolution: {integrity: sha512-j/34jAl3ul3PNcK3pfI0NSlBANduT2UO5kZ7FCaK33XFv3chDhICLY8wJJWIhiQ+YNdQ9dxqQctRg2bvrMlYgg==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.18.17: + resolution: {integrity: sha512-QM50vJ/y+8I60qEmFxMoxIx4de03pGo2HwxdBeFd4nMh364X6TIBZ6VQ5UQmPbQWUVWHWws5MmJXlHAXvJEmpQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.18.17: + resolution: {integrity: sha512-/jGlhWR7Sj9JPZHzXyyMZ1RFMkNPjC6QIAan0sDOtIo2TYk3tZn5UDrkE0XgsTQCxWTTOcMPf9p6Rh2hXtl5TQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.18.17: + resolution: {integrity: sha512-rSEeYaGgyGGf4qZM2NonMhMOP/5EHp4u9ehFiBrg7stH6BYEEjlkVREuDEcQ0LfIl53OXLxNbfuIj7mr5m29TA==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.18.17: + resolution: {integrity: sha512-Y7ZBbkLqlSgn4+zot4KUNYst0bFoO68tRgI6mY2FIM+b7ZbyNVtNbDP5y8qlu4/knZZ73fgJDlXID+ohY5zt5g==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.18.17: + resolution: {integrity: sha512-bwPmTJsEQcbZk26oYpc4c/8PvTY3J5/QK8jM19DVlEsAB41M39aWovWoHtNm78sd6ip6prilxeHosPADXtEJFw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.18.17: + resolution: {integrity: sha512-H/XaPtPKli2MhW+3CQueo6Ni3Avggi6hP/YvgkEe1aSaxw+AeO8MFjq8DlgfTd9Iz4Yih3QCZI6YLMoyccnPRg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.18.17: + resolution: {integrity: sha512-fGEb8f2BSA3CW7riJVurug65ACLuQAzKq0SSqkY2b2yHHH0MzDfbLyKIGzHwOI/gkHcxM/leuSW6D5w/LMNitA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@eslint-community/eslint-utils@4.4.0(eslint@8.44.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.44.0 + eslint-visitor-keys: 3.4.2 + dev: true + + /@eslint-community/regexpp@4.6.2: + resolution: {integrity: sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/eslintrc@2.1.1: + resolution: {integrity: sha512-9t7ZA7NGGK8ckelF0PQCfcxIUzs1Md5rrO6U/c+FIQNanea5UZC0wqKXH4vHBccmu4ZJgZ2idtPeW7+Q2npOEA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.1 + globals: 13.20.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/js@8.44.0: + resolution: {integrity: sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@fingerprintjs/fingerprintjs@4.0.1: + resolution: {integrity: sha512-utXfX0ntmU08MxQ1cfKRbri57xb+aqYNIt2UNYcPsT/fQgKhZsnIBGRIhEifMZ7NZDyGLAhctWaytDkC27fibA==} + dependencies: + tslib: 2.6.0 + dev: false + + /@humanwhocodes/config-array@0.11.10: + resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@1.2.1: + resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + dev: true + + /@ioredis/commands@1.2.0: + resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==} + + /@jest/schemas@29.6.0: + resolution: {integrity: sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@sinclair/typebox': 0.27.8 + dev: true + + /@jest/types@29.6.1: + resolution: {integrity: sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.0 + '@types/istanbul-lib-coverage': 2.0.4 + '@types/istanbul-reports': 3.0.1 + '@types/node': 20.3.3 + '@types/yargs': 17.0.24 + chalk: 4.1.2 + dev: true + + /@jridgewell/gen-mapping@0.3.3: + resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.18 + dev: true + + /@jridgewell/resolve-uri@3.1.0: + resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/resolve-uri@3.1.1: + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + + /@jridgewell/set-array@1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/source-map@0.3.5: + resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.18 + dev: true + + /@jridgewell/sourcemap-codec@1.4.14: + resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} + dev: true + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + + /@jridgewell/trace-mapping@0.3.18: + resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==} + dependencies: + '@jridgewell/resolve-uri': 3.1.0 + '@jridgewell/sourcemap-codec': 1.4.14 + dev: true + + /@jridgewell/trace-mapping@0.3.9: + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + + /@leichtgewicht/ip-codec@2.0.4: + resolution: {integrity: sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==} + dev: true + + /@lukeed/csprng@1.1.0: + resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==} + engines: {node: '>=8'} + + /@manypkg/find-root@1.1.0: + resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} + dependencies: + '@babel/runtime': 7.22.6 + '@types/node': 12.20.55 + find-up: 4.1.0 + fs-extra: 8.1.0 + dev: true + + /@manypkg/get-packages@1.1.3: + resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + dependencies: + '@babel/runtime': 7.22.6 + '@changesets/types': 4.1.0 + '@manypkg/find-root': 1.1.0 + fs-extra: 8.1.0 + globby: 11.1.0 + read-yaml-file: 1.1.0 + dev: true + + /@mapbox/node-pre-gyp@1.0.11: + resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} + hasBin: true + dependencies: + detect-libc: 2.0.2 + https-proxy-agent: 5.0.1 + make-dir: 3.1.0 + node-fetch: 2.6.12 + nopt: 5.0.0 + npmlog: 5.0.1 + rimraf: 3.0.2 + semver: 7.5.4 + tar: 6.1.15 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /@nestjs/axios@2.0.0(@nestjs/common@9.0.0)(axios@1.4.0)(reflect-metadata@0.1.13)(rxjs@7.8.1): + resolution: {integrity: sha512-F6oceoQLEn031uun8NiommeMkRIojQqVryxQy/mK7fx0CI0KbgkJL3SloCQcsOD+agoEnqKJKXZpEvL6FNswJg==} + peerDependencies: + '@nestjs/common': ^7.0.0 || ^8.0.0 || ^9.0.0 + axios: ^1.3.1 + reflect-metadata: ^0.1.12 + rxjs: ^6.0.0 || ^7.0.0 + dependencies: + '@nestjs/common': 9.0.0(reflect-metadata@0.1.13)(rxjs@7.8.1) + axios: 1.4.0 + reflect-metadata: 0.1.13 + rxjs: 7.8.1 + dev: false + + /@nestjs/cli@10.0.0: + resolution: {integrity: sha512-14pju3ejAAUpFe1iK99v/b7Bw96phBMV58GXTSm3TcdgaI4O7UTLXTbMiUNyU+LGr/1CPIfThcWqFyKhDIC9VQ==} + engines: {node: '>= 16'} + hasBin: true + peerDependencies: + '@swc/cli': ^0.1.62 + '@swc/core': ^1.3.62 + peerDependenciesMeta: + '@swc/cli': + optional: true + '@swc/core': + optional: true + dependencies: + '@angular-devkit/core': 16.1.0(chokidar@3.5.3) + '@angular-devkit/schematics': 16.1.0(chokidar@3.5.3) + '@angular-devkit/schematics-cli': 16.1.0(chokidar@3.5.3) + '@nestjs/schematics': 10.0.0(chokidar@3.5.3)(typescript@5.1.3) + chalk: 4.1.2 + chokidar: 3.5.3 + cli-table3: 0.6.3 + commander: 4.1.1 + fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.1.3)(webpack@5.87.0) + inquirer: 8.2.5 + node-emoji: 1.11.0 + ora: 5.4.1 + os-name: 4.0.1 + rimraf: 4.4.1 + shelljs: 0.8.5 + source-map-support: 0.5.21 + tree-kill: 1.2.2 + tsconfig-paths: 4.2.0 + tsconfig-paths-webpack-plugin: 4.0.1 + typescript: 5.1.3 + webpack: 5.87.0 + webpack-node-externals: 3.0.0 + transitivePeerDependencies: + - esbuild + - uglify-js + - webpack-cli + dev: true + + /@nestjs/cli@9.0.0: + resolution: {integrity: sha512-xT5uOoIEcaB/Fn6UeF7atfKqKiEEsTeRKPiM55p+e5H9WVw8FC2r4ceZgaINJbsw0QWskVj/ZQadMo6dA6hXxw==} + engines: {node: '>= 12.9.0'} + hasBin: true + dependencies: + '@angular-devkit/core': 14.0.5(chokidar@3.5.3) + '@angular-devkit/schematics': 14.0.5(chokidar@3.5.3) + '@angular-devkit/schematics-cli': 14.0.5(chokidar@3.5.3) + '@nestjs/schematics': 9.0.0(chokidar@3.5.3)(typescript@4.7.4) + chalk: 3.0.0 + chokidar: 3.5.3 + cli-table3: 0.6.2 + commander: 4.1.1 + fork-ts-checker-webpack-plugin: 7.2.11(typescript@4.7.4)(webpack@5.73.0) + inquirer: 7.3.3 + node-emoji: 1.11.0 + ora: 5.4.1 + os-name: 4.0.1 + rimraf: 3.0.2 + shelljs: 0.8.5 + source-map-support: 0.5.21 + tree-kill: 1.2.2 + tsconfig-paths: 3.14.1 + tsconfig-paths-webpack-plugin: 3.5.2 + typescript: 4.7.4 + webpack: 5.73.0 + webpack-node-externals: 3.0.0 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + - vue-template-compiler + - webpack-cli + dev: true + + /@nestjs/common@10.1.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1): + resolution: {integrity: sha512-3GNOuDjeAqEVt5Zjia3ZSK55Jg80hIIkq52BOzU+LkCjFgbuEhDot80lCKu05WyntAMAq5wREoDRGEGlSVxENw==} + peerDependencies: + class-transformer: '*' + class-validator: '*' + reflect-metadata: ^0.1.12 + rxjs: ^7.1.0 + peerDependenciesMeta: + class-transformer: + optional: true + class-validator: + optional: true + dependencies: + class-transformer: 0.5.1 + class-validator: 0.14.0 + iterare: 1.2.1 + reflect-metadata: 0.1.13 + rxjs: 7.8.1 + tslib: 2.6.0 + uid: 2.0.2 + + /@nestjs/common@9.0.0(reflect-metadata@0.1.13)(rxjs@7.8.1): + resolution: {integrity: sha512-dyAd48ux/eFYj1uEnQAisSVWq54ttEfeHJBDljvAc6hXbBNHTzZfq/fUH6DmlK29WdGXNMVabCjfduwX2EPquQ==} + peerDependencies: + cache-manager: '*' + class-transformer: '*' + class-validator: '*' + reflect-metadata: ^0.1.12 + rxjs: ^7.1.0 + peerDependenciesMeta: + cache-manager: + optional: true + class-transformer: + optional: true + class-validator: + optional: true + dependencies: + iterare: 1.2.1 + reflect-metadata: 0.1.13 + rxjs: 7.8.1 + tslib: 2.4.0 + uuid: 8.3.2 + dev: false + + /@nestjs/config@2.3.2(@nestjs/common@9.0.0)(reflect-metadata@0.1.13)(rxjs@7.8.1): + resolution: {integrity: sha512-VtGV8PBpxzMzz68kdxTWqPm9v7SYCSZXQ0tC72AMNnjdmU+CVjUSLpEpdnm0XcWHxE1nV6wSI3HZxsATIV4ZxA==} + peerDependencies: + '@nestjs/common': ^7.0.0 || ^8.0.0 || ^9.0.0 + reflect-metadata: ^0.1.13 + rxjs: ^6.0.0 || ^7.2.0 + dependencies: + '@nestjs/common': 9.0.0(reflect-metadata@0.1.13)(rxjs@7.8.1) + dotenv: 16.0.3 + dotenv-expand: 10.0.0 + lodash: 4.17.21 + reflect-metadata: 0.1.13 + rxjs: 7.8.1 + uuid: 9.0.0 + dev: false + + /@nestjs/config@3.0.0(@nestjs/common@10.1.0)(reflect-metadata@0.1.13): + resolution: {integrity: sha512-fzASk1Uv6AjdE6uA1na8zpqRCXAhRpcfgpCVv3SAKlgJ3VR3bEjcI4G17WHLgLBsmPzI1ofdkSI451WLD1F1Rw==} + peerDependencies: + '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 + reflect-metadata: ^0.1.13 + dependencies: + '@nestjs/common': 10.1.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + dotenv: 16.1.4 + dotenv-expand: 10.0.0 + lodash: 4.17.21 + reflect-metadata: 0.1.13 + uuid: 9.0.0 + dev: false + + /@nestjs/core@10.1.0(@nestjs/common@10.1.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@10.1.0)(reflect-metadata@0.1.13)(rxjs@7.8.1): + resolution: {integrity: sha512-3ogHxrRAktQZNBSV709QxhNJQPsVInZRqxAK2fV7JDnfoBMu1lM3xI7cO498iViqq5xme3o/46+AdfjW9W2E2A==} + requiresBuild: true + peerDependencies: + '@nestjs/common': ^10.0.0 + '@nestjs/microservices': ^10.0.0 + '@nestjs/platform-express': ^10.0.0 + '@nestjs/websockets': ^10.0.0 + reflect-metadata: ^0.1.12 + rxjs: ^7.1.0 + peerDependenciesMeta: + '@nestjs/microservices': + optional: true + '@nestjs/platform-express': + optional: true + '@nestjs/websockets': + optional: true + dependencies: + '@nestjs/common': 10.1.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/microservices': 10.0.5(@nestjs/common@10.1.0)(@nestjs/core@10.1.0)(ioredis@5.3.2)(nats@2.15.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/platform-express': 10.1.0(@nestjs/common@10.1.0)(@nestjs/core@10.1.0) + '@nuxtjs/opencollective': 0.3.2 + fast-safe-stringify: 2.1.1 + iterare: 1.2.1 + path-to-regexp: 3.2.0 + reflect-metadata: 0.1.13 + rxjs: 7.8.1 + tslib: 2.6.0 + uid: 2.0.2 + transitivePeerDependencies: + - encoding + + /@nestjs/core@9.0.0(@nestjs/common@9.0.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@9.0.0)(reflect-metadata@0.1.13)(rxjs@7.8.1): + resolution: {integrity: sha512-Ib25JrYQf5ICro19FBytoMpMQicanC4HG3goPBSqsolu+AhVzSU0OhDwmmiDy3aHgmheFnNEEdUH+Gh5Rm2cNw==} + requiresBuild: true + peerDependencies: + '@nestjs/common': ^9.0.0 + '@nestjs/microservices': ^9.0.0 + '@nestjs/platform-express': ^9.0.0 + '@nestjs/websockets': ^9.0.0 + reflect-metadata: ^0.1.12 + rxjs: ^7.1.0 + peerDependenciesMeta: + '@nestjs/microservices': + optional: true + '@nestjs/platform-express': + optional: true + '@nestjs/websockets': + optional: true + dependencies: + '@nestjs/common': 9.0.0(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/microservices': 10.0.5(@nestjs/common@9.0.0)(@nestjs/core@9.0.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/platform-express': 9.0.0(@nestjs/common@9.0.0)(@nestjs/core@9.0.0) + '@nuxtjs/opencollective': 0.3.2 + fast-safe-stringify: 2.1.1 + iterare: 1.2.1 + object-hash: 3.0.0 + path-to-regexp: 3.2.0 + reflect-metadata: 0.1.13 + rxjs: 7.8.1 + tslib: 2.4.0 + uuid: 8.3.2 + transitivePeerDependencies: + - encoding + dev: false + + /@nestjs/jwt@10.0.3(@nestjs/common@9.0.0): + resolution: {integrity: sha512-WO8MI3uEMOFKpbO+SAg6l4aRCr+9KvaL+raFMZaXuEUDphXek6pqdox+4tex9242pNSJUA0trfAMaiy/yVrXQg==} + peerDependencies: + '@nestjs/common': ^8.0.0 || ^9.0.0 + dependencies: + '@nestjs/common': 9.0.0(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@types/jsonwebtoken': 9.0.1 + jsonwebtoken: 9.0.0 + dev: false + + /@nestjs/jwt@10.1.0(@nestjs/common@10.1.0): + resolution: {integrity: sha512-iLwCGS25ybUxGS7i5j/Mwuyzvp/WxJftHlm8aLEBv5GV92apz6L1QVjxLdZrqXbzo++C8gdJauhzil8qitY+6w==} + peerDependencies: + '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 + dependencies: + '@nestjs/common': 10.1.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@types/jsonwebtoken': 9.0.2 + jsonwebtoken: 9.0.0 + dev: false + + /@nestjs/microservices@10.0.5(@nestjs/common@10.1.0)(@nestjs/core@10.1.0)(ioredis@5.3.2)(nats@2.15.1)(reflect-metadata@0.1.13)(rxjs@7.8.1): + resolution: {integrity: sha512-hWzyU9Hrv/v58BRRfxtVFza7k7WQ55HY6R/6hQR1Lju7mMWqByE8ddAyDl3K4uCKGshTL90ixKCoEpLi0suMjA==} + peerDependencies: + '@grpc/grpc-js': '*' + '@nestjs/common': ^10.0.0 + '@nestjs/core': ^10.0.0 + '@nestjs/websockets': ^10.0.0 + amqp-connection-manager: '*' + amqplib: '*' + cache-manager: '*' + ioredis: '*' + kafkajs: '*' + mqtt: '*' + nats: '*' + reflect-metadata: ^0.1.12 + rxjs: ^7.1.0 + peerDependenciesMeta: + '@grpc/grpc-js': + optional: true + '@nestjs/websockets': + optional: true + amqp-connection-manager: + optional: true + amqplib: + optional: true + cache-manager: + optional: true + ioredis: + optional: true + kafkajs: + optional: true + mqtt: + optional: true + nats: + optional: true + dependencies: + '@nestjs/common': 10.1.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/core': 10.1.0(@nestjs/common@10.1.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@10.1.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + ioredis: 5.3.2 + iterare: 1.2.1 + nats: 2.15.1 + reflect-metadata: 0.1.13 + rxjs: 7.8.1 + tslib: 2.6.0 + + /@nestjs/microservices@10.0.5(@nestjs/common@9.0.0)(@nestjs/core@9.0.0)(reflect-metadata@0.1.13)(rxjs@7.8.1): + resolution: {integrity: sha512-hWzyU9Hrv/v58BRRfxtVFza7k7WQ55HY6R/6hQR1Lju7mMWqByE8ddAyDl3K4uCKGshTL90ixKCoEpLi0suMjA==} + peerDependencies: + '@grpc/grpc-js': '*' + '@nestjs/common': ^10.0.0 + '@nestjs/core': ^10.0.0 + '@nestjs/websockets': ^10.0.0 + amqp-connection-manager: '*' + amqplib: '*' + cache-manager: '*' + ioredis: '*' + kafkajs: '*' + mqtt: '*' + nats: '*' + reflect-metadata: ^0.1.12 + rxjs: ^7.1.0 + peerDependenciesMeta: + '@grpc/grpc-js': + optional: true + '@nestjs/websockets': + optional: true + amqp-connection-manager: + optional: true + amqplib: + optional: true + cache-manager: + optional: true + ioredis: + optional: true + kafkajs: + optional: true + mqtt: + optional: true + nats: + optional: true + dependencies: + '@nestjs/common': 9.0.0(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/core': 9.0.0(@nestjs/common@9.0.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@9.0.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + iterare: 1.2.1 + reflect-metadata: 0.1.13 + rxjs: 7.8.1 + tslib: 2.6.0 + dev: false + + /@nestjs/passport@10.0.0(@nestjs/common@10.1.0)(passport@0.6.0): + resolution: {integrity: sha512-IlKKc6M7JOe+4dBbW6gZsXBSD05ZYgwfGf3GJhgCmUGYVqffpDdALQSS6JftnExrE+12rACoEmHkzYwKAGVK0Q==} + peerDependencies: + '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 + passport: ^0.4.0 || ^0.5.0 || ^0.6.0 + dependencies: + '@nestjs/common': 10.1.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + passport: 0.6.0 + dev: false + + /@nestjs/platform-express@10.1.0(@nestjs/common@10.1.0)(@nestjs/core@10.1.0): + resolution: {integrity: sha512-wl3gsad9Zsv+Im8Fl+meXwpzPLNFRlLbrepGL6Y8za35xXsdx74oCv7NJbjptHMYdwzTZHvbyprfSxV+oHUaXg==} + peerDependencies: + '@nestjs/common': ^10.0.0 + '@nestjs/core': ^10.0.0 + dependencies: + '@nestjs/common': 10.1.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/core': 10.1.0(@nestjs/common@10.1.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@10.1.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + body-parser: 1.20.2 + cors: 2.8.5 + express: 4.18.2 + multer: 1.4.4-lts.1 + tslib: 2.6.0 + transitivePeerDependencies: + - supports-color + + /@nestjs/platform-express@9.0.0(@nestjs/common@9.0.0)(@nestjs/core@9.0.0): + resolution: {integrity: sha512-5W5KeYHKKQe4/H7DcPViIObC9nO74P8wnLZUpk4HCUUuFZIzPpUu9v+RAg7c/jGrbdyjfg3VKODCUKFo6PBfmg==} + peerDependencies: + '@nestjs/common': ^9.0.0 + '@nestjs/core': ^9.0.0 + dependencies: + '@nestjs/common': 9.0.0(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/core': 9.0.0(@nestjs/common@9.0.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@9.0.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + body-parser: 1.20.0 + cors: 2.8.5 + express: 4.18.1 + multer: 1.4.4-lts.1 + tslib: 2.4.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@nestjs/schematics@10.0.0(chokidar@3.5.3)(typescript@5.1.3): + resolution: {integrity: sha512-gfUy/N1m1paN33BXq4d7HoCM+zM4rFxYjqAb8jkrBfBHiwyEhHHozfX/aRy/kOnAcy/VP8v4Zs4HKKrbRRlHnw==} + peerDependencies: + typescript: '>=4.8.2' + dependencies: + '@angular-devkit/core': 16.1.0(chokidar@3.5.3) + '@angular-devkit/schematics': 16.1.0(chokidar@3.5.3) + comment-json: 4.2.3 + jsonc-parser: 3.2.0 + pluralize: 8.0.0 + typescript: 5.1.3 + transitivePeerDependencies: + - chokidar + dev: true + + /@nestjs/schematics@9.0.0(chokidar@3.5.3)(typescript@4.7.4): + resolution: {integrity: sha512-l4AReqX597iKyAXVN9WsrLQ1NDY0G15s7x8dHpwM0+3MOFoEKZMvqeiFrfVMqbwuMiTvXTuLcoMdlKuz7qtrDg==} + peerDependencies: + typescript: ^4.3.5 + dependencies: + '@angular-devkit/core': 14.0.5(chokidar@3.5.3) + '@angular-devkit/schematics': 14.0.5(chokidar@3.5.3) + fs-extra: 10.1.0 + jsonc-parser: 3.0.0 + pluralize: 8.0.0 + typescript: 4.7.4 + transitivePeerDependencies: + - chokidar + dev: true + + /@nestjs/schematics@9.0.0(typescript@5.1.3): + resolution: {integrity: sha512-l4AReqX597iKyAXVN9WsrLQ1NDY0G15s7x8dHpwM0+3MOFoEKZMvqeiFrfVMqbwuMiTvXTuLcoMdlKuz7qtrDg==} + peerDependencies: + typescript: ^4.3.5 + dependencies: + '@angular-devkit/core': 14.0.5(chokidar@3.5.3) + '@angular-devkit/schematics': 14.0.5(chokidar@3.5.3) + fs-extra: 10.1.0 + jsonc-parser: 3.0.0 + pluralize: 8.0.0 + typescript: 5.1.3 + transitivePeerDependencies: + - chokidar + dev: true + + /@nestjs/testing@10.0.0(@nestjs/common@10.1.0)(@nestjs/core@10.1.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@10.1.0): + resolution: {integrity: sha512-U5q3+svkddpdSk51ZFCEnFpQuWxAwE4ahsX77FrqqCAYidr7HUtL/BHYOVzI5H9vUH6BvJxMbfo3tiUXQl/2aA==} + peerDependencies: + '@nestjs/common': ^10.0.0 + '@nestjs/core': ^10.0.0 + '@nestjs/microservices': ^10.0.0 + '@nestjs/platform-express': ^10.0.0 + peerDependenciesMeta: + '@nestjs/microservices': + optional: true + '@nestjs/platform-express': + optional: true + dependencies: + '@nestjs/common': 10.1.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/core': 10.1.0(@nestjs/common@10.1.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@10.1.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/microservices': 10.0.5(@nestjs/common@10.1.0)(@nestjs/core@10.1.0)(ioredis@5.3.2)(nats@2.15.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/platform-express': 10.1.0(@nestjs/common@10.1.0)(@nestjs/core@10.1.0) + tslib: 2.5.3 + dev: true + + /@nestjs/typeorm@10.0.0(@nestjs/common@10.1.0)(@nestjs/core@10.1.0)(reflect-metadata@0.1.13)(rxjs@7.8.1)(typeorm@0.3.17): + resolution: {integrity: sha512-WQU4HCDTz4UavsFzvGUKDHqi0MO5K47yFoPXdmh+Z/hCNO7SHCMmV9jLiLukM8n5nKUqJ3jDqiljkWBcZPdCtA==} + peerDependencies: + '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 + '@nestjs/core': ^8.0.0 || ^9.0.0 || ^10.0.0 + reflect-metadata: ^0.1.13 + rxjs: ^7.2.0 + typeorm: ^0.3.0 + dependencies: + '@nestjs/common': 10.1.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/core': 10.1.0(@nestjs/common@10.1.0)(@nestjs/microservices@10.0.5)(@nestjs/platform-express@10.1.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + reflect-metadata: 0.1.13 + rxjs: 7.8.1 + typeorm: 0.3.17(ts-node@10.9.1) + uuid: 9.0.0 + dev: false + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: true + + /@nuxtjs/opencollective@0.3.2: + resolution: {integrity: sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==} + engines: {node: '>=8.0.0', npm: '>=5.0.0'} + hasBin: true + dependencies: + chalk: 4.1.2 + consola: 2.15.3 + node-fetch: 2.6.12 + transitivePeerDependencies: + - encoding + + /@pmmmwh/react-refresh-webpack-plugin@0.5.10(react-refresh@0.14.0)(webpack-dev-server@4.13.3)(webpack@5.75.0): + resolution: {integrity: sha512-j0Ya0hCFZPd4x40qLzbhGsh9TMtdb+CJQiso+WxLOPNasohq9cc5SNUcwsZaRH6++Xh91Xkm/xHCkuIiIu0LUA==} + engines: {node: '>= 10.13'} + peerDependencies: + '@types/webpack': 4.x || 5.x + react-refresh: '>=0.10.0 <1.0.0' + sockjs-client: ^1.4.0 + type-fest: '>=0.17.0 <4.0.0' + webpack: '>=4.43.0 <6.0.0' + webpack-dev-server: 3.x || 4.x + webpack-hot-middleware: 2.x + webpack-plugin-serve: 0.x || 1.x + peerDependenciesMeta: + '@types/webpack': + optional: true + sockjs-client: + optional: true + type-fest: + optional: true + webpack-dev-server: + optional: true + webpack-hot-middleware: + optional: true + webpack-plugin-serve: + optional: true + dependencies: + ansi-html-community: 0.0.8 + common-path-prefix: 3.0.0 + core-js-pure: 3.32.0 + error-stack-parser: 2.1.4 + find-up: 5.0.0 + html-entities: 2.4.0 + loader-utils: 2.0.4 + react-refresh: 0.14.0 + schema-utils: 3.3.0 + source-map: 0.7.4 + webpack: 5.75.0(webpack-cli@5.0.2) + webpack-dev-server: 4.13.3(webpack-cli@5.0.2)(webpack@5.75.0) + dev: true + + /@polka/url@1.0.0-next.21: + resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} + dev: true + + /@rc-component/color-picker@1.2.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-IitJ6RWGHs7btI1AqzGPrehr5bueWLGDUyMKwDwvFunfSDo/o8g/95kUG55vC5EYLM0ZJ3SDfw45OrW5KAx3oA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + '@ctrl/tinycolor': 3.6.0 + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@rc-component/color-picker@1.4.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-vh5EWqnsayZa/JwUznqDaPJz39jznx/YDbyBuVJntv735tKXKwEUZZb2jYEldOg+NKWZwtALjGMrNeGBmqFoEw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + '@ctrl/tinycolor': 3.6.0 + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@rc-component/context@1.3.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-6QdaCJ7Wn5UZLJs15IEfqy4Ru3OaL5ctqpQYWd5rlfV9wwzrzdt6+kgAQZV/qdB0MUPN4nhyBfRembQCIvBf+w==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@rc-component/mini-decimal@1.1.0: + resolution: {integrity: sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==} + engines: {node: '>=8.x'} + dependencies: + '@babel/runtime': 7.22.6 + dev: false + + /@rc-component/mutate-observer@1.0.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-okqRJSfNisXdI6CUeOLZC5ukBW/8kir2Ii4PJiKpUt+3+uS7dxwJUMxsUZquxA1rQuL8YcEmKVp/TCnR+yUdZA==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@rc-component/portal@1.1.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@rc-component/tour@1.8.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-CsrQnfKgNArxx2j1RNHVLZgVA+rLrEj06lIsl4KSynMqADsqz8eKvVkr0F3p9PA10948M6WEEZt5a/FGAbGR2A==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/portal': 1.1.2(react-dom@18.2.0)(react@18.2.0) + '@rc-component/trigger': 1.15.1(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@rc-component/trigger@1.15.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-U1F9WsIMLXB2JLjLSEa6uWifmTX2vxQ1r0RQCLnor8d/83e3U7TuclNbcWcM/eGcgrT2YUZid3TLDDKbDOHmLg==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/portal': 1.1.2(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-align: 4.0.15(react-dom@18.2.0)(react@18.2.0) + rc-motion: 2.7.3(react-dom@18.2.0)(react@18.2.0) + rc-resize-observer: 1.3.1(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@remix-run/router@1.6.2: + resolution: {integrity: sha512-LzqpSrMK/3JBAVBI9u3NWtOhWNw5AMQfrUFYB0+bDHTSw17z++WJLsPsxAuK+oSddsxk4d7F/JcdDPM1M5YAhA==} + engines: {node: '>=14'} + dev: false + + /@remix-run/router@1.7.1: + resolution: {integrity: sha512-bgVQM4ZJ2u2CM8k1ey70o1ePFXsEzYVZoWghh6WjM8p59jQ7HxzbHW4SbnWFG7V9ig9chLawQxDTZ3xzOF8MkQ==} + engines: {node: '>=14'} + dev: false + + /@remix-run/router@1.7.2: + resolution: {integrity: sha512-7Lcn7IqGMV+vizMPoEl5F0XDshcdDYtMI6uJLQdQz5CfZAwy3vvGKYSUk789qndt5dEC4HfSjviSYlSoHGL2+A==} + engines: {node: '>=14'} + dev: false + + /@rollup/plugin-commonjs@24.1.0(rollup@3.21.5): + resolution: {integrity: sha512-eSL45hjhCWI0jCCXcNtLVqM5N1JlBGvlFfY0m6oOYnLCJ6N0qEXoZql4sY2MOUArzhH4SA/qBpTxvvZp2Sc+DQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.68.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@rollup/pluginutils': 5.0.2(rollup@3.21.5) + commondir: 1.0.1 + estree-walker: 2.0.2 + glob: 8.1.0 + is-reference: 1.2.1 + magic-string: 0.27.0 + rollup: 3.21.5 + dev: true + + /@rollup/plugin-node-resolve@15.0.2(rollup@3.21.5): + resolution: {integrity: sha512-Y35fRGUjC3FaurG722uhUuG8YHOJRJQbI6/CkbRkdPotSpDj9NtIN85z1zrcyDcCQIW4qp5mgG72U+gJ0TAFEg==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@rollup/pluginutils': 5.0.2(rollup@3.21.5) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-builtin-module: 3.2.1 + is-module: 1.0.0 + resolve: 1.22.2 + rollup: 3.21.5 + dev: true + + /@rollup/pluginutils@4.2.1: + resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} + engines: {node: '>= 8.0.0'} + dependencies: + estree-walker: 2.0.2 + picomatch: 2.3.1 + dev: true + + /@rollup/pluginutils@5.0.2(rollup@3.21.5): + resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@types/estree': 1.0.1 + estree-walker: 2.0.2 + picomatch: 2.3.1 + rollup: 3.21.5 + dev: true + + /@sinclair/typebox@0.27.8: + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + dev: true + + /@sqltools/formatter@1.2.5: + resolution: {integrity: sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==} + dev: false + + /@trysound/sax@0.2.0: + resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} + engines: {node: '>=10.13.0'} + dev: true + + /@tsconfig/node10@1.0.9: + resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} + + /@tsconfig/node12@1.0.11: + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + /@tsconfig/node14@1.0.3: + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + /@tsconfig/node16@1.0.4: + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + + /@types/body-parser@1.19.2: + resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==} + dependencies: + '@types/connect': 3.4.35 + '@types/node': 20.3.3 + dev: true + + /@types/bonjour@3.5.10: + resolution: {integrity: sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==} + dependencies: + '@types/node': 20.3.3 + dev: true + + /@types/connect-history-api-fallback@1.5.0: + resolution: {integrity: sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig==} + dependencies: + '@types/express-serve-static-core': 4.17.35 + '@types/node': 20.3.3 + dev: true + + /@types/connect@3.4.35: + resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} + dependencies: + '@types/node': 20.3.3 + dev: true + + /@types/cookie-parser@1.4.3: + resolution: {integrity: sha512-CqSKwFwefj4PzZ5n/iwad/bow2hTCh0FlNAeWLtQM3JA/NX/iYagIpWG2cf1bQKQ2c9gU2log5VUCrn7LDOs0w==} + dependencies: + '@types/express': 4.17.17 + dev: true + + /@types/cookiejar@2.1.2: + resolution: {integrity: sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==} + dev: true + + /@types/eslint-scope@3.7.4: + resolution: {integrity: sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==} + dependencies: + '@types/eslint': 8.44.1 + '@types/estree': 0.0.51 + dev: true + + /@types/eslint@8.44.1: + resolution: {integrity: sha512-XpNDc4Z5Tb4x+SW1MriMVeIsMoONHCkWFMkR/aPJbzEsxqHy+4Glu/BqTdPrApfDeMaXbtNh6bseNgl5KaWrSg==} + dependencies: + '@types/estree': 0.0.51 + '@types/json-schema': 7.0.12 + dev: true + + /@types/estree@0.0.51: + resolution: {integrity: sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==} + dev: true + + /@types/estree@1.0.1: + resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} + dev: true + + /@types/express-serve-static-core@4.17.35: + resolution: {integrity: sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==} + dependencies: + '@types/node': 20.3.3 + '@types/qs': 6.9.7 + '@types/range-parser': 1.2.4 + '@types/send': 0.17.1 + dev: true + + /@types/express@4.17.17: + resolution: {integrity: sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==} + dependencies: + '@types/body-parser': 1.19.2 + '@types/express-serve-static-core': 4.17.35 + '@types/qs': 6.9.7 + '@types/serve-static': 1.15.2 + dev: true + + /@types/history@4.7.11: + resolution: {integrity: sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==} + dev: true + + /@types/html-minifier-terser@6.1.0: + resolution: {integrity: sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==} + dev: true + + /@types/http-errors@2.0.1: + resolution: {integrity: sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==} + dev: true + + /@types/http-proxy@1.17.11: + resolution: {integrity: sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==} + dependencies: + '@types/node': 20.3.3 + dev: true + + /@types/is-ci@3.0.0: + resolution: {integrity: sha512-Q0Op0hdWbYd1iahB+IFNQcWXFq4O0Q5MwQP7uN0souuQ4rPg1vEYcnIOfr1gY+M+6rc8FGoRaBO1mOOvL29sEQ==} + dependencies: + ci-info: 3.8.0 + dev: true + + /@types/istanbul-lib-coverage@2.0.4: + resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} + dev: true + + /@types/istanbul-lib-report@3.0.0: + resolution: {integrity: sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==} + dependencies: + '@types/istanbul-lib-coverage': 2.0.4 + dev: true + + /@types/istanbul-reports@3.0.1: + resolution: {integrity: sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==} + dependencies: + '@types/istanbul-lib-report': 3.0.0 + dev: true + + /@types/js-cookie@3.0.3: + resolution: {integrity: sha512-Xe7IImK09HP1sv2M/aI+48a20VX+TdRJucfq4vfRVy6nWN8PYPOEnlMRSgxJAgYQIXJVL8dZ4/ilAM7dWNaOww==} + dev: true + + /@types/json-schema@7.0.12: + resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} + dev: true + + /@types/json5@0.0.29: + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + dev: true + + /@types/jsonwebtoken@9.0.1: + resolution: {integrity: sha512-c5ltxazpWabia/4UzhIoaDcIza4KViOQhdbjRlfcIGVnsE3c3brkz9Z+F/EeJIECOQP7W7US2hNE930cWWkPiw==} + dependencies: + '@types/node': 20.3.3 + dev: false + + /@types/jsonwebtoken@9.0.2: + resolution: {integrity: sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==} + dependencies: + '@types/node': 20.3.3 + dev: false + + /@types/mime@1.3.2: + resolution: {integrity: sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==} + dev: true + + /@types/mime@3.0.1: + resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==} + dev: true + + /@types/minimist@1.2.2: + resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} + dev: true + + /@types/multer@1.4.7: + resolution: {integrity: sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==} + dependencies: + '@types/express': 4.17.17 + dev: true + + /@types/node@12.20.55: + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + dev: true + + /@types/node@18.16.12: + resolution: {integrity: sha512-tIRrjbY9C277MOfP8M3zjMIhtMlUJ6YVqkGgLjz+74jVsdf4/UjC6Hku4+1N0BS0qyC0JAS6tJLUk9H6JUKviQ==} + + /@types/node@18.16.3: + resolution: {integrity: sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q==} + dev: true + + /@types/node@20.3.3: + resolution: {integrity: sha512-wheIYdr4NYML61AjC8MKj/2jrR/kDQri/CIpVoZwldwhnIrD/j9jIU5bJ8yBKuB2VhpFV7Ab6G2XkBjv9r9Zzw==} + + /@types/normalize-package-data@2.4.1: + resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} + dev: true + + /@types/parse-json@4.0.0: + resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} + dev: true + + /@types/prop-types@15.7.5: + resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} + dev: true + + /@types/qs@6.9.7: + resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==} + dev: true + + /@types/raf@3.4.0: + resolution: {integrity: sha512-taW5/WYqo36N7V39oYyHP9Ipfd5pNFvGTIQsNGj86xV88YQ7GnI30/yMfKDF7Zgin0m3e+ikX88FvImnK4RjGw==} + requiresBuild: true + dev: false + optional: true + + /@types/range-parser@1.2.4: + resolution: {integrity: sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==} + dev: true + + /@types/react-dom@18.2.6: + resolution: {integrity: sha512-2et4PDvg6PVCyS7fuTc4gPoksV58bW0RwSxWKcPRcHZf0PRUGq03TKcD/rUHe3azfV6/5/biUBJw+HhCQjaP0A==} + dependencies: + '@types/react': 18.2.14 + dev: true + + /@types/react-router-dom@5.3.3: + resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==} + dependencies: + '@types/history': 4.7.11 + '@types/react': 18.2.14 + '@types/react-router': 5.1.20 + dev: true + + /@types/react-router@5.1.20: + resolution: {integrity: sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==} + dependencies: + '@types/history': 4.7.11 + '@types/react': 18.2.14 + dev: true + + /@types/react@18.2.14: + resolution: {integrity: sha512-A0zjq+QN/O0Kpe30hA1GidzyFjatVvrpIvWLxD+xv67Vt91TWWgco9IvrJBkeyHm1trGaFS/FSGqPlhyeZRm0g==} + dependencies: + '@types/prop-types': 15.7.5 + '@types/scheduler': 0.16.3 + csstype: 3.1.2 + dev: true + + /@types/resolve@1.20.2: + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + dev: true + + /@types/retry@0.12.0: + resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + dev: true + + /@types/scheduler@0.16.3: + resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==} + dev: true + + /@types/semver@7.5.0: + resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} + dev: true + + /@types/send@0.17.1: + resolution: {integrity: sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==} + dependencies: + '@types/mime': 1.3.2 + '@types/node': 20.3.3 + dev: true + + /@types/serve-index@1.9.1: + resolution: {integrity: sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==} + dependencies: + '@types/express': 4.17.17 + dev: true + + /@types/serve-static@1.15.2: + resolution: {integrity: sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==} + dependencies: + '@types/http-errors': 2.0.1 + '@types/mime': 3.0.1 + '@types/node': 20.3.3 + dev: true + + /@types/sockjs@0.3.33: + resolution: {integrity: sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==} + dependencies: + '@types/node': 20.3.3 + dev: true + + /@types/superagent@4.1.18: + resolution: {integrity: sha512-LOWgpacIV8GHhrsQU+QMZuomfqXiqzz3ILLkCtKx3Us6AmomFViuzKT9D693QTKgyut2oCytMG8/efOop+DB+w==} + dependencies: + '@types/cookiejar': 2.1.2 + '@types/node': 20.3.3 + dev: true + + /@types/supertest@2.0.12: + resolution: {integrity: sha512-X3HPWTwXRerBZS7Mo1k6vMVR1Z6zmJcDVn5O/31whe0tnjE4te6ZJSJGq1RiqHPjzPdMTfjCFogDJmwng9xHaQ==} + dependencies: + '@types/superagent': 4.1.18 + dev: true + + /@types/validator@13.9.0: + resolution: {integrity: sha512-NclP0IbzHj/4tJZKFqKh8E7kZdgss+MCUYV9G+TLltFfDA4lFgE4PKPpDIyS2FlcdANIfSx273emkupvChigbw==} + + /@types/ws@8.5.5: + resolution: {integrity: sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==} + dependencies: + '@types/node': 20.3.3 + dev: true + + /@types/yargs-parser@21.0.0: + resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} + dev: true + + /@types/yargs@17.0.24: + resolution: {integrity: sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==} + dependencies: + '@types/yargs-parser': 21.0.0 + dev: true + + /@typescript-eslint/eslint-plugin@5.61.0(@typescript-eslint/parser@5.61.0)(eslint@8.44.0)(typescript@5.1.3): + resolution: {integrity: sha512-A5l/eUAug103qtkwccSCxn8ZRwT+7RXWkFECdA4Cvl1dOlDUgTpAOfSEElZn2uSUxhdDpnCdetrf0jvU4qrL+g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/parser': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.6.2 + '@typescript-eslint/parser': 5.61.0(eslint@8.44.0)(typescript@5.1.3) + '@typescript-eslint/scope-manager': 5.61.0 + '@typescript-eslint/type-utils': 5.61.0(eslint@8.44.0)(typescript@5.1.3) + '@typescript-eslint/utils': 5.61.0(eslint@8.44.0)(typescript@5.1.3) + debug: 4.3.4 + eslint: 8.44.0 + graphemer: 1.4.0 + ignore: 5.2.4 + natural-compare-lite: 1.4.0 + semver: 7.5.4 + tsutils: 3.21.0(typescript@5.1.3) + typescript: 5.1.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@5.61.0(eslint@8.44.0)(typescript@5.1.3): + resolution: {integrity: sha512-yGr4Sgyh8uO6fSi9hw3jAFXNBHbCtKKFMdX2IkT3ZqpKmtAq3lHS4ixB/COFuAIJpwl9/AqF7j72ZDWYKmIfvg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 5.61.0 + '@typescript-eslint/types': 5.61.0 + '@typescript-eslint/typescript-estree': 5.61.0(typescript@5.1.3) + debug: 4.3.4 + eslint: 8.44.0 + typescript: 5.1.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@5.61.0: + resolution: {integrity: sha512-W8VoMjoSg7f7nqAROEmTt6LoBpn81AegP7uKhhW5KzYlehs8VV0ZW0fIDVbcZRcaP3aPSW+JZFua+ysQN+m/Nw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.61.0 + '@typescript-eslint/visitor-keys': 5.61.0 + dev: true + + /@typescript-eslint/type-utils@5.61.0(eslint@8.44.0)(typescript@5.1.3): + resolution: {integrity: sha512-kk8u//r+oVK2Aj3ph/26XdH0pbAkC2RiSjUYhKD+PExemG4XSjpGFeyZ/QM8lBOa7O8aGOU+/yEbMJgQv/DnCg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 5.61.0(typescript@5.1.3) + '@typescript-eslint/utils': 5.61.0(eslint@8.44.0)(typescript@5.1.3) + debug: 4.3.4 + eslint: 8.44.0 + tsutils: 3.21.0(typescript@5.1.3) + typescript: 5.1.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@5.61.0: + resolution: {integrity: sha512-ldyueo58KjngXpzloHUog/h9REmHl59G1b3a5Sng1GfBo14BkS3ZbMEb3693gnP1k//97lh7bKsp6/V/0v1veQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@typescript-eslint/typescript-estree@5.61.0(typescript@5.1.3): + resolution: {integrity: sha512-Fud90PxONnnLZ36oR5ClJBLTLfU4pIWBmnvGwTbEa2cXIqj70AEDEmOmpkFComjBZ/037ueKrOdHuYmSFVD7Rw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 5.61.0 + '@typescript-eslint/visitor-keys': 5.61.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.4 + tsutils: 3.21.0(typescript@5.1.3) + typescript: 5.1.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@5.61.0(eslint@8.44.0)(typescript@5.1.3): + resolution: {integrity: sha512-mV6O+6VgQmVE6+xzlA91xifndPW9ElFW8vbSF0xCT/czPXVhwDewKila1jOyRwa9AE19zKnrr7Cg5S3pJVrTWQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.44.0) + '@types/json-schema': 7.0.12 + '@types/semver': 7.5.0 + '@typescript-eslint/scope-manager': 5.61.0 + '@typescript-eslint/types': 5.61.0 + '@typescript-eslint/typescript-estree': 5.61.0(typescript@5.1.3) + eslint: 8.44.0 + eslint-scope: 5.1.1 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@5.61.0: + resolution: {integrity: sha512-50XQ5VdbWrX06mQXhy93WywSFZZGsv3EOjq+lqp6WC2t+j3mb6A9xYVdrRxafvK88vg9k9u+CT4l6D8PEatjKg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.61.0 + eslint-visitor-keys: 3.4.2 + dev: true + + /@ucast/core@1.10.2: + resolution: {integrity: sha512-ons5CwXZ/51wrUPfoduC+cO7AS1/wRb0ybpQJ9RrssossDxVy4t49QxWoWgfBDvVKsz9VXzBk9z0wqTdZ+Cq8g==} + dev: false + + /@ucast/js@3.0.3: + resolution: {integrity: sha512-jBBqt57T5WagkAjqfCIIE5UYVdaXYgGkOFYv2+kjq2AVpZ2RIbwCo/TujJpDlwTVluUI+WpnRpoGU2tSGlEvFQ==} + dependencies: + '@ucast/core': 1.10.2 + dev: false + + /@ucast/mongo2js@1.3.4: + resolution: {integrity: sha512-ahazOr1HtelA5AC1KZ9x0UwPMqqimvfmtSm/PRRSeKKeE5G2SCqTgwiNzO7i9jS8zA3dzXpKVPpXMkcYLnyItA==} + dependencies: + '@ucast/core': 1.10.2 + '@ucast/js': 3.0.3 + '@ucast/mongo': 2.4.3 + dev: false + + /@ucast/mongo@2.4.3: + resolution: {integrity: sha512-XcI8LclrHWP83H+7H2anGCEeDq0n+12FU2mXCTz6/Tva9/9ddK/iacvvhCyW6cijAAOILmt0tWplRyRhVyZLsA==} + dependencies: + '@ucast/core': 1.10.2 + dev: false + + /@vitejs/plugin-react@4.0.1(vite@4.4.0): + resolution: {integrity: sha512-g25lL98essfeSj43HJ0o4DMp0325XK0ITkxpgChzJU/CyemgyChtlxfnRbjfwxDGCTRxTiXtQAsdebQXKMRSOA==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.2.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/plugin-transform-react-jsx-self': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.22.9) + react-refresh: 0.14.0 + vite: 4.4.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@webassemblyjs/ast@1.11.1: + resolution: {integrity: sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==} + dependencies: + '@webassemblyjs/helper-numbers': 1.11.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.1 + dev: true + + /@webassemblyjs/ast@1.11.6: + resolution: {integrity: sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==} + dependencies: + '@webassemblyjs/helper-numbers': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + dev: true + + /@webassemblyjs/floating-point-hex-parser@1.11.1: + resolution: {integrity: sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==} + dev: true + + /@webassemblyjs/floating-point-hex-parser@1.11.6: + resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==} + dev: true + + /@webassemblyjs/helper-api-error@1.11.1: + resolution: {integrity: sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==} + dev: true + + /@webassemblyjs/helper-api-error@1.11.6: + resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==} + dev: true + + /@webassemblyjs/helper-buffer@1.11.1: + resolution: {integrity: sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==} + dev: true + + /@webassemblyjs/helper-buffer@1.11.6: + resolution: {integrity: sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==} + dev: true + + /@webassemblyjs/helper-numbers@1.11.1: + resolution: {integrity: sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==} + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.11.1 + '@webassemblyjs/helper-api-error': 1.11.1 + '@xtuc/long': 4.2.2 + dev: true + + /@webassemblyjs/helper-numbers@1.11.6: + resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==} + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.11.6 + '@webassemblyjs/helper-api-error': 1.11.6 + '@xtuc/long': 4.2.2 + dev: true + + /@webassemblyjs/helper-wasm-bytecode@1.11.1: + resolution: {integrity: sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==} + dev: true + + /@webassemblyjs/helper-wasm-bytecode@1.11.6: + resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==} + dev: true + + /@webassemblyjs/helper-wasm-section@1.11.1: + resolution: {integrity: sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==} + dependencies: + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/helper-buffer': 1.11.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.1 + '@webassemblyjs/wasm-gen': 1.11.1 + dev: true + + /@webassemblyjs/helper-wasm-section@1.11.6: + resolution: {integrity: sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-buffer': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/wasm-gen': 1.11.6 + dev: true + + /@webassemblyjs/ieee754@1.11.1: + resolution: {integrity: sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==} + dependencies: + '@xtuc/ieee754': 1.2.0 + dev: true + + /@webassemblyjs/ieee754@1.11.6: + resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==} + dependencies: + '@xtuc/ieee754': 1.2.0 + dev: true + + /@webassemblyjs/leb128@1.11.1: + resolution: {integrity: sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==} + dependencies: + '@xtuc/long': 4.2.2 + dev: true + + /@webassemblyjs/leb128@1.11.6: + resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==} + dependencies: + '@xtuc/long': 4.2.2 + dev: true + + /@webassemblyjs/utf8@1.11.1: + resolution: {integrity: sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==} + dev: true + + /@webassemblyjs/utf8@1.11.6: + resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==} + dev: true + + /@webassemblyjs/wasm-edit@1.11.1: + resolution: {integrity: sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==} + dependencies: + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/helper-buffer': 1.11.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.1 + '@webassemblyjs/helper-wasm-section': 1.11.1 + '@webassemblyjs/wasm-gen': 1.11.1 + '@webassemblyjs/wasm-opt': 1.11.1 + '@webassemblyjs/wasm-parser': 1.11.1 + '@webassemblyjs/wast-printer': 1.11.1 + dev: true + + /@webassemblyjs/wasm-edit@1.11.6: + resolution: {integrity: sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-buffer': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/helper-wasm-section': 1.11.6 + '@webassemblyjs/wasm-gen': 1.11.6 + '@webassemblyjs/wasm-opt': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + '@webassemblyjs/wast-printer': 1.11.6 + dev: true + + /@webassemblyjs/wasm-gen@1.11.1: + resolution: {integrity: sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==} + dependencies: + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.1 + '@webassemblyjs/ieee754': 1.11.1 + '@webassemblyjs/leb128': 1.11.1 + '@webassemblyjs/utf8': 1.11.1 + dev: true + + /@webassemblyjs/wasm-gen@1.11.6: + resolution: {integrity: sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 + dev: true + + /@webassemblyjs/wasm-opt@1.11.1: + resolution: {integrity: sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==} + dependencies: + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/helper-buffer': 1.11.1 + '@webassemblyjs/wasm-gen': 1.11.1 + '@webassemblyjs/wasm-parser': 1.11.1 + dev: true + + /@webassemblyjs/wasm-opt@1.11.6: + resolution: {integrity: sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-buffer': 1.11.6 + '@webassemblyjs/wasm-gen': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + dev: true + + /@webassemblyjs/wasm-parser@1.11.1: + resolution: {integrity: sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==} + dependencies: + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/helper-api-error': 1.11.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.1 + '@webassemblyjs/ieee754': 1.11.1 + '@webassemblyjs/leb128': 1.11.1 + '@webassemblyjs/utf8': 1.11.1 + dev: true + + /@webassemblyjs/wasm-parser@1.11.6: + resolution: {integrity: sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-api-error': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 + dev: true + + /@webassemblyjs/wast-printer@1.11.1: + resolution: {integrity: sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==} + dependencies: + '@webassemblyjs/ast': 1.11.1 + '@xtuc/long': 4.2.2 + dev: true + + /@webassemblyjs/wast-printer@1.11.6: + resolution: {integrity: sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@xtuc/long': 4.2.2 + dev: true + + /@webpack-cli/configtest@2.1.1(webpack-cli@5.0.2)(webpack@5.75.0): + resolution: {integrity: sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==} + engines: {node: '>=14.15.0'} + peerDependencies: + webpack: 5.x.x + webpack-cli: 5.x.x + dependencies: + webpack: 5.75.0(webpack-cli@5.0.2) + webpack-cli: 5.0.2(webpack-bundle-analyzer@4.8.0)(webpack-dev-server@4.13.3)(webpack@5.75.0) + dev: true + + /@webpack-cli/info@2.0.2(webpack-cli@5.0.2)(webpack@5.75.0): + resolution: {integrity: sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==} + engines: {node: '>=14.15.0'} + peerDependencies: + webpack: 5.x.x + webpack-cli: 5.x.x + dependencies: + webpack: 5.75.0(webpack-cli@5.0.2) + webpack-cli: 5.0.2(webpack-bundle-analyzer@4.8.0)(webpack-dev-server@4.13.3)(webpack@5.75.0) + dev: true + + /@webpack-cli/serve@2.0.5(webpack-cli@5.0.2)(webpack-dev-server@4.13.3)(webpack@5.75.0): + resolution: {integrity: sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==} + engines: {node: '>=14.15.0'} + peerDependencies: + webpack: 5.x.x + webpack-cli: 5.x.x + webpack-dev-server: '*' + peerDependenciesMeta: + webpack-dev-server: + optional: true + dependencies: + webpack: 5.75.0(webpack-cli@5.0.2) + webpack-cli: 5.0.2(webpack-bundle-analyzer@4.8.0)(webpack-dev-server@4.13.3)(webpack@5.75.0) + webpack-dev-server: 4.13.3(webpack-cli@5.0.2)(webpack@5.75.0) + dev: true + + /@xtuc/ieee754@1.2.0: + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + dev: true + + /@xtuc/long@4.2.2: + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + dev: true + + /@zeit/schemas@2.29.0: + resolution: {integrity: sha512-g5QiLIfbg3pLuYUJPlisNKY+epQJTcMDsOnVNkscrDP1oi7vmJnzOANYJI/1pZcVJ6umUkBv3aFtlg1UvUHGzA==} + dev: true + + /@zxing/text-encoding@0.9.0: + resolution: {integrity: sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==} + requiresBuild: true + dev: false + optional: true + + /abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + dev: false + + /accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + /acorn-import-assertions@1.9.0(acorn@8.10.0): + resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} + peerDependencies: + acorn: ^8 + dependencies: + acorn: 8.10.0 + dev: true + + /acorn-jsx@5.3.2(acorn@8.10.0): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.10.0 + dev: true + + /acorn-walk@8.2.0: + resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + engines: {node: '>=0.4.0'} + + /acorn@8.10.0: + resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} + engines: {node: '>=0.4.0'} + hasBin: true + + /address@1.2.2: + resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} + engines: {node: '>= 10.0.0'} + dev: false + + /agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + + /ajv-formats@2.1.1(ajv@8.11.0): + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + dependencies: + ajv: 8.11.0 + dev: true + + /ajv-formats@2.1.1(ajv@8.12.0): + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + dependencies: + ajv: 8.12.0 + dev: true + + /ajv-keywords@3.5.2(ajv@6.12.6): + resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} + peerDependencies: + ajv: ^6.9.1 + dependencies: + ajv: 6.12.6 + dev: true + + /ajv-keywords@5.1.0(ajv@8.12.0): + resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} + peerDependencies: + ajv: ^8.8.2 + dependencies: + ajv: 8.12.0 + fast-deep-equal: 3.1.3 + dev: true + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ajv@8.11.0: + resolution: {integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==} + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + dev: true + + /ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + dev: true + + /ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + dependencies: + string-width: 4.2.3 + dev: true + + /ansi-colors@4.1.1: + resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} + engines: {node: '>=6'} + dev: true + + /ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + dev: true + + /ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: true + + /ansi-html-community@0.0.8: + resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} + engines: {'0': node >= 0.8.0} + hasBin: true + dev: true + + /ansi-regex@2.1.1: + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + engines: {node: '>=0.10.0'} + dev: true + + /ansi-regex@3.0.1: + resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==} + engines: {node: '>=4'} + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + /ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: true + + /ansi-styles@2.2.1: + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} + engines: {node: '>=0.10.0'} + dev: true + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: true + + /antd@5.6.4(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-ttAN5vk6yUybDCe5WFloEb49dyLwyec+FJlvopfZFSkScHX2OBbfpPlCQ50Bpp2u5P/eqN6EQUM4PsE4MPslAA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@ant-design/colors': 7.0.0 + '@ant-design/cssinjs': 1.16.1(react-dom@18.2.0)(react@18.2.0) + '@ant-design/icons': 5.2.5(react-dom@18.2.0)(react@18.2.0) + '@ant-design/react-slick': 1.0.2(react@18.2.0) + '@babel/runtime': 7.22.6 + '@ctrl/tinycolor': 3.6.0 + '@rc-component/color-picker': 1.2.0(react-dom@18.2.0)(react@18.2.0) + '@rc-component/mutate-observer': 1.0.0(react-dom@18.2.0)(react@18.2.0) + '@rc-component/tour': 1.8.1(react-dom@18.2.0)(react@18.2.0) + '@rc-component/trigger': 1.15.1(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + copy-to-clipboard: 3.3.3 + dayjs: 1.11.9 + qrcode.react: 3.1.0(react@18.2.0) + rc-cascader: 3.12.1(react-dom@18.2.0)(react@18.2.0) + rc-checkbox: 3.1.0(react-dom@18.2.0)(react@18.2.0) + rc-collapse: 3.7.1(react-dom@18.2.0)(react@18.2.0) + rc-dialog: 9.1.0(react-dom@18.2.0)(react@18.2.0) + rc-drawer: 6.2.0(react-dom@18.2.0)(react@18.2.0) + rc-dropdown: 4.1.0(react-dom@18.2.0)(react@18.2.0) + rc-field-form: 1.34.2(react-dom@18.2.0)(react@18.2.0) + rc-image: 5.17.1(react-dom@18.2.0)(react@18.2.0) + rc-input: 1.0.4(react-dom@18.2.0)(react@18.2.0) + rc-input-number: 7.4.2(react-dom@18.2.0)(react@18.2.0) + rc-mentions: 2.3.0(react-dom@18.2.0)(react@18.2.0) + rc-menu: 9.9.2(react-dom@18.2.0)(react@18.2.0) + rc-motion: 2.7.3(react-dom@18.2.0)(react@18.2.0) + rc-notification: 5.0.5(react-dom@18.2.0)(react@18.2.0) + rc-pagination: 3.5.0(react-dom@18.2.0)(react@18.2.0) + rc-picker: 3.8.2(dayjs@1.11.9)(react-dom@18.2.0)(react@18.2.0) + rc-progress: 3.4.2(react-dom@18.2.0)(react@18.2.0) + rc-rate: 2.12.0(react-dom@18.2.0)(react@18.2.0) + rc-resize-observer: 1.3.1(react-dom@18.2.0)(react@18.2.0) + rc-segmented: 2.2.2(react-dom@18.2.0)(react@18.2.0) + rc-select: 14.5.2(react-dom@18.2.0)(react@18.2.0) + rc-slider: 10.1.1(react-dom@18.2.0)(react@18.2.0) + rc-steps: 6.0.1(react-dom@18.2.0)(react@18.2.0) + rc-switch: 4.1.0(react-dom@18.2.0)(react@18.2.0) + rc-table: 7.32.1(react-dom@18.2.0)(react@18.2.0) + rc-tabs: 12.7.1(react-dom@18.2.0)(react@18.2.0) + rc-textarea: 1.2.3(react-dom@18.2.0)(react@18.2.0) + rc-tooltip: 6.0.1(react-dom@18.2.0)(react@18.2.0) + rc-tree: 5.7.9(react-dom@18.2.0)(react@18.2.0) + rc-tree-select: 5.9.0(react-dom@18.2.0)(react@18.2.0) + rc-upload: 4.3.4(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + scroll-into-view-if-needed: 3.0.10 + throttle-debounce: 5.0.0 + transitivePeerDependencies: + - date-fns + - luxon + - moment + dev: false + + /antd@5.8.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-kkC2BSBde1JzJxk2wNYj/NXgNZQZ2yu6avJoCKleSi32nsjiadi7FFu1AyGxIzoJ9CrxoLacjGvrwbKJQ6kCvw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@ant-design/colors': 7.0.0 + '@ant-design/cssinjs': 1.16.1(react-dom@18.2.0)(react@18.2.0) + '@ant-design/icons': 5.2.5(react-dom@18.2.0)(react@18.2.0) + '@ant-design/react-slick': 1.0.2(react@18.2.0) + '@babel/runtime': 7.22.6 + '@ctrl/tinycolor': 3.6.0 + '@rc-component/color-picker': 1.4.1(react-dom@18.2.0)(react@18.2.0) + '@rc-component/mutate-observer': 1.0.0(react-dom@18.2.0)(react@18.2.0) + '@rc-component/tour': 1.8.1(react-dom@18.2.0)(react@18.2.0) + '@rc-component/trigger': 1.15.1(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + copy-to-clipboard: 3.3.3 + dayjs: 1.11.9 + qrcode.react: 3.1.0(react@18.2.0) + rc-cascader: 3.14.1(react-dom@18.2.0)(react@18.2.0) + rc-checkbox: 3.1.0(react-dom@18.2.0)(react@18.2.0) + rc-collapse: 3.7.1(react-dom@18.2.0)(react@18.2.0) + rc-dialog: 9.1.0(react-dom@18.2.0)(react@18.2.0) + rc-drawer: 6.2.0(react-dom@18.2.0)(react@18.2.0) + rc-dropdown: 4.1.0(react-dom@18.2.0)(react@18.2.0) + rc-field-form: 1.36.2(react-dom@18.2.0)(react@18.2.0) + rc-image: 7.1.3(react-dom@18.2.0)(react@18.2.0) + rc-input: 1.1.1(react-dom@18.2.0)(react@18.2.0) + rc-input-number: 8.0.4(react-dom@18.2.0)(react@18.2.0) + rc-mentions: 2.5.0(react-dom@18.2.0)(react@18.2.0) + rc-menu: 9.10.0(react-dom@18.2.0)(react@18.2.0) + rc-motion: 2.7.3(react-dom@18.2.0)(react@18.2.0) + rc-notification: 5.0.5(react-dom@18.2.0)(react@18.2.0) + rc-pagination: 3.5.0(react-dom@18.2.0)(react@18.2.0) + rc-picker: 3.12.0(dayjs@1.11.9)(react-dom@18.2.0)(react@18.2.0) + rc-progress: 3.4.2(react-dom@18.2.0)(react@18.2.0) + rc-rate: 2.12.0(react-dom@18.2.0)(react@18.2.0) + rc-resize-observer: 1.3.1(react-dom@18.2.0)(react@18.2.0) + rc-segmented: 2.2.2(react-dom@18.2.0)(react@18.2.0) + rc-select: 14.7.4(react-dom@18.2.0)(react@18.2.0) + rc-slider: 10.1.1(react-dom@18.2.0)(react@18.2.0) + rc-steps: 6.0.1(react-dom@18.2.0)(react@18.2.0) + rc-switch: 4.1.0(react-dom@18.2.0)(react@18.2.0) + rc-table: 7.32.1(react-dom@18.2.0)(react@18.2.0) + rc-tabs: 12.9.0(react-dom@18.2.0)(react@18.2.0) + rc-textarea: 1.3.4(react-dom@18.2.0)(react@18.2.0) + rc-tooltip: 6.0.1(react-dom@18.2.0)(react@18.2.0) + rc-tree: 5.7.9(react-dom@18.2.0)(react@18.2.0) + rc-tree-select: 5.11.1(react-dom@18.2.0)(react@18.2.0) + rc-upload: 4.3.4(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + scroll-into-view-if-needed: 3.0.10 + throttle-debounce: 5.0.0 + transitivePeerDependencies: + - date-fns + - luxon + - moment + dev: false + + /antd@5.8.3(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-/DIGg/1UXyPdNLs9FYalfJO1LnnwMv2pnx9DS6ANSJwlo6fDxtb693IJWdaBuRlxgXJfARzxMNsPyFygy9N/Qw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@ant-design/colors': 7.0.0 + '@ant-design/cssinjs': 1.16.1(react-dom@18.2.0)(react@18.2.0) + '@ant-design/icons': 5.2.5(react-dom@18.2.0)(react@18.2.0) + '@ant-design/react-slick': 1.0.2(react@18.2.0) + '@babel/runtime': 7.22.6 + '@ctrl/tinycolor': 3.6.0 + '@rc-component/color-picker': 1.4.1(react-dom@18.2.0)(react@18.2.0) + '@rc-component/mutate-observer': 1.0.0(react-dom@18.2.0)(react@18.2.0) + '@rc-component/tour': 1.8.1(react-dom@18.2.0)(react@18.2.0) + '@rc-component/trigger': 1.15.1(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + copy-to-clipboard: 3.3.3 + dayjs: 1.11.9 + qrcode.react: 3.1.0(react@18.2.0) + rc-cascader: 3.14.1(react-dom@18.2.0)(react@18.2.0) + rc-checkbox: 3.1.0(react-dom@18.2.0)(react@18.2.0) + rc-collapse: 3.7.1(react-dom@18.2.0)(react@18.2.0) + rc-dialog: 9.1.0(react-dom@18.2.0)(react@18.2.0) + rc-drawer: 6.2.0(react-dom@18.2.0)(react@18.2.0) + rc-dropdown: 4.1.0(react-dom@18.2.0)(react@18.2.0) + rc-field-form: 1.36.2(react-dom@18.2.0)(react@18.2.0) + rc-image: 7.1.3(react-dom@18.2.0)(react@18.2.0) + rc-input: 1.1.1(react-dom@18.2.0)(react@18.2.0) + rc-input-number: 8.0.4(react-dom@18.2.0)(react@18.2.0) + rc-mentions: 2.5.0(react-dom@18.2.0)(react@18.2.0) + rc-menu: 9.10.0(react-dom@18.2.0)(react@18.2.0) + rc-motion: 2.7.3(react-dom@18.2.0)(react@18.2.0) + rc-notification: 5.0.5(react-dom@18.2.0)(react@18.2.0) + rc-pagination: 3.5.0(react-dom@18.2.0)(react@18.2.0) + rc-picker: 3.13.0(dayjs@1.11.9)(react-dom@18.2.0)(react@18.2.0) + rc-progress: 3.4.2(react-dom@18.2.0)(react@18.2.0) + rc-rate: 2.12.0(react-dom@18.2.0)(react@18.2.0) + rc-resize-observer: 1.3.1(react-dom@18.2.0)(react@18.2.0) + rc-segmented: 2.2.2(react-dom@18.2.0)(react@18.2.0) + rc-select: 14.7.4(react-dom@18.2.0)(react@18.2.0) + rc-slider: 10.1.1(react-dom@18.2.0)(react@18.2.0) + rc-steps: 6.0.1(react-dom@18.2.0)(react@18.2.0) + rc-switch: 4.1.0(react-dom@18.2.0)(react@18.2.0) + rc-table: 7.32.1(react-dom@18.2.0)(react@18.2.0) + rc-tabs: 12.9.0(react-dom@18.2.0)(react@18.2.0) + rc-textarea: 1.3.4(react-dom@18.2.0)(react@18.2.0) + rc-tooltip: 6.0.1(react-dom@18.2.0)(react@18.2.0) + rc-tree: 5.7.9(react-dom@18.2.0)(react@18.2.0) + rc-tree-select: 5.11.1(react-dom@18.2.0)(react@18.2.0) + rc-upload: 4.3.4(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + scroll-into-view-if-needed: 3.0.10 + throttle-debounce: 5.0.0 + transitivePeerDependencies: + - date-fns + - luxon + - moment + dev: false + + /any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + dev: false + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /app-root-path@3.1.0: + resolution: {integrity: sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==} + engines: {node: '>= 6.0.0'} + dev: false + + /append-field@1.0.0: + resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==} + + /aproba@2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + dev: false + + /arch@2.2.0: + resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} + dev: true + + /are-we-there-yet@2.0.0: + resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} + engines: {node: '>=10'} + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.2 + dev: false + + /arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + /arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + dev: true + + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: true + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + /array-buffer-byte-length@1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + dependencies: + call-bind: 1.0.2 + is-array-buffer: 3.0.2 + dev: true + + /array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + /array-flatten@2.1.2: + resolution: {integrity: sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==} + dev: true + + /array-timsort@1.0.3: + resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} + dev: true + + /array-tree-filter@2.1.0: + resolution: {integrity: sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==} + dev: false + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /array.prototype.flat@1.3.1: + resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + es-shim-unscopables: 1.0.0 + dev: true + + /arraybuffer.prototype.slice@1.0.1: + resolution: {integrity: sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + call-bind: 1.0.2 + define-properties: 1.2.0 + get-intrinsic: 1.2.1 + is-array-buffer: 3.0.2 + is-shared-array-buffer: 1.0.2 + dev: true + + /arrify@1.0.1: + resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} + engines: {node: '>=0.10.0'} + dev: true + + /asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + dev: true + + /async-validator@4.2.5: + resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} + dev: false + + /async@3.2.4: + resolution: {integrity: sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==} + dev: false + + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + /atob@2.1.2: + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} + engines: {node: '>= 4.5.0'} + hasBin: true + dev: false + + /available-typed-arrays@1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + + /await-event@2.1.0: + resolution: {integrity: sha512-hADm2dFnyugZnfFoJ0Oug2T9xAT2gFdvxZXXnWUOFsHL+VTCvj4Q7oBOinUYzvAFeAD5HN1YSrP78iS3/SQ7iQ==} + dev: false + + /await-first@1.0.0: + resolution: {integrity: sha512-SK20HicVu6lXvNM0nS1flurrs4/1NdhvccvEn52Gf+vpERZnnkKBnJvAQDsYkzJnsHs1bRNNKEiobEet7a/0TA==} + engines: {node: '>= 6.0.0'} + dependencies: + ee-first: 1.1.1 + dev: false + + /axios@1.3.6: + resolution: {integrity: sha512-PEcdkk7JcdPiMDkvM4K6ZBRYq9keuVJsToxm2zQIM70Qqo2WHTdJZMXcG9X+RmRp2VPNUQC8W1RAGbgt6b1yMg==} + dependencies: + follow-redirects: 1.15.2 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: false + + /axios@1.4.0: + resolution: {integrity: sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==} + dependencies: + follow-redirects: 1.15.2 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: false + + /babel-loader@9.1.2(@babel/core@7.21.8)(webpack@5.75.0): + resolution: {integrity: sha512-mN14niXW43tddohGl8HPu5yfQq70iUThvFL/4QzESA7GcZoC0eVOhvWdQ8+3UlSjaDE9MVtsW9mxDY07W7VpVA==} + engines: {node: '>= 14.15.0'} + peerDependencies: + '@babel/core': ^7.12.0 + webpack: '>=5' + dependencies: + '@babel/core': 7.21.8 + find-cache-dir: 3.3.2 + schema-utils: 4.2.0 + webpack: 5.75.0(webpack-cli@5.0.2) + dev: true + + /babel-plugin-polyfill-corejs2@0.3.3(@babel/core@7.21.8): + resolution: {integrity: sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.22.9 + '@babel/core': 7.21.8 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.8) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-corejs3@0.6.0(@babel/core@7.21.8): + resolution: {integrity: sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.8) + core-js-compat: 3.32.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-regenerator@0.4.1(@babel/core@7.21.8): + resolution: {integrity: sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.8) + transitivePeerDependencies: + - supports-color + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + /base64-arraybuffer@1.0.2: + resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==} + engines: {node: '>= 0.6.0'} + dev: false + + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + /batch@0.6.1: + resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} + dev: true + + /bcrypt@5.1.0: + resolution: {integrity: sha512-RHBS7HI5N5tEnGTmtR/pppX0mmDSBpQ4aCBsj7CEQfYXDcO74A8sIBYcJMuCsis2E81zDxeENYhv66oZwLiA+Q==} + engines: {node: '>= 10.0.0'} + requiresBuild: true + dependencies: + '@mapbox/node-pre-gyp': 1.0.11 + node-addon-api: 5.1.0 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /better-path-resolve@1.0.0: + resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} + engines: {node: '>=4'} + dependencies: + is-windows: 1.0.2 + dev: true + + /big.js@5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + dev: true + + /binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + + /bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: true + + /block-stream2@2.1.0: + resolution: {integrity: sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==} + dependencies: + readable-stream: 3.6.2 + dev: false + + /body-parser@1.20.0: + resolution: {integrity: sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.10.3 + raw-body: 2.5.1 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /body-parser@1.20.1: + resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.1 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + /body-parser@1.20.2: + resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + /bonjour-service@1.1.1: + resolution: {integrity: sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==} + dependencies: + array-flatten: 2.1.2 + dns-equal: 1.0.0 + fast-deep-equal: 3.1.3 + multicast-dns: 7.2.5 + dev: true + + /boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + dev: true + + /boxen@7.0.0: + resolution: {integrity: sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==} + engines: {node: '>=14.16'} + dependencies: + ansi-align: 3.0.1 + camelcase: 7.0.1 + chalk: 5.0.1 + cli-boxes: 3.0.0 + string-width: 5.1.2 + type-fest: 2.19.0 + widest-line: 4.0.1 + wrap-ansi: 8.1.0 + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /breakword@1.0.6: + resolution: {integrity: sha512-yjxDAYyK/pBvws9H4xKYpLDpYKEH6CzrBPAuXq3x18I+c/2MkVtT3qAr7Oloi6Dss9qNhPVueAAVU1CSeNDIXw==} + dependencies: + wcwidth: 1.0.1 + dev: true + + /browser-or-node@2.1.1: + resolution: {integrity: sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==} + dev: false + + /browserslist@4.21.10: + resolution: {integrity: sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001518 + electron-to-chromium: 1.4.480 + node-releases: 2.0.13 + update-browserslist-db: 1.0.11(browserslist@4.21.10) + dev: true + + /btoa@1.2.1: + resolution: {integrity: sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==} + engines: {node: '>= 0.4.0'} + hasBin: true + dev: false + + /buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + dev: false + + /buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + dev: false + + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + /buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: true + + /buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + + /builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + dev: true + + /busboy@1.6.0: + resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} + engines: {node: '>=10.16.0'} + dependencies: + streamsearch: 1.1.0 + + /byte@2.0.0: + resolution: {integrity: sha512-rNiK8YxOMvquToaBubKxA10sjRIZ/taDqtc/1jLQA4X7aNDlA1XGx4Ciml3YxL8DskFz1XX3WFskSp0peKYSKg==} + engines: {node: '>= 8.0.0'} + dependencies: + debug: 3.2.7 + long: 4.0.0 + utility: 1.18.0 + transitivePeerDependencies: + - supports-color + dev: false + + /bytes@3.0.0: + resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} + engines: {node: '>= 0.8'} + dev: true + + /bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + /call-bind@1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.2.1 + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camel-case@4.1.2: + resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} + dependencies: + pascal-case: 3.1.2 + tslib: 2.6.0 + dev: true + + /camelcase-keys@6.2.2: + resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} + engines: {node: '>=8'} + dependencies: + camelcase: 5.3.1 + map-obj: 4.3.0 + quick-lru: 4.0.1 + dev: true + + /camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: true + + /camelcase@7.0.1: + resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} + engines: {node: '>=14.16'} + dev: true + + /caniuse-api@3.0.0: + resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} + dependencies: + browserslist: 4.21.10 + caniuse-lite: 1.0.30001518 + lodash.memoize: 4.1.2 + lodash.uniq: 4.5.0 + dev: true + + /caniuse-lite@1.0.30001518: + resolution: {integrity: sha512-rup09/e3I0BKjncL+FesTayKtPrdwKhUufQFd3riFw1hHg8JmIFoInYfB102cFcY/pPgGmdyl/iy+jgiDi2vdA==} + dev: true + + /canvg@3.0.10: + resolution: {integrity: sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==} + engines: {node: '>=10.0.0'} + requiresBuild: true + dependencies: + '@babel/runtime': 7.22.6 + '@types/raf': 3.4.0 + core-js: 3.30.1 + raf: 3.4.1 + regenerator-runtime: 0.13.11 + rgbcolor: 1.0.1 + stackblur-canvas: 2.6.0 + svg-pathdata: 6.0.3 + dev: false + optional: true + + /chalk-template@0.4.0: + resolution: {integrity: sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==} + engines: {node: '>=12'} + dependencies: + chalk: 4.1.2 + dev: true + + /chalk@1.1.3: + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-styles: 2.2.1 + escape-string-regexp: 1.0.5 + has-ansi: 2.0.0 + strip-ansi: 3.0.1 + supports-color: 2.0.0 + dev: true + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + /chalk@3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + /chalk@5.0.1: + resolution: {integrity: sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true + + /chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + dev: true + + /charenc@0.0.2: + resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} + dev: false + + /chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + dev: false + + /chrome-trace-event@1.0.3: + resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} + engines: {node: '>=6.0'} + dev: true + + /ci-info@3.8.0: + resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==} + engines: {node: '>=8'} + dev: true + + /circular-json-for-egg@1.0.0: + resolution: {integrity: sha512-BzMR1dg0+YqcFoMETHq0gFeQNNKliXI1Oe+C0nx/4npLaohsR7/Oj3UFht65MLwF7zs6x13gOr+f4+JeYni6vw==} + dev: false + + /class-transformer@0.5.1: + resolution: {integrity: sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==} + + /class-validator@0.14.0: + resolution: {integrity: sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==} + dependencies: + '@types/validator': 13.9.0 + libphonenumber-js: 1.10.38 + validator: 13.9.0 + + /classnames@2.3.2: + resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==} + dev: false + + /clean-css@5.3.2: + resolution: {integrity: sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==} + engines: {node: '>= 10.0'} + dependencies: + source-map: 0.6.1 + dev: true + + /cli-boxes@3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} + dev: true + + /cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + dependencies: + restore-cursor: 3.1.0 + dev: true + + /cli-highlight@2.1.11: + resolution: {integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==} + engines: {node: '>=8.0.0', npm: '>=5.0.0'} + hasBin: true + dependencies: + chalk: 4.1.2 + highlight.js: 10.7.3 + mz: 2.7.0 + parse5: 5.1.1 + parse5-htmlparser2-tree-adapter: 6.0.1 + yargs: 16.2.0 + dev: false + + /cli-spinners@2.9.0: + resolution: {integrity: sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==} + engines: {node: '>=6'} + dev: true + + /cli-table3@0.6.2: + resolution: {integrity: sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw==} + engines: {node: 10.* || >= 12.*} + dependencies: + string-width: 4.2.3 + optionalDependencies: + '@colors/colors': 1.5.0 + dev: true + + /cli-table3@0.6.3: + resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==} + engines: {node: 10.* || >= 12.*} + dependencies: + string-width: 4.2.3 + optionalDependencies: + '@colors/colors': 1.5.0 + dev: true + + /cli-width@3.0.0: + resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} + engines: {node: '>= 10'} + dev: true + + /clipboardy@3.0.0: + resolution: {integrity: sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + arch: 2.2.0 + execa: 5.1.1 + is-wsl: 2.2.0 + dev: true + + /cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + dev: true + + /cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: false + + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + /clone-deep@4.0.1: + resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} + engines: {node: '>=6'} + dependencies: + is-plain-object: 2.0.4 + kind-of: 6.0.3 + shallow-clone: 3.0.1 + dev: true + + /clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + dev: true + + /cluster-client@2.1.2: + resolution: {integrity: sha512-0DdRIA04ws90MTE+w4WfgiTcBoIgk7HX24KpZSqfmUfuUzlsNBlOL7WvupYfpJNAF0lAOknw2DWmPRxP6K0YlQ==} + engines: {node: '>= 8.0.0'} + dependencies: + byte: 2.0.0 + co: 4.6.0 + debug: 4.3.4 + egg-logger: 2.9.1 + is-type-of: 1.4.0 + json-stringify-safe: 5.0.1 + long: 4.0.0 + mz-modules: 2.1.0 + sdk-base: 3.6.0 + serialize-json: 1.0.3 + tcp-base: 3.1.1 + utility: 1.18.0 + transitivePeerDependencies: + - supports-color + dev: false + + /cluster-key-slot@1.1.2: + resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} + engines: {node: '>=0.10.0'} + + /co-gather@1.0.1: + resolution: {integrity: sha512-f3v1koF5sPfFhmI901quN9dwvHz02swCOqoAFi/DmODKARIMyOEdrUxIyAxYBS8nxf+WcbXPHrjcnel1A5suIw==} + dependencies: + co: 4.6.0 + dev: false + + /co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + dev: false + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + /color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + dev: false + + /colord@2.9.3: + resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} + dev: true + + /colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + dev: true + + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + + /commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + dev: true + + /commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + dev: true + + /commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + dev: true + + /commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + dev: true + + /commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + dev: true + + /commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + dev: true + + /comment-json@4.2.3: + resolution: {integrity: sha512-SsxdiOf064DWoZLH799Ata6u7iV658A11PlWtZATDlXPpKGJnbJZ5Z24ybixAi+LUUqJ/GKowAejtC5GFUG7Tw==} + engines: {node: '>= 6'} + dependencies: + array-timsort: 1.0.3 + core-util-is: 1.0.3 + esprima: 4.0.1 + has-own-prop: 2.0.0 + repeat-string: 1.6.1 + dev: true + + /common-path-prefix@3.0.0: + resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} + dev: true + + /commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + dev: true + + /component-emitter@1.3.0: + resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==} + dev: true + + /compressible@2.0.18: + resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: true + + /compression-webpack-plugin@10.0.0(webpack@5.75.0): + resolution: {integrity: sha512-wLXLIBwpul/ALcm7Aj+69X0pYT3BYt6DdPn3qrgBIh9YejV9Bju9ShhlAsjujLyWMo6SAweFIWaUoFmXZNuNrg==} + engines: {node: '>= 14.15.0'} + peerDependencies: + webpack: ^5.1.0 + dependencies: + schema-utils: 4.2.0 + serialize-javascript: 6.0.1 + webpack: 5.75.0(webpack-cli@5.0.2) + dev: true + + /compression@1.7.4: + resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==} + engines: {node: '>= 0.8.0'} + dependencies: + accepts: 1.3.8 + bytes: 3.0.0 + compressible: 2.0.18 + debug: 2.6.9 + on-headers: 1.0.2 + safe-buffer: 5.1.2 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /compute-scroll-into-view@3.0.3: + resolution: {integrity: sha512-nadqwNxghAGTamwIqQSG433W6OADZx2vCo3UXHNrzTRHK/htu+7+L0zhjEoaeaQVNAi3YgqWDv8+tzf0hRfR+A==} + dev: false + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + /concat-stream@1.6.2: + resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} + engines: {'0': node >= 0.8} + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 2.3.8 + typedarray: 0.0.6 + + /connect-history-api-fallback@2.0.0: + resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==} + engines: {node: '>=0.8'} + dev: true + + /consola@2.15.3: + resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} + + /console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + dev: false + + /content-disposition@0.5.2: + resolution: {integrity: sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==} + engines: {node: '>= 0.6'} + dev: true + + /content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.2.1 + + /content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + /convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + dev: true + + /cookie-parser@1.4.6: + resolution: {integrity: sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==} + engines: {node: '>= 0.8.0'} + dependencies: + cookie: 0.4.1 + cookie-signature: 1.0.6 + dev: false + + /cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + + /cookie@0.4.1: + resolution: {integrity: sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==} + engines: {node: '>= 0.6'} + dev: false + + /cookie@0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + + /cookiejar@2.1.4: + resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==} + dev: true + + /copy-anything@2.0.6: + resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} + dependencies: + is-what: 3.14.1 + dev: true + + /copy-to-clipboard@3.3.3: + resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} + dependencies: + toggle-selection: 1.0.6 + dev: false + + /copy-to@2.0.1: + resolution: {integrity: sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w==} + dev: false + + /copy-webpack-plugin@11.0.0(webpack@5.75.0): + resolution: {integrity: sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==} + engines: {node: '>= 14.15.0'} + peerDependencies: + webpack: ^5.1.0 + dependencies: + fast-glob: 3.3.1 + glob-parent: 6.0.2 + globby: 13.2.2 + normalize-path: 3.0.0 + schema-utils: 4.2.0 + serialize-javascript: 6.0.1 + webpack: 5.75.0(webpack-cli@5.0.2) + dev: true + + /core-js-compat@3.32.0: + resolution: {integrity: sha512-7a9a3D1k4UCVKnLhrgALyFcP7YCsLOQIxPd0dKjf/6GuPcgyiGP70ewWdCGrSK7evyhymi0qO4EqCmSJofDeYw==} + dependencies: + browserslist: 4.21.10 + dev: true + + /core-js-pure@3.32.0: + resolution: {integrity: sha512-qsev1H+dTNYpDUEURRuOXMvpdtAnNEvQWS/FMJ2Vb5AY8ZP4rAPQldkE27joykZPJTe0+IVgHZYh1P5Xu1/i1g==} + requiresBuild: true + dev: true + + /core-js@3.30.1: + resolution: {integrity: sha512-ZNS5nbiSwDTq4hFosEDqm65izl2CWmLz0hARJMyNQBgkUZMIF51cQiMvIQKA6hvuaeWxQDP3hEedM1JZIgTldQ==} + requiresBuild: true + + /core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + /cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + /cosmiconfig@7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + dependencies: + '@types/parse-json': 4.0.0 + import-fresh: 3.3.0 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + dev: true + + /create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + /cross-env@6.0.0: + resolution: {integrity: sha512-G/B6gtkjgthT8AP/xN1wdj5Xe18fVyk58JepK8GxpUbqcz3hyWxegocMbvnZK+KoTslwd0ACZ3woi/DVUdVjyQ==} + engines: {node: '>=8.0'} + hasBin: true + dependencies: + cross-spawn: 7.0.3 + dev: true + + /cross-env@7.0.3: + resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} + engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} + hasBin: true + dependencies: + cross-spawn: 7.0.3 + dev: false + + /cross-fetch@3.1.6: + resolution: {integrity: sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g==} + dependencies: + node-fetch: 2.6.12 + transitivePeerDependencies: + - encoding + dev: false + + /cross-spawn@5.1.0: + resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + dependencies: + lru-cache: 4.1.5 + shebang-command: 1.2.0 + which: 1.3.1 + dev: true + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + /crypt@0.0.2: + resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} + dev: false + + /crypto-js@4.1.1: + resolution: {integrity: sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==} + dev: false + + /css-declaration-sorter@6.4.1(postcss@8.4.27): + resolution: {integrity: sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==} + engines: {node: ^10 || ^12 || >=14} + peerDependencies: + postcss: ^8.0.9 + dependencies: + postcss: 8.4.27 + dev: true + + /css-line-break@2.1.0: + resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==} + dependencies: + utrie: 1.0.2 + dev: false + + /css-loader@6.7.3(webpack@5.75.0): + resolution: {integrity: sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + dependencies: + icss-utils: 5.1.0(postcss@8.4.27) + postcss: 8.4.27 + postcss-modules-extract-imports: 3.0.0(postcss@8.4.27) + postcss-modules-local-by-default: 4.0.3(postcss@8.4.27) + postcss-modules-scope: 3.0.0(postcss@8.4.27) + postcss-modules-values: 4.0.0(postcss@8.4.27) + postcss-value-parser: 4.2.0 + semver: 7.5.4 + webpack: 5.75.0(webpack-cli@5.0.2) + dev: true + + /css-minimizer-webpack-plugin@5.0.0(webpack@5.75.0): + resolution: {integrity: sha512-1wZ/PYvg+ZKwi5FX6YrvbB31jMAdurS+CmRQLwWCVSlfzJC85l/a6RVICqUHFa+jXyhilfnCyjafzJGbmz5tcA==} + engines: {node: '>= 14.15.0'} + peerDependencies: + '@parcel/css': '*' + '@swc/css': '*' + clean-css: '*' + csso: '*' + esbuild: '*' + lightningcss: '*' + webpack: ^5.0.0 + peerDependenciesMeta: + '@parcel/css': + optional: true + '@swc/css': + optional: true + clean-css: + optional: true + csso: + optional: true + esbuild: + optional: true + lightningcss: + optional: true + dependencies: + cssnano: 6.0.1(postcss@8.4.27) + jest-worker: 29.6.2 + postcss: 8.4.27 + schema-utils: 4.2.0 + serialize-javascript: 6.0.1 + source-map: 0.6.1 + webpack: 5.75.0(webpack-cli@5.0.2) + dev: true + + /css-select@4.3.0: + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 4.3.1 + domutils: 2.8.0 + nth-check: 2.1.1 + dev: true + + /css-select@5.1.0: + resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 5.0.3 + domutils: 3.1.0 + nth-check: 2.1.1 + dev: true + + /css-tree@2.2.1: + resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + dependencies: + mdn-data: 2.0.28 + source-map-js: 1.0.2 + dev: true + + /css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.0.2 + dev: true + + /css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + dev: true + + /cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /cssnano-preset-default@6.0.1(postcss@8.4.27): + resolution: {integrity: sha512-7VzyFZ5zEB1+l1nToKyrRkuaJIx0zi/1npjvZfbBwbtNTzhLtlvYraK/7/uqmX2Wb2aQtd983uuGw79jAjLSuQ==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + css-declaration-sorter: 6.4.1(postcss@8.4.27) + cssnano-utils: 4.0.0(postcss@8.4.27) + postcss: 8.4.27 + postcss-calc: 9.0.1(postcss@8.4.27) + postcss-colormin: 6.0.0(postcss@8.4.27) + postcss-convert-values: 6.0.0(postcss@8.4.27) + postcss-discard-comments: 6.0.0(postcss@8.4.27) + postcss-discard-duplicates: 6.0.0(postcss@8.4.27) + postcss-discard-empty: 6.0.0(postcss@8.4.27) + postcss-discard-overridden: 6.0.0(postcss@8.4.27) + postcss-merge-longhand: 6.0.0(postcss@8.4.27) + postcss-merge-rules: 6.0.1(postcss@8.4.27) + postcss-minify-font-values: 6.0.0(postcss@8.4.27) + postcss-minify-gradients: 6.0.0(postcss@8.4.27) + postcss-minify-params: 6.0.0(postcss@8.4.27) + postcss-minify-selectors: 6.0.0(postcss@8.4.27) + postcss-normalize-charset: 6.0.0(postcss@8.4.27) + postcss-normalize-display-values: 6.0.0(postcss@8.4.27) + postcss-normalize-positions: 6.0.0(postcss@8.4.27) + postcss-normalize-repeat-style: 6.0.0(postcss@8.4.27) + postcss-normalize-string: 6.0.0(postcss@8.4.27) + postcss-normalize-timing-functions: 6.0.0(postcss@8.4.27) + postcss-normalize-unicode: 6.0.0(postcss@8.4.27) + postcss-normalize-url: 6.0.0(postcss@8.4.27) + postcss-normalize-whitespace: 6.0.0(postcss@8.4.27) + postcss-ordered-values: 6.0.0(postcss@8.4.27) + postcss-reduce-initial: 6.0.0(postcss@8.4.27) + postcss-reduce-transforms: 6.0.0(postcss@8.4.27) + postcss-svgo: 6.0.0(postcss@8.4.27) + postcss-unique-selectors: 6.0.0(postcss@8.4.27) + dev: true + + /cssnano-utils@4.0.0(postcss@8.4.27): + resolution: {integrity: sha512-Z39TLP+1E0KUcd7LGyF4qMfu8ZufI0rDzhdyAMsa/8UyNUU8wpS0fhdBxbQbv32r64ea00h4878gommRVg2BHw==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + dev: true + + /cssnano@6.0.1(postcss@8.4.27): + resolution: {integrity: sha512-fVO1JdJ0LSdIGJq68eIxOqFpIJrZqXUsBt8fkrBcztCQqAjQD51OhZp7tc0ImcbwXD4k7ny84QTV90nZhmqbkg==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + cssnano-preset-default: 6.0.1(postcss@8.4.27) + lilconfig: 2.1.0 + postcss: 8.4.27 + dev: true + + /csso@5.0.5: + resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + dependencies: + css-tree: 2.2.1 + dev: true + + /csstype@3.1.2: + resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} + + /csv-generate@3.4.3: + resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==} + dev: true + + /csv-parse@4.16.3: + resolution: {integrity: sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==} + dev: true + + /csv-stringify@5.6.5: + resolution: {integrity: sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==} + dev: true + + /csv@5.5.3: + resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==} + engines: {node: '>= 0.1.90'} + dependencies: + csv-generate: 3.4.3 + csv-parse: 4.16.3 + csv-stringify: 5.6.5 + stream-transform: 2.1.3 + dev: true + + /date-fns@2.30.0: + resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} + engines: {node: '>=0.11'} + dependencies: + '@babel/runtime': 7.22.6 + dev: false + + /dayjs@1.11.9: + resolution: {integrity: sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==} + dev: false + + /debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + + /decamelize-keys@1.1.1: + resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} + engines: {node: '>=0.10.0'} + dependencies: + decamelize: 1.2.0 + map-obj: 1.0.1 + dev: true + + /decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + dev: true + + /decode-uri-component@0.2.2: + resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} + engines: {node: '>=0.10'} + dev: false + + /deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + dev: true + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + dev: true + + /default-gateway@6.0.3: + resolution: {integrity: sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==} + engines: {node: '>= 10'} + dependencies: + execa: 5.1.1 + dev: true + + /default-user-agent@1.0.0: + resolution: {integrity: sha512-bDF7bg6OSNcSwFWPu4zYKpVkJZQYVrAANMYB8bc9Szem1D0yKdm4sa/rOCs2aC9+2GMqQ7KnwtZRvDhmLF0dXw==} + engines: {node: '>= 0.10.0'} + dependencies: + os-name: 1.0.3 + dev: false + + /defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + dependencies: + clone: 1.0.4 + dev: true + + /define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + dev: true + + /define-properties@1.2.0: + resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} + engines: {node: '>= 0.4'} + dependencies: + has-property-descriptors: 1.0.0 + object-keys: 1.1.1 + dev: true + + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + /delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + dev: false + + /denque@2.1.0: + resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} + engines: {node: '>=0.10'} + + /depd@1.1.2: + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} + dev: true + + /depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + /destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + /detect-indent@6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + dev: true + + /detect-libc@2.0.2: + resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} + engines: {node: '>=8'} + dev: false + + /detect-node@2.1.0: + resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + dev: true + + /dezalgo@1.0.4: + resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} + dependencies: + asap: 2.0.6 + wrappy: 1.0.2 + dev: true + + /dicom-parser@1.8.21: + resolution: {integrity: sha512-lYCweHQDsC8UFpXErPlg86Px2A8bay0HiUY+wzoG3xv5GzgqVHU3lziwSc/Gzn7VV7y2KeP072SzCviuOoU02w==} + dev: false + + /diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + + /digest-header@1.1.0: + resolution: {integrity: sha512-glXVh42vz40yZb9Cq2oMOt70FIoWiv+vxNvdKdU8CwjLad25qHM3trLxhl9bVjdr6WaslIXhWpn0NO8T/67Qjg==} + engines: {node: '>= 8.0.0'} + dev: false + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /dns-equal@1.0.0: + resolution: {integrity: sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==} + dev: true + + /dns-packet@5.6.0: + resolution: {integrity: sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ==} + engines: {node: '>=6'} + dependencies: + '@leichtgewicht/ip-codec': 2.0.4 + dev: true + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /dom-align@1.12.4: + resolution: {integrity: sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==} + dev: false + + /dom-converter@0.2.0: + resolution: {integrity: sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==} + dependencies: + utila: 0.4.0 + dev: true + + /dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + dev: true + + /dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + dev: true + + /domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + dev: true + + /domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + dependencies: + domelementtype: 2.3.0 + dev: true + + /domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + dependencies: + domelementtype: 2.3.0 + dev: true + + /dompurify@2.4.7: + resolution: {integrity: sha512-kxxKlPEDa6Nc5WJi+qRgPbOAbgTpSULL+vI3NUXsZMlkJxTqYI9wg5ZTay2sFrdZRWHPWNi+EdAhcJf81WtoMQ==} + requiresBuild: true + dev: false + optional: true + + /domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + dev: true + + /domutils@3.1.0: + resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + dev: true + + /dot-case@3.0.4: + resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.0 + dev: true + + /dotenv-expand@10.0.0: + resolution: {integrity: sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==} + engines: {node: '>=12'} + dev: false + + /dotenv@16.0.3: + resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} + engines: {node: '>=12'} + + /dotenv@16.1.4: + resolution: {integrity: sha512-m55RtE8AsPeJBpOIFKihEmqUcoVncQIwo7x9U8ZwLEZw9ZpXboz2c+rvog+jUaJvVrZ5kBOeYQBX5+8Aa/OZQw==} + engines: {node: '>=12'} + dev: false + + /duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + dev: true + + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true + + /ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + /egg-errors@2.3.2: + resolution: {integrity: sha512-E+Sx7IBVrfRyHSjFXaq4sCZ3Uk3ka9PYySaQ8VbRZmLEt9ENBCD99yVzLIeWUH2QfzvkrjY9El1eHmLeRx7cfw==} + engines: {node: '>=8.9.0'} + dev: false + + /egg-logger@2.9.1: + resolution: {integrity: sha512-TPYdNthc7yGV+08A2U4g1T1wgRAjfTnsYC53JgfdKiYukaH3na1KPXEu+TEWni7IooqkFGkQ0t0WY+ylWFnvbw==} + engines: {node: '>=8.5.0'} + dependencies: + chalk: 2.4.2 + circular-json-for-egg: 1.0.0 + debug: 2.6.9 + depd: 2.0.0 + egg-errors: 2.3.2 + iconv-lite: 0.4.24 + mkdirp: 0.5.6 + utility: 1.18.0 + transitivePeerDependencies: + - supports-color + dev: false + + /electron-to-chromium@1.4.480: + resolution: {integrity: sha512-IXTgg+bITkQv/FLP9FjX6f9KFCs5hQWeh5uNSKxB9mqYj/JXhHDbu+ekS43LVvbkL3eW6/oZy4+r9Om6lan1Uw==} + dev: true + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + + /emojis-list@3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + dev: true + + /encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + /end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + + /enhanced-resolve@5.15.0: + resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + dev: true + + /enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + dev: true + + /entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + dev: true + + /entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + dev: true + + /envinfo@7.10.0: + resolution: {integrity: sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /equals@1.0.5: + resolution: {integrity: sha512-wI15a6ZoaaXPv+55+Vh2Kqn3+efKRv8QPtcGTjW5xmanMnQzESdAt566jevtMZyt3W/jwLDTzXpMph5ECDJ2zg==} + dependencies: + jkroso-type: 1.1.1 + dev: false + + /errno@0.1.8: + resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} + hasBin: true + requiresBuild: true + dependencies: + prr: 1.0.1 + dev: true + optional: true + + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /error-stack-parser@2.1.4: + resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} + dependencies: + stackframe: 1.3.4 + dev: true + + /es-abstract@1.22.1: + resolution: {integrity: sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==} + engines: {node: '>= 0.4'} + 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.12 + 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.11 + dev: true + + /es-module-lexer@0.9.3: + resolution: {integrity: sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==} + dev: true + + /es-module-lexer@1.3.0: + resolution: {integrity: sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==} + dev: true + + /es-set-tostringtag@2.0.1: + resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.1 + has: 1.0.3 + has-tostringtag: 1.0.0 + dev: true + + /es-shim-unscopables@1.0.0: + resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} + dependencies: + has: 1.0.3 + dev: true + + /es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + + /esbuild@0.18.17: + resolution: {integrity: sha512-1GJtYnUxsJreHYA0Y+iQz2UEykonY66HNWOb0yXYZi9/kNrORUEHVg87eQsCtqh59PEJ5YVZJO98JHznMJSWjg==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.18.17 + '@esbuild/android-arm64': 0.18.17 + '@esbuild/android-x64': 0.18.17 + '@esbuild/darwin-arm64': 0.18.17 + '@esbuild/darwin-x64': 0.18.17 + '@esbuild/freebsd-arm64': 0.18.17 + '@esbuild/freebsd-x64': 0.18.17 + '@esbuild/linux-arm': 0.18.17 + '@esbuild/linux-arm64': 0.18.17 + '@esbuild/linux-ia32': 0.18.17 + '@esbuild/linux-loong64': 0.18.17 + '@esbuild/linux-mips64el': 0.18.17 + '@esbuild/linux-ppc64': 0.18.17 + '@esbuild/linux-riscv64': 0.18.17 + '@esbuild/linux-s390x': 0.18.17 + '@esbuild/linux-x64': 0.18.17 + '@esbuild/netbsd-x64': 0.18.17 + '@esbuild/openbsd-x64': 0.18.17 + '@esbuild/sunos-x64': 0.18.17 + '@esbuild/win32-arm64': 0.18.17 + '@esbuild/win32-ia32': 0.18.17 + '@esbuild/win32-x64': 0.18.17 + dev: true + + /escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + + /escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /eslint-config-prettier@8.8.0(eslint@8.44.0): + resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.44.0 + dev: true + + /eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.8.0)(eslint@8.44.0)(prettier@2.8.8): + resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + eslint: '>=7.28.0' + eslint-config-prettier: '*' + prettier: '>=2.0.0' + peerDependenciesMeta: + eslint-config-prettier: + optional: true + dependencies: + eslint: 8.44.0 + eslint-config-prettier: 8.8.0(eslint@8.44.0) + prettier: 2.8.8 + prettier-linter-helpers: 1.0.0 + dev: true + + /eslint-plugin-react-hooks@4.6.0(eslint@8.44.0): + resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} + engines: {node: '>=10'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + dependencies: + eslint: 8.44.0 + dev: true + + /eslint-plugin-react-refresh@0.4.1(eslint@8.44.0): + resolution: {integrity: sha512-QgrvtRJkmV+m4w953LS146+6RwEe5waouubFVNLBfOjXJf6MLczjymO8fOcKj9jMS8aKkTCMJqiPu2WEeFI99A==} + peerDependencies: + eslint: '>=7' + dependencies: + eslint: 8.44.0 + dev: true + + /eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: true + + /eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-visitor-keys@3.4.2: + resolution: {integrity: sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.44.0: + resolution: {integrity: sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.44.0) + '@eslint-community/regexpp': 4.6.2 + '@eslint/eslintrc': 2.1.1 + '@eslint/js': 8.44.0 + '@humanwhocodes/config-array': 0.11.10 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.2 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.20.0 + graphemer: 1.4.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.10.0 + acorn-jsx: 5.3.2(acorn@8.10.0) + eslint-visitor-keys: 3.4.2 + dev: true + + /esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /estree-walker@0.6.1: + resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} + dev: true + + /estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + /eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + dev: true + + /events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + dev: true + + /execa@4.1.0: + resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 5.2.0 + human-signals: 1.1.1 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /express@4.18.1: + resolution: {integrity: sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.0 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.5.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.10.3 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /express@4.18.2: + resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.1 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.5.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.11.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + /extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + dependencies: + is-extendable: 0.1.1 + dev: false + + /extendable-error@0.1.7: + resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} + dev: true + + /external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + dev: true + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + dev: true + + /fast-glob@3.3.1: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + + /fast-url-parser@1.1.3: + resolution: {integrity: sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==} + dependencies: + punycode: 1.4.1 + dev: true + + /fast-xml-parser@4.2.7: + resolution: {integrity: sha512-J8r6BriSLO1uj2miOk1NW0YVm8AGOOu3Si2HQp/cSmo6EA4m3fcwu2WKjJ4RK9wMLBtg69y1kS8baDiQBR41Ig==} + hasBin: true + dependencies: + strnum: 1.0.5 + dev: false + + /fastest-levenshtein@1.0.16: + resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} + engines: {node: '>= 4.9.1'} + dev: true + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: true + + /faye-websocket@0.11.4: + resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} + engines: {node: '>=0.8.0'} + dependencies: + websocket-driver: 0.7.4 + dev: true + + /fflate@0.4.8: + resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==} + dev: false + + /figures@3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.0.4 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /filter-obj@1.1.0: + resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} + engines: {node: '>=0.10.0'} + dev: false + + /finalhandler@1.2.0: + resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + engines: {node: '>= 0.8'} + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + /find-cache-dir@3.3.2: + resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} + engines: {node: '>=8'} + dependencies: + commondir: 1.0.1 + make-dir: 3.1.0 + pkg-dir: 4.2.0 + dev: true + + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /find-yarn-workspace-root2@1.2.16: + resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} + dependencies: + micromatch: 4.0.5 + pkg-dir: 4.2.0 + dev: true + + /flat-cache@3.0.4: + resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.2.7 + rimraf: 3.0.2 + dev: true + + /flatted@3.2.7: + resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} + + /follow-redirects@1.15.2: + resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + + /fork-ts-checker-webpack-plugin@7.2.11(typescript@4.7.4)(webpack@5.73.0): + resolution: {integrity: sha512-2e5+NyTUTE1Xq4fWo7KFEQblCaIvvINQwUX3jRmEGlgCTc1Ecqw/975EfQrQ0GEraxJTnp8KB9d/c8hlCHUMJA==} + engines: {node: '>=12.13.0', yarn: '>=1.0.0'} + peerDependencies: + typescript: '>3.6.0' + vue-template-compiler: '*' + webpack: ^5.11.0 + peerDependenciesMeta: + vue-template-compiler: + optional: true + dependencies: + '@babel/code-frame': 7.22.5 + chalk: 4.1.2 + chokidar: 3.5.3 + cosmiconfig: 7.1.0 + deepmerge: 4.3.1 + fs-extra: 10.1.0 + memfs: 3.5.3 + minimatch: 3.1.2 + schema-utils: 3.3.0 + semver: 7.5.4 + tapable: 2.2.1 + typescript: 4.7.4 + webpack: 5.73.0 + dev: true + + /fork-ts-checker-webpack-plugin@8.0.0(typescript@5.1.3)(webpack@5.87.0): + resolution: {integrity: sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==} + engines: {node: '>=12.13.0', yarn: '>=1.0.0'} + peerDependencies: + typescript: '>3.6.0' + webpack: ^5.11.0 + dependencies: + '@babel/code-frame': 7.22.5 + chalk: 4.1.2 + chokidar: 3.5.3 + cosmiconfig: 7.1.0 + deepmerge: 4.3.1 + fs-extra: 10.1.0 + memfs: 3.5.3 + minimatch: 3.1.2 + node-abort-controller: 3.1.1 + schema-utils: 3.3.0 + semver: 7.5.4 + tapable: 2.2.1 + typescript: 5.1.3 + webpack: 5.87.0 + dev: true + + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + + /formidable@2.1.2: + resolution: {integrity: sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==} + dependencies: + dezalgo: 1.0.4 + hexoid: 1.0.0 + once: 1.4.0 + qs: 6.11.2 + dev: true + + /formstream@1.3.1: + resolution: {integrity: sha512-FkW++ub+VbE5dpwukJVDizNWhSgp8FhmhI65pF7BZSVStBqe6Wgxe2Z9/Vhsn7l7nXCPwP+G1cyYlX8VwWOf0g==} + dependencies: + destroy: 1.2.0 + mime: 2.6.0 + pause-stream: 0.0.11 + dev: false + + /forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + /fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + /friendly-errors-webpack-plugin@1.7.0(webpack@5.75.0): + resolution: {integrity: sha512-K27M3VK30wVoOarP651zDmb93R9zF28usW4ocaK3mfQeIEI5BPht/EzZs5E8QLLwbLRJQMwscAjDxYPb1FuNiw==} + peerDependencies: + webpack: ^2.0.0 || ^3.0.0 || ^4.0.0 + dependencies: + chalk: 1.1.3 + error-stack-parser: 2.1.4 + string-width: 2.1.1 + webpack: 5.75.0(webpack-cli@5.0.2) + dev: true + + /fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: true + + /fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + dev: true + + /fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + dev: true + + /fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: false + + /fs-monkey@1.0.4: + resolution: {integrity: sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==} + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + /fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind@1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + + /function.prototype.name@1.1.5: + resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + functions-have-names: 1.2.3 + dev: true + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /gauge@3.0.2: + resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} + engines: {node: '>=10'} + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + object-assign: 4.1.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + dev: false + + /generate-function@2.3.1: + resolution: {integrity: sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==} + dependencies: + is-property: 1.0.2 + dev: false + + /gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: true + + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + /get-intrinsic@1.2.1: + resolution: {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-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + dependencies: + pump: 3.0.0 + dev: true + + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + + /get-symbol-description@1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + dev: true + + /glob-all@3.3.1: + resolution: {integrity: sha512-Y+ESjdI7ZgMwfzanHZYQ87C59jOO0i+Hd+QYtVt9PhLi6d8wlOpzQnfBxWUlaTuAoR3TkybLqqbIoWveU4Ji7Q==} + hasBin: true + dependencies: + glob: 7.2.3 + yargs: 15.4.1 + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + /glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + + /glob@9.3.5: + resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + fs.realpath: 1.0.0 + minimatch: 8.0.4 + minipass: 4.2.8 + path-scurry: 1.10.1 + dev: true + + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: true + + /globals@13.20.0: + resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.0 + dev: true + + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.1 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /globby@13.2.2: + resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + dir-glob: 3.0.1 + fast-glob: 3.3.1 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 4.0.0 + dev: true + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.1 + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + + /grapheme-splitter@1.0.4: + resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} + dev: true + + /graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true + + /gzip-size@6.0.0: + resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} + engines: {node: '>=10'} + dependencies: + duplexer: 0.1.2 + dev: true + + /handle-thing@2.0.1: + resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} + dev: true + + /hard-rejection@2.1.0: + resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} + engines: {node: '>=6'} + dev: true + + /has-ansi@2.0.0: + resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-regex: 2.1.1 + dev: true + + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + /has-own-prop@2.0.0: + resolution: {integrity: sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==} + engines: {node: '>=8'} + dev: true + + /has-property-descriptors@1.0.0: + resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + dependencies: + get-intrinsic: 1.2.1 + dev: true + + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + /has-tostringtag@1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + + /has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + dev: false + + /has@1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + + /he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + dev: true + + /hexoid@1.0.0: + resolution: {integrity: sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==} + engines: {node: '>=8'} + dev: true + + /highlight.js@10.7.3: + resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} + dev: false + + /hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + dev: true + + /hpack.js@2.1.6: + resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} + dependencies: + inherits: 2.0.4 + obuf: 1.1.2 + readable-stream: 2.3.8 + wbuf: 1.7.3 + dev: true + + /html-entities@2.4.0: + resolution: {integrity: sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==} + dev: true + + /html-minifier-terser@6.1.0: + resolution: {integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==} + engines: {node: '>=12'} + hasBin: true + dependencies: + camel-case: 4.1.2 + clean-css: 5.3.2 + commander: 8.3.0 + he: 1.2.0 + param-case: 3.0.4 + relateurl: 0.2.7 + terser: 5.19.2 + dev: true + + /html-parse-stringify@3.0.1: + resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==} + dependencies: + void-elements: 3.1.0 + dev: false + + /html-webpack-plugin@5.5.1(webpack@5.75.0): + resolution: {integrity: sha512-cTUzZ1+NqjGEKjmVgZKLMdiFg3m9MdRXkZW2OEe69WYVi5ONLMmlnSZdXzGGMOq0C8jGDrL6EWyEDDUioHO/pA==} + engines: {node: '>=10.13.0'} + peerDependencies: + webpack: ^5.20.0 + dependencies: + '@types/html-minifier-terser': 6.1.0 + html-minifier-terser: 6.1.0 + lodash: 4.17.21 + pretty-error: 4.0.0 + tapable: 2.2.1 + webpack: 5.75.0(webpack-cli@5.0.2) + dev: true + + /html2canvas@1.4.1: + resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==} + engines: {node: '>=8.0.0'} + dependencies: + css-line-break: 2.1.0 + text-segmentation: 1.0.3 + dev: false + + /htmlparser2@6.1.0: + resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + domutils: 2.8.0 + entities: 2.2.0 + dev: true + + /http-deceiver@1.2.7: + resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} + dev: true + + /http-errors@1.6.3: + resolution: {integrity: sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==} + engines: {node: '>= 0.6'} + dependencies: + depd: 1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.0 + statuses: 1.5.0 + dev: true + + /http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + + /http-parser-js@0.5.8: + resolution: {integrity: sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==} + dev: true + + /http-proxy-middleware@2.0.6(@types/express@4.17.17): + resolution: {integrity: sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/express': ^4.17.13 + peerDependenciesMeta: + '@types/express': + optional: true + dependencies: + '@types/express': 4.17.17 + '@types/http-proxy': 1.17.11 + http-proxy: 1.18.1 + is-glob: 4.0.3 + is-plain-obj: 3.0.0 + micromatch: 4.0.5 + transitivePeerDependencies: + - debug + dev: true + + /http-proxy@1.18.1: + resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} + engines: {node: '>=8.0.0'} + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.15.2 + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + dev: true + + /https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + + /human-id@1.0.2: + resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} + dev: true + + /human-signals@1.1.1: + resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} + engines: {node: '>=8.12.0'} + dev: true + + /human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: true + + /humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + dependencies: + ms: 2.1.3 + dev: false + + /i18next-browser-languagedetector@7.0.1: + resolution: {integrity: sha512-Pa5kFwaczXJAeHE56CHG2aWzFBMJNUNghf0Pm4SwSrEMps/PTKqW90EYWlIvhuYStf3Sn1K0vw+gH3+TLdkH1g==} + dependencies: + '@babel/runtime': 7.22.6 + dev: false + + /i18next-http-backend@2.2.1: + resolution: {integrity: sha512-ZXIdn/8NJIBJ0X4hzXfc3STYxKrCKh1fYjji9HPyIpEJfvTvy8/ZlTl8RuTizzCPj2ZcWrfaecyOMKs6bQ7u5A==} + dependencies: + cross-fetch: 3.1.6 + transitivePeerDependencies: + - encoding + dev: false + + /i18next@22.5.0: + resolution: {integrity: sha512-sqWuJFj+wJAKQP2qBQ+b7STzxZNUmnSxrehBCCj9vDOW9RDYPfqCaK1Hbh2frNYQuPziz6O2CGoJPwtzY3vAYA==} + dependencies: + '@babel/runtime': 7.22.6 + dev: false + + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + + /iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + + /icss-utils@5.1.0(postcss@8.4.27): + resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + postcss: 8.4.27 + dev: true + + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + /ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + dev: true + + /image-size@0.5.5: + resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} + engines: {node: '>=0.10.0'} + hasBin: true + requiresBuild: true + dev: true + optional: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /import-local@3.1.0: + resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + engines: {node: '>=8'} + hasBin: true + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + /inherits@2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + /ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: true + + /inquirer@7.3.3: + resolution: {integrity: sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==} + engines: {node: '>=8.0.0'} + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + run-async: 2.4.1 + rxjs: 6.6.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + through: 2.3.8 + dev: true + + /inquirer@8.2.4: + resolution: {integrity: sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==} + engines: {node: '>=12.0.0'} + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + ora: 5.4.1 + run-async: 2.4.1 + rxjs: 7.8.1 + string-width: 4.2.3 + strip-ansi: 6.0.1 + through: 2.3.8 + wrap-ansi: 7.0.0 + dev: true + + /inquirer@8.2.5: + resolution: {integrity: sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==} + engines: {node: '>=12.0.0'} + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + ora: 5.4.1 + run-async: 2.4.1 + rxjs: 7.8.1 + string-width: 4.2.3 + strip-ansi: 6.0.1 + through: 2.3.8 + wrap-ansi: 7.0.0 + dev: true + + /internal-slot@1.0.5: + resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.1 + has: 1.0.3 + side-channel: 1.0.4 + dev: true + + /interpret@1.4.0: + resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} + engines: {node: '>= 0.10'} + dev: true + + /interpret@3.1.1: + resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} + engines: {node: '>=10.13.0'} + dev: true + + /ioredis@5.3.2: + resolution: {integrity: sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==} + engines: {node: '>=12.22.0'} + dependencies: + '@ioredis/commands': 1.2.0 + cluster-key-slot: 1.1.2 + debug: 4.3.4 + denque: 2.1.0 + lodash.defaults: 4.2.0 + lodash.isarguments: 3.1.0 + redis-errors: 1.2.0 + redis-parser: 3.0.0 + standard-as-callback: 2.1.0 + transitivePeerDependencies: + - supports-color + + /ip@1.1.8: + resolution: {integrity: sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==} + dev: false + + /ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + /ipaddr.js@2.1.0: + resolution: {integrity: sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==} + engines: {node: '>= 10'} + + /is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: false + + /is-array-buffer@3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-typed-array: 1.1.12 + dev: true + + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: true + + /is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + dev: false + + /is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + dependencies: + builtin-modules: 3.3.0 + dev: true + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + /is-ci@3.0.1: + resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} + hasBin: true + dependencies: + ci-info: 3.8.0 + dev: true + + /is-class-hotfix@0.0.6: + resolution: {integrity: sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ==} + dev: false + + /is-core-module@2.12.1: + resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==} + dependencies: + has: 1.0.3 + dev: true + + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + dev: true + + /is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + dev: false + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-fullwidth-code-point@2.0.0: + resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} + engines: {node: '>=4'} + dev: true + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + /is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: false + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + dev: true + + /is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + dev: true + + /is-negative-zero@2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + dev: true + + /is-plain-obj@3.0.0: + resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} + engines: {node: '>=10'} + dev: true + + /is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: true + + /is-port-reachable@4.0.0: + resolution: {integrity: sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /is-property@1.0.2: + resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==} + dev: false + + /is-reference@1.2.1: + resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + dependencies: + '@types/estree': 1.0.1 + dev: true + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: true + + /is-shared-array-buffer@1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.2 + dev: true + + /is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: true + + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-subdir@1.2.0: + resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} + engines: {node: '>=4'} + dependencies: + better-path-resolve: 1.0.0 + dev: true + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-type-of@1.4.0: + resolution: {integrity: sha512-EddYllaovi5ysMLMEN7yzHEKh8A850cZ7pykrY1aNRQGn/CDjRDE9qEWbIdt7xGEVJmjBXzU/fNnC4ABTm8tEQ==} + dependencies: + core-util-is: 1.0.3 + is-class-hotfix: 0.0.6 + isstream: 0.1.2 + dev: false + + /is-typed-array@1.1.12: + resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.11 + + /is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + dev: true + + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.2 + dev: true + + /is-what@3.14.1: + resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==} + dev: true + + /is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + dev: true + + /is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + dependencies: + is-docker: 2.2.1 + dev: true + + /isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + /isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + dev: true + + /isstream@0.1.2: + resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} + dev: false + + /iterare@1.2.1: + resolution: {integrity: sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==} + engines: {node: '>=6'} + + /jest-util@29.6.2: + resolution: {integrity: sha512-3eX1qb6L88lJNCFlEADKOkjpXJQyZRiavX1INZ4tRnrBVr2COd3RgcTLyUiEXMNBlDU/cgYq6taUS0fExrWW4w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.1 + '@types/node': 20.3.3 + chalk: 4.1.2 + ci-info: 3.8.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + dev: true + + /jest-worker@26.6.2: + resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/node': 20.3.3 + merge-stream: 2.0.0 + supports-color: 7.2.0 + dev: true + + /jest-worker@27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/node': 20.3.3 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: true + + /jest-worker@29.6.2: + resolution: {integrity: sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@types/node': 20.3.3 + jest-util: 29.6.2 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: true + + /jkroso-type@1.1.1: + resolution: {integrity: sha512-zZgay+fPG6PgMUrpyFADmQmvLo39+AZa7Gc5pZhev2RhDxwANEq2etwD8d0e6rTg5NkwOIlQmaEmns3draC6Ng==} + dev: false + + /js-cookie@3.0.5: + resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} + engines: {node: '>=14'} + dev: false + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + /js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: true + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + + /jsesc@0.5.0: + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + hasBin: true + dev: true + + /jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + dev: true + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /json-stream@1.0.0: + resolution: {integrity: sha512-H/ZGY0nIAg3QcOwE1QN/rK/Fa7gJn7Ii5obwp6zyPO4xiPNwpIMjqy2gwjBEGqzkF/vSWEIBQCBuN19hYiL6Qg==} + dev: false + + /json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + dev: false + + /json2mq@0.2.0: + resolution: {integrity: sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==} + dependencies: + string-convert: 0.2.1 + dev: false + + /json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /jsonc-parser@3.0.0: + resolution: {integrity: sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==} + dev: true + + /jsonc-parser@3.2.0: + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + dev: true + + /jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.0 + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /jsonwebtoken@9.0.0: + resolution: {integrity: sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==} + engines: {node: '>=12', npm: '>=6'} + dependencies: + jws: 3.2.2 + lodash: 4.17.21 + ms: 2.1.3 + semver: 7.5.4 + dev: false + + /jspdf@2.5.1: + resolution: {integrity: sha512-hXObxz7ZqoyhxET78+XR34Xu2qFGrJJ2I2bE5w4SM8eFaFEkW2xcGRVUss360fYelwRSid/jT078kbNvmoW0QA==} + dependencies: + '@babel/runtime': 7.22.6 + atob: 2.1.2 + btoa: 1.2.1 + fflate: 0.4.8 + optionalDependencies: + canvg: 3.0.10 + core-js: 3.30.1 + dompurify: 2.4.7 + html2canvas: 1.4.1 + dev: false + + /jwa@1.4.1: + resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + dev: false + + /jws@3.2.2: + resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + dependencies: + jwa: 1.4.1 + safe-buffer: 5.2.1 + dev: false + + /kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: true + + /kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + dev: true + + /klona@2.0.6: + resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} + engines: {node: '>= 8'} + dev: true + + /ko-sleep@1.1.4: + resolution: {integrity: sha512-s05WGpvvzyTuRlRE8fM7ru2Z3O+InbJuBcckTWKg2W+2c1k6SnFa3IfiSSt0/peFrlYAXgNoxuJWWVNmWh+K/A==} + dependencies: + ms: 2.1.3 + dev: false + + /launch-editor@2.6.0: + resolution: {integrity: sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==} + dependencies: + picocolors: 1.0.0 + shell-quote: 1.8.1 + dev: true + + /less-loader@11.1.0(less@4.1.3)(webpack@5.75.0): + resolution: {integrity: sha512-C+uDBV7kS7W5fJlUjq5mPBeBVhYpTIm5gB09APT9o3n/ILeaXVsiSFTbZpTJCJwQ/Crczfn3DmfQFwxYusWFug==} + engines: {node: '>= 14.15.0'} + peerDependencies: + less: ^3.5.0 || ^4.0.0 + webpack: ^5.0.0 + dependencies: + klona: 2.0.6 + less: 4.1.3 + webpack: 5.75.0(webpack-cli@5.0.2) + dev: true + + /less@4.1.3: + resolution: {integrity: sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==} + engines: {node: '>=6'} + hasBin: true + dependencies: + copy-anything: 2.0.6 + parse-node-version: 1.0.1 + tslib: 2.6.0 + optionalDependencies: + errno: 0.1.8 + graceful-fs: 4.2.11 + image-size: 0.5.5 + make-dir: 2.1.0 + mime: 1.6.0 + needle: 3.2.0 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /libphonenumber-js@1.10.38: + resolution: {integrity: sha512-4NjVXVUmpZ9Zsqq6FXa2+MKI+KAI3tOqA0pxXgXGluhpj4ge5didmbWJpMBqGB3AVGv1SnEtKdGTbxjSEG1kCQ==} + + /lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + dev: true + + /lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /load-yaml-file@0.2.0: + resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} + engines: {node: '>=6'} + dependencies: + graceful-fs: 4.2.11 + js-yaml: 3.14.1 + pify: 4.0.1 + strip-bom: 3.0.0 + dev: true + + /loader-runner@4.3.0: + resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} + engines: {node: '>=6.11.5'} + dev: true + + /loader-utils@2.0.4: + resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==} + engines: {node: '>=8.9.0'} + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 2.2.3 + dev: true + + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + dev: false + + /lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + dev: true + + /lodash.defaults@4.2.0: + resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + + /lodash.isarguments@3.1.0: + resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} + + /lodash.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + dev: true + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + dev: true + + /lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + dev: true + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + /log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + dev: true + + /long@4.0.0: + resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==} + dev: false + + /long@5.2.3: + resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} + dev: false + + /loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + dependencies: + js-tokens: 4.0.0 + dev: false + + /lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + dependencies: + tslib: 2.6.0 + dev: true + + /lru-cache@10.0.0: + resolution: {integrity: sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==} + engines: {node: 14 || >=16.14} + dev: true + + /lru-cache@4.1.5: + resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + dependencies: + pseudomap: 1.0.2 + yallist: 2.1.2 + dev: true + + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: true + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + + /lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + dev: false + + /lru-cache@8.0.5: + resolution: {integrity: sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==} + engines: {node: '>=16.14'} + dev: false + + /macos-release@2.5.1: + resolution: {integrity: sha512-DXqXhEM7gW59OjZO8NIjBCz9AQ1BEMrfiOAl4AYByHCtVHRF4KoGNO8mqQeM8lRCtQe/UnJ4imO/d2HdkKsd+A==} + engines: {node: '>=6'} + dev: true + + /magic-string@0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + dependencies: + sourcemap-codec: 1.4.8 + dev: true + + /magic-string@0.26.1: + resolution: {integrity: sha512-ndThHmvgtieXe8J/VGPjG+Apu7v7ItcD5mhEIvOscWjPF/ccOiLxHaSuCAS2G+3x4GKsAbT8u7zdyamupui8Tg==} + engines: {node: '>=12'} + dependencies: + sourcemap-codec: 1.4.8 + dev: true + + /magic-string@0.27.0: + resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /magic-string@0.30.0: + resolution: {integrity: sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /make-dir@2.1.0: + resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} + engines: {node: '>=6'} + requiresBuild: true + dependencies: + pify: 4.0.1 + semver: 5.7.2 + dev: true + optional: true + + /make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + dependencies: + semver: 6.3.1 + + /make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + /map-obj@1.0.1: + resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} + engines: {node: '>=0.10.0'} + dev: true + + /map-obj@4.3.0: + resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} + engines: {node: '>=8'} + dev: true + + /md5@2.3.0: + resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} + dependencies: + charenc: 0.0.2 + crypt: 0.0.2 + is-buffer: 1.1.6 + dev: false + + /mdn-data@2.0.28: + resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} + dev: true + + /mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + dev: true + + /media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + /memfs@3.5.3: + resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} + engines: {node: '>= 4.0.0'} + dependencies: + fs-monkey: 1.0.4 + dev: true + + /meow@6.1.1: + resolution: {integrity: sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==} + engines: {node: '>=8'} + dependencies: + '@types/minimist': 1.2.2 + camelcase-keys: 6.2.2 + decamelize-keys: 1.1.1 + hard-rejection: 2.1.0 + minimist-options: 4.1.0 + normalize-package-data: 2.5.0 + read-pkg-up: 7.0.1 + redent: 3.0.0 + trim-newlines: 3.0.1 + type-fest: 0.13.1 + yargs-parser: 18.1.3 + dev: true + + /merge-descriptors@1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /mime-db@1.33.0: + resolution: {integrity: sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==} + engines: {node: '>= 0.6'} + dev: true + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + /mime-types@2.1.18: + resolution: {integrity: sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.33.0 + dev: true + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + + /mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + /mime@2.6.0: + resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} + engines: {node: '>=4.0.0'} + hasBin: true + + /mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: true + + /min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + dev: true + + /mini-css-extract-plugin@2.7.5(webpack@5.75.0): + resolution: {integrity: sha512-9HaR++0mlgom81s95vvNjxkg52n2b5s//3ZTI1EtzFb98awsLSivs2LMsVqnQ3ay0PVhqWcGNyDaTE961FOcjQ==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + dependencies: + schema-utils: 4.2.0 + webpack: 5.75.0(webpack-cli@5.0.2) + dev: true + + /minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + + /minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + + /minimatch@8.0.4: + resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: false + + /minimist-options@4.1.0: + resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} + engines: {node: '>= 6'} + dependencies: + arrify: 1.0.1 + is-plain-obj: 1.1.0 + kind-of: 6.0.3 + dev: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + /minio@7.1.1: + resolution: {integrity: sha512-HBLRFXs1CkNwAkahU+j1ilB9YS/Tmkdc6orpxVW1YN11NlEJyLjarIpBYu/inF+dj+tJIsA8PSKNnRmUNm+9qQ==} + engines: {node: ^16 || ^18 || >=20} + dependencies: + async: 3.2.4 + block-stream2: 2.1.0 + browser-or-node: 2.1.1 + buffer-crc32: 0.2.13 + fast-xml-parser: 4.2.7 + ipaddr.js: 2.1.0 + json-stream: 1.0.0 + lodash: 4.17.21 + mime-types: 2.1.35 + query-string: 7.1.3 + through2: 4.0.2 + web-encoding: 1.1.5 + xml: 1.0.1 + xml2js: 0.5.0 + dev: false + + /minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + dependencies: + yallist: 4.0.0 + dev: false + + /minipass@4.2.8: + resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} + engines: {node: '>=8'} + dev: true + + /minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + dev: false + + /minipass@7.0.2: + resolution: {integrity: sha512-eL79dXrE1q9dBbDCLg7xfn/vl7MS4F1gvJAgjJrQli/jbQWdUttuVawphqpffoIYfRdq78LHx6GP4bU/EQ2ATA==} + engines: {node: '>=16 || 14 >=14.17'} + dev: true + + /minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + dev: false + + /mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + dev: false + + /mixme@0.5.9: + resolution: {integrity: sha512-VC5fg6ySUscaWUpI4gxCBTQMH2RdUpNrk+MsbpCYtIvf9SBJdiUey4qE7BXviJsJR4nDQxCZ+3yaYNW3guz/Pw==} + engines: {node: '>= 8.0.0'} + dev: true + + /mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + dependencies: + minimist: 1.2.8 + + /mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: false + + /mkdirp@2.1.6: + resolution: {integrity: sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==} + engines: {node: '>=10'} + hasBin: true + dev: false + + /mobx-react-lite@3.4.3(mobx@6.9.0)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-NkJREyFTSUXR772Qaai51BnE1voWx56LOL80xG7qkZr6vo8vEaLF3sz1JNUVh+rxmUzxYaqOhfuxTfqUh0FXUg==} + peerDependencies: + mobx: ^6.1.0 + react: ^16.8.0 || ^17 || ^18 + react-dom: '*' + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + dependencies: + mobx: 6.9.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /mobx@6.9.0: + resolution: {integrity: sha512-HdKewQEREEJgsWnErClfbFoVebze6rGazxFLU/XUyrII8dORfVszN1V0BMRnQSzcgsNNtkX8DHj3nC6cdWE9YQ==} + dev: false + + /mrmime@1.0.1: + resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==} + engines: {node: '>=10'} + dev: true + + /ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + /multer@1.4.4-lts.1: + resolution: {integrity: sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==} + engines: {node: '>= 6.0.0'} + dependencies: + append-field: 1.0.0 + busboy: 1.6.0 + concat-stream: 1.6.2 + mkdirp: 0.5.6 + object-assign: 4.1.1 + type-is: 1.6.18 + xtend: 4.0.2 + + /multicast-dns@7.2.5: + resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} + hasBin: true + dependencies: + dns-packet: 5.6.0 + thunky: 1.1.0 + dev: true + + /mute-stream@0.0.8: + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + dev: true + + /mysql2@3.3.3: + resolution: {integrity: sha512-MxDQJztArk4JFX1PKVjDhIXRzAmVJfuqZrVU+my6NeYBAA/XZRaDw5q7vga8TNvgyy3Lv3rivBFBBuJFbsdjaw==} + engines: {node: '>= 8.0'} + dependencies: + denque: 2.1.0 + generate-function: 2.3.1 + iconv-lite: 0.6.3 + long: 5.2.3 + lru-cache: 8.0.5 + named-placeholders: 1.1.3 + seq-queue: 0.0.5 + sqlstring: 2.3.3 + dev: false + + /mz-modules@2.1.0: + resolution: {integrity: sha512-sjk8lcRW3vrVYnZ+W+67L/2rL+jbO5K/N6PFGIcLWTiYytNr22Ah9FDXFs+AQntTM1boZcoHi5qS+CV1seuPog==} + engines: {node: '>=6.0.0'} + dependencies: + glob: 7.2.3 + ko-sleep: 1.1.4 + mkdirp: 0.5.6 + pump: 3.0.0 + rimraf: 2.7.1 + dev: false + + /mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + dev: false + + /nacos-config@2.5.1: + resolution: {integrity: sha512-yKKXRh5xB8qxWIAkOC5AsgIyQv/34FFigMBOvR7NTG312TDanVginbjkrYJeowgSLLKfaxwsmMGcuy9Z7BP2TQ==} + engines: {node: '>= 8.0.0'} + dependencies: + cluster-client: 2.1.2 + co-gather: 1.0.1 + debug: 3.2.7 + iconv-lite: 0.4.24 + is-type-of: 1.4.0 + mz: 2.7.0 + mz-modules: 2.1.0 + osenv: 0.1.5 + sdk-base: 3.6.0 + urlencode: 1.1.0 + urllib: 2.41.0 + utility: 1.18.0 + transitivePeerDependencies: + - proxy-agent + - supports-color + dev: false + + /nacos-naming@2.5.0: + resolution: {integrity: sha512-e7YieRZtv76OB3h0GYqw015y3WOPTPt8grCB2QS1l73U0XqbMmpmQHwZ+BwnsM5qAKfVf4XZax8VUr8l09LOvQ==} + engines: {node: '>= 8.0.0'} + dependencies: + address: 1.2.2 + equals: 1.0.5 + mz-modules: 2.1.0 + sdk-base: 3.6.0 + urllib: 2.41.0 + utility: 1.18.0 + uuid: 3.4.0 + transitivePeerDependencies: + - proxy-agent + - supports-color + dev: false + + /nacos@2.5.1: + resolution: {integrity: sha512-xUWK1MrWaeld6tXbai+iOWgpqm2S4+jDw3mvWGMqAhVSP90lhqGKvA7l6b1EpYjN1Vv1viYiVIlEoQKm756mqQ==} + engines: {node: '>= 8.0.0'} + dependencies: + nacos-config: 2.5.1 + nacos-naming: 2.5.0 + transitivePeerDependencies: + - proxy-agent + - supports-color + dev: false + + /named-placeholders@1.1.3: + resolution: {integrity: sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==} + engines: {node: '>=12.0.0'} + dependencies: + lru-cache: 7.18.3 + dev: false + + /nanoid@3.3.6: + resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + + /nats@2.15.1: + resolution: {integrity: sha512-MMCQXxOLv3dUwh0CRai0RGdMdAHjA3LNOYEAdNkLT8GX4CJFVKlYqkM3K9qVkYhvWwiCUVPHWFSktcrhexSzSw==} + engines: {node: '>= 14.0.0'} + dependencies: + nkeys.js: 1.0.5 + + /natural-compare-lite@1.4.0: + resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} + dev: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /needle@3.2.0: + resolution: {integrity: sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==} + engines: {node: '>= 4.4.x'} + hasBin: true + requiresBuild: true + dependencies: + debug: 3.2.7 + iconv-lite: 0.6.3 + sax: 1.2.4 + transitivePeerDependencies: + - supports-color + dev: true + optional: true + + /negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + /neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + dev: true + + /nkeys.js@1.0.5: + resolution: {integrity: sha512-u25YnRPHiGVsNzwyHnn+PT90sgAhnS8jUJ1nxmkHMFYCJ6+Ic0lv291w7uhRBpJVJ3PH2GWbYqA151lGCRrB5g==} + engines: {node: '>=10.0.0'} + dependencies: + tweetnacl: 1.0.3 + + /no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + dependencies: + lower-case: 2.0.2 + tslib: 2.6.0 + dev: true + + /node-abort-controller@3.1.1: + resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} + dev: true + + /node-addon-api@5.1.0: + resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} + dev: false + + /node-emoji@1.11.0: + resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} + dependencies: + lodash: 4.17.21 + dev: true + + /node-fetch@2.6.12: + resolution: {integrity: sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + + /node-forge@1.3.1: + resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} + engines: {node: '>= 6.13.0'} + dev: true + + /node-releases@2.0.13: + resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} + dev: true + + /nopt@5.0.0: + resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} + engines: {node: '>=6'} + hasBin: true + dependencies: + abbrev: 1.1.1 + dev: false + + /normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.2 + semver: 5.7.2 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: true + + /npmlog@5.0.1: + resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} + dependencies: + are-we-there-yet: 2.0.0 + console-control-strings: 1.1.0 + gauge: 3.0.2 + set-blocking: 2.0.0 + dev: false + + /nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + dependencies: + boolbase: 1.0.0 + dev: true + + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + /object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + dev: false + + /object-inspect@1.12.3: + resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign@4.1.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /obuf@1.1.2: + resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} + dev: true + + /on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + + /on-headers@1.0.2: + resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} + engines: {node: '>= 0.8'} + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + + /onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: true + + /open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + dev: true + + /opener@1.5.2: + resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} + hasBin: true + dev: true + + /optionator@0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + dependencies: + '@aashutoshrathi/word-wrap': 1.2.6 + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.0 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + dev: true + + /os-homedir@1.0.2: + resolution: {integrity: sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==} + engines: {node: '>=0.10.0'} + dev: false + + /os-name@1.0.3: + resolution: {integrity: sha512-f5estLO2KN8vgtTRaILIgEGBoBrMnZ3JQ7W9TMZCnOIGwHe8TRGSpcagnWDo+Dfhd/z08k9Xe75hvciJJ8Qaew==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + osx-release: 1.1.0 + win-release: 1.1.1 + dev: false + + /os-name@4.0.1: + resolution: {integrity: sha512-xl9MAoU97MH1Xt5K9ERft2YfCAoaO6msy1OBA0ozxEC0x0TmIoE6K3QvgJMMZA9yKGLmHXNY/YZoDbiGDj4zYw==} + engines: {node: '>=10'} + dependencies: + macos-release: 2.5.1 + windows-release: 4.0.0 + dev: true + + /os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + + /osenv@0.1.5: + resolution: {integrity: sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==} + dependencies: + os-homedir: 1.0.2 + os-tmpdir: 1.0.2 + dev: false + + /osx-release@1.1.0: + resolution: {integrity: sha512-ixCMMwnVxyHFQLQnINhmIpWqXIfS2YOXchwQrk+OFzmo6nDjQ0E4KXAyyUh0T0MZgV4bUhkRrAbVqlE4yLVq4A==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: false + + /outdent@0.5.0: + resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} + dev: true + + /p-filter@2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} + engines: {node: '>=8'} + dependencies: + p-map: 2.1.0 + dev: true + + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + dev: true + + /p-retry@4.6.2: + resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} + engines: {node: '>=8'} + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 + dev: true + + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /param-case@3.0.4: + resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} + dependencies: + dot-case: 3.0.4 + tslib: 2.6.0 + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.22.5 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /parse-node-version@1.0.1: + resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} + engines: {node: '>= 0.10'} + dev: true + + /parse5-htmlparser2-tree-adapter@6.0.1: + resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} + dependencies: + parse5: 6.0.1 + dev: false + + /parse5@5.1.1: + resolution: {integrity: sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==} + dev: false + + /parse5@6.0.1: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + dev: false + + /parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + /pascal-case@3.1.2: + resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.0 + dev: true + + /passport-strategy@1.0.0: + resolution: {integrity: sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==} + engines: {node: '>= 0.4.0'} + dev: false + + /passport@0.6.0: + resolution: {integrity: sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==} + engines: {node: '>= 0.4.0'} + dependencies: + passport-strategy: 1.0.0 + pause: 0.0.1 + utils-merge: 1.0.1 + dev: false + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + /path-is-inside@1.0.2: + resolution: {integrity: sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-scurry@1.10.1: + resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + lru-cache: 10.0.0 + minipass: 7.0.2 + dev: true + + /path-to-regexp@0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + + /path-to-regexp@2.2.1: + resolution: {integrity: sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==} + dev: true + + /path-to-regexp@3.2.0: + resolution: {integrity: sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==} + + /path-to-regexp@6.2.1: + resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} + dev: false + + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /pause-stream@0.0.11: + resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==} + dependencies: + through: 2.3.8 + dev: false + + /pause@0.0.1: + resolution: {integrity: sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==} + dev: false + + /performance-now@2.1.0: + resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} + requiresBuild: true + dev: false + optional: true + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + dev: true + + /pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + dev: true + + /pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + dev: true + + /postcss-calc@9.0.1(postcss@8.4.27): + resolution: {integrity: sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.2 + dependencies: + postcss: 8.4.27 + postcss-selector-parser: 6.0.13 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-colormin@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-EuO+bAUmutWoZYgHn2T1dG1pPqHU6L4TjzPlu4t1wZGXQ/fxV16xg2EJmYi0z+6r+MGV1yvpx1BHkUaRrPa2bw==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + browserslist: 4.21.10 + caniuse-api: 3.0.0 + colord: 2.9.3 + postcss: 8.4.27 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-convert-values@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-U5D8QhVwqT++ecmy8rnTb+RL9n/B806UVaS3m60lqle4YDFcpbS3ae5bTQIh3wOGUSDHSEtMYLs/38dNG7EYFw==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + browserslist: 4.21.10 + postcss: 8.4.27 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-discard-comments@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-p2skSGqzPMZkEQvJsgnkBhCn8gI7NzRH2683EEjrIkoMiwRELx68yoUJ3q3DGSGuQ8Ug9Gsn+OuDr46yfO+eFw==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + dev: true + + /postcss-discard-duplicates@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-bU1SXIizMLtDW4oSsi5C/xHKbhLlhek/0/yCnoMQany9k3nPBq+Ctsv/9oMmyqbR96HYHxZcHyK2HR5P/mqoGA==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + dev: true + + /postcss-discard-empty@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-b+h1S1VT6dNhpcg+LpyiUrdnEZfICF0my7HAKgJixJLW7BnNmpRH34+uw/etf5AhOlIhIAuXApSzzDzMI9K/gQ==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + dev: true + + /postcss-discard-overridden@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-4VELwssYXDFigPYAZ8vL4yX4mUepF/oCBeeIT4OXsJPYOtvJumyz9WflmJWTfDwCUcpDR+z0zvCWBXgTx35SVw==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + dev: true + + /postcss-merge-longhand@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-4VSfd1lvGkLTLYcxFuISDtWUfFS4zXe0FpF149AyziftPFQIWxjvFSKhA4MIxMe4XM3yTDgQMbSNgzIVxChbIg==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + postcss-value-parser: 4.2.0 + stylehacks: 6.0.0(postcss@8.4.27) + dev: true + + /postcss-merge-rules@6.0.1(postcss@8.4.27): + resolution: {integrity: sha512-a4tlmJIQo9SCjcfiCcCMg/ZCEe0XTkl/xK0XHBs955GWg9xDX3NwP9pwZ78QUOWB8/0XCjZeJn98Dae0zg6AAw==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + browserslist: 4.21.10 + caniuse-api: 3.0.0 + cssnano-utils: 4.0.0(postcss@8.4.27) + postcss: 8.4.27 + postcss-selector-parser: 6.0.13 + dev: true + + /postcss-minify-font-values@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-zNRAVtyh5E8ndZEYXA4WS8ZYsAp798HiIQ1V2UF/C/munLp2r1UGHwf1+6JFu7hdEhJFN+W1WJQKBrtjhFgEnA==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-minify-gradients@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-wO0F6YfVAR+K1xVxF53ueZJza3L+R3E6cp0VwuXJQejnNUH0DjcAFe3JEBeTY1dLwGa0NlDWueCA1VlEfiKgAA==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + colord: 2.9.3 + cssnano-utils: 4.0.0(postcss@8.4.27) + postcss: 8.4.27 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-minify-params@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-Fz/wMQDveiS0n5JPcvsMeyNXOIMrwF88n7196puSuQSWSa+/Ofc1gDOSY2xi8+A4PqB5dlYCKk/WfqKqsI+ReQ==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + browserslist: 4.21.10 + cssnano-utils: 4.0.0(postcss@8.4.27) + postcss: 8.4.27 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-minify-selectors@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-ec/q9JNCOC2CRDNnypipGfOhbYPuUkewGwLnbv6omue/PSASbHSU7s6uSQ0tcFRVv731oMIx8k0SP4ZX6be/0g==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + postcss-selector-parser: 6.0.13 + dev: true + + /postcss-modules-extract-imports@3.0.0(postcss@8.4.27): + resolution: {integrity: sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + postcss: 8.4.27 + dev: true + + /postcss-modules-local-by-default@4.0.3(postcss@8.4.27): + resolution: {integrity: sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + icss-utils: 5.1.0(postcss@8.4.27) + postcss: 8.4.27 + postcss-selector-parser: 6.0.13 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-modules-scope@3.0.0(postcss@8.4.27): + resolution: {integrity: sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + postcss: 8.4.27 + postcss-selector-parser: 6.0.13 + dev: true + + /postcss-modules-values@4.0.0(postcss@8.4.27): + resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + icss-utils: 5.1.0(postcss@8.4.27) + postcss: 8.4.27 + dev: true + + /postcss-normalize-charset@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-cqundwChbu8yO/gSWkuFDmKrCZ2vJzDAocheT2JTd0sFNA4HMGoKMfbk2B+J0OmO0t5GUkiAkSM5yF2rSLUjgQ==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + dev: true + + /postcss-normalize-display-values@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-Qyt5kMrvy7dJRO3OjF7zkotGfuYALETZE+4lk66sziWSPzlBEt7FrUshV6VLECkI4EN8Z863O6Nci4NXQGNzYw==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-normalize-positions@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-mPCzhSV8+30FZyWhxi6UoVRYd3ZBJgTRly4hOkaSifo0H+pjDYcii/aVT4YE6QpOil15a5uiv6ftnY3rm0igPg==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-normalize-repeat-style@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-50W5JWEBiOOAez2AKBh4kRFm2uhrT3O1Uwdxz7k24aKtbD83vqmcVG7zoIwo6xI2FZ/HDlbrCopXhLeTpQib1A==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-normalize-string@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-KWkIB7TrPOiqb8ZZz6homet2KWKJwIlysF5ICPZrXAylGe2hzX/HSf4NTX2rRPJMAtlRsj/yfkrWGavFuB+c0w==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-normalize-timing-functions@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-tpIXWciXBp5CiFs8sem90IWlw76FV4oi6QEWfQwyeREVwUy39VSeSqjAT7X0Qw650yAimYW5gkl2Gd871N5SQg==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-normalize-unicode@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-ui5crYkb5ubEUDugDc786L/Me+DXp2dLg3fVJbqyAl0VPkAeALyAijF2zOsnZyaS1HyfPuMH0DwyY18VMFVNkg==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + browserslist: 4.21.10 + postcss: 8.4.27 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-normalize-url@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-98mvh2QzIPbb02YDIrYvAg4OUzGH7s1ZgHlD3fIdTHLgPLRpv1ZTKJDnSAKr4Rt21ZQFzwhGMXxpXlfrUBKFHw==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-normalize-whitespace@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-7cfE1AyLiK0+ZBG6FmLziJzqQCpTQY+8XjMhMAz8WSBSCsCNNUKujgIgjCAmDT3cJ+3zjTXFkoD15ZPsckArVw==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-ordered-values@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-K36XzUDpvfG/nWkjs6d1hRBydeIxGpKS2+n+ywlKPzx1nMYDYpoGbcjhj5AwVYJK1qV2/SDoDEnHzlPD6s3nMg==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + cssnano-utils: 4.0.0(postcss@8.4.27) + postcss: 8.4.27 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-reduce-initial@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-s2UOnidpVuXu6JiiI5U+fV2jamAw5YNA9Fdi/GRK0zLDLCfXmSGqQtzpUPtfN66RtCbb9fFHoyZdQaxOB3WxVA==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + browserslist: 4.21.10 + caniuse-api: 3.0.0 + postcss: 8.4.27 + dev: true + + /postcss-reduce-transforms@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-FQ9f6xM1homnuy1wLe9lP1wujzxnwt1EwiigtWwuyf8FsqqXUDUp2Ulxf9A5yjlUOTdCJO6lonYjg1mgqIIi2w==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-selector-parser@6.0.13: + resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: true + + /postcss-svgo@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-r9zvj/wGAoAIodn84dR/kFqwhINp5YsJkLoujybWG59grR/IHx+uQ2Zo+IcOwM0jskfYX3R0mo+1Kip1VSNcvw==} + engines: {node: ^14 || ^16 || >= 18} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + postcss-value-parser: 4.2.0 + svgo: 3.0.2 + dev: true + + /postcss-unique-selectors@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-EPQzpZNxOxP7777t73RQpZE5e9TrnCrkvp7AH7a0l89JmZiPnS82y216JowHXwpBCQitfyxrof9TK3rYbi7/Yw==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + postcss: 8.4.27 + postcss-selector-parser: 6.0.13 + dev: true + + /postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + dev: true + + /postcss@8.4.27: + resolution: {integrity: sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.6 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + + /preferred-pm@3.0.3: + resolution: {integrity: sha512-+wZgbxNES/KlJs9q40F/1sfOd/j7f1O9JaHcW5Dsn3aUUOZg3L2bjpVUcKV2jvtElYfoTuQiNeMfQJ4kwUAhCQ==} + engines: {node: '>=10'} + dependencies: + find-up: 5.0.0 + find-yarn-workspace-root2: 1.2.16 + path-exists: 4.0.0 + which-pm: 2.0.0 + dev: true + + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + dependencies: + fast-diff: 1.3.0 + dev: true + + /prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + dev: true + + /pretty-error@4.0.0: + resolution: {integrity: sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==} + dependencies: + lodash: 4.17.21 + renderkid: 3.0.0 + dev: true + + /pretty-time@1.1.0: + resolution: {integrity: sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==} + engines: {node: '>=4'} + dev: true + + /process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + /proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: false + + /prr@1.0.1: + resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} + requiresBuild: true + dev: true + optional: true + + /pseudomap@1.0.2: + resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + dev: true + + /pump@3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + + /punycode@1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + dev: true + + /punycode@2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} + engines: {node: '>=6'} + dev: true + + /purgecss-webpack-plugin@5.0.0(webpack@5.75.0): + resolution: {integrity: sha512-u8J0SxXdMekVOsbyV6hK1x6LlzJbE/mrC+UbNX0mLz5Jo/Jle8o4S3IFIRCgdzGdxtOBPCKW+UNgaULfKVmx2w==} + peerDependencies: + webpack: '>=5.0.0' + dependencies: + purgecss: 5.0.0 + webpack: 5.75.0(webpack-cli@5.0.2) + dev: true + + /purgecss@5.0.0: + resolution: {integrity: sha512-RAnuxrGuVyLLTr8uMbKaxDRGWMgK5CCYDfRyUNNcaz5P3kGgD2b7ymQGYEyo2ST7Tl/ScwFgf5l3slKMxHSbrw==} + hasBin: true + dependencies: + commander: 9.5.0 + glob: 8.1.0 + postcss: 8.4.27 + postcss-selector-parser: 6.0.13 + dev: true + + /qrcode.react@3.1.0(react@18.2.0): + resolution: {integrity: sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + dev: false + + /qs@6.10.3: + resolution: {integrity: sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: false + + /qs@6.11.0: + resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + + /qs@6.11.2: + resolution: {integrity: sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + + /query-string@7.1.3: + resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==} + engines: {node: '>=6'} + dependencies: + decode-uri-component: 0.2.2 + filter-obj: 1.1.0 + split-on-first: 1.1.0 + strict-uri-encode: 2.0.0 + dev: false + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /quick-lru@4.0.1: + resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} + engines: {node: '>=8'} + dev: true + + /raf@3.4.1: + resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==} + requiresBuild: true + dependencies: + performance-now: 2.1.0 + dev: false + optional: true + + /randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /range-parser@1.2.0: + resolution: {integrity: sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==} + engines: {node: '>= 0.6'} + dev: true + + /range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + /raw-body@2.5.1: + resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + /raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + /rc-align@4.0.15(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-wqJtVH60pka/nOX7/IspElA8gjPNQKIx/ZqJ6heATCkXpe1Zg4cPVrMD2vC96wjsFFL8WsmhPbx9tdMo1qqlIA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + dom-align: 1.12.4 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + resize-observer-polyfill: 1.5.1 + dev: false + + /rc-cascader@3.12.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-g6In2y6eudHXS/Fs9dKFhp9acvHRUPqem/7xReR9ng8M1pNAE137uGBOt9WNpgsKT/cDGudXZQVehaBwAKg6hQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + array-tree-filter: 2.1.0 + classnames: 2.3.2 + rc-select: 14.5.2(react-dom@18.2.0)(react@18.2.0) + rc-tree: 5.7.9(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-cascader@3.14.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-fCsgjLIQqYZMhFj9UT+x2ZW4uobx7OP5yivcn6Xto5fuxHaldphsryzCeUVmreQOHEo0RP+032Ip9RDzrKVKJA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + array-tree-filter: 2.1.0 + classnames: 2.3.2 + rc-select: 14.7.4(react-dom@18.2.0)(react@18.2.0) + rc-tree: 5.7.9(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-checkbox@3.1.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-PAwpJFnBa3Ei+5pyqMMXdcKYKNBMS+TvSDiLdDnARnMJHC8ESxwPfm4Ao1gJiKtWLdmGfigascnCpwrHFgoOBQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-collapse@3.7.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-N/7ejyiTf3XElNJBBpxqnZBUuMsQWEOPjB2QkfNvZ/Ca54eAvJXuOD1EGbCWCk2m7v/MSxku7mRpdeaLOCd4Gg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-motion: 2.7.3(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-dialog@9.1.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-5ry+JABAWEbaKyYsmITtrJbZbJys8CtMyzV8Xn4LYuXMeUx5XVHNyJRoqLFE4AzBuXXzOWeaC49cg+XkxK6kHA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/portal': 1.1.2(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-motion: 2.7.3(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-drawer@6.2.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-spPkZ3WvP0U0vy5dyzSwlUJ/+vLFtjP/cTwSwejhQRoDBaexSZHsBhELoCZcEggI7LQ7typmtG30lAue2HEhvA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/portal': 1.1.2(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-motion: 2.7.3(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-dropdown@4.1.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-VZjMunpBdlVzYpEdJSaV7WM7O0jf8uyDjirxXLZRNZ+tAC+NzD3PXPEtliFwGzVwBBdCmGuSqiS9DWcOLxQ9tw==} + peerDependencies: + react: '>=16.11.0' + react-dom: '>=16.11.0' + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/trigger': 1.15.1(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-field-form@1.34.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-BdciU5C7dBO51/9ZKcMvK2f8zaaO12Lt1eBhlAo8nNv+6htlNcgY9DAkUlZ7gfyWjnCc1Oo4hHIXau1m6tLw1A==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + async-validator: 4.2.5 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-field-form@1.36.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-tCF/JjUsnxW80Gk4E4ZH74ONsaQMxVTRtui6XhQB8DJc4FHWLLa5pP8zwhxtPKC5NaO0QZ0Cv79JggDubn6n2g==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + async-validator: 4.2.5 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-image@5.17.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-oR4eviLyQxd/5A7pn843w2/Z1wuBA27L2lS4agq0sjl2z97ssNIVEzRzgwgB0ZxVZG/qSu9Glit2Zgzb/n+blQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/portal': 1.1.2(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-dialog: 9.1.0(react-dom@18.2.0)(react@18.2.0) + rc-motion: 2.7.3(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-image@7.1.3(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-foMl1rcit1F0+vgxE5kf0c8TygQcHhILsOohQUL+JMUbzOo3OBFRcehJudYbqbCTArzCecS8nA1irUU9vvgQbg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/portal': 1.1.2(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-dialog: 9.1.0(react-dom@18.2.0)(react@18.2.0) + rc-motion: 2.7.3(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-input-number@7.4.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-yGturTw7WGP+M1GbJ+UTAO7L4buxeW6oilhL9Sq3DezsRS8/9qec4UiXUbeoiX9bzvRXH11JvgskBtxSp4YSNg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/mini-decimal': 1.1.0 + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-input-number@8.0.4(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-TP+G5b7mZtbwXJ/YEZXF/OgbEZ6iqD4+RSuxZJ8VGKGXDcdt0FKIvpFoNQr/knspdFC4OxA0OfsWfFWfN4XSyA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/mini-decimal': 1.1.0 + classnames: 2.3.2 + rc-input: 1.1.1(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-input@1.0.4(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-clY4oneVHRtKHYf/HCxT/MO+4BGzCIywSNLosXWOm7fcQAS0jQW7n0an8Raa8JMB8kpxc8m28p7SNwFZmlMj6g==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-input@1.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-NTR1Z4em681L8/ewb2KR80RykSmN8I2mzqzJDCoUmTrV1BB9Hk5d7ha4TnfgdEPPL148N+603sW2LExSXk1IbA==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-mentions@2.3.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-gNpsSKsBHSXvyAA1ZowVTqXSWUIw7+OI9wmjL87KcYURvtm9nDo8R0KtOc2f1PT7q9McUpFzhm6AvQdIly0aRA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/trigger': 1.15.1(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-input: 1.0.4(react-dom@18.2.0)(react@18.2.0) + rc-menu: 9.9.2(react-dom@18.2.0)(react@18.2.0) + rc-textarea: 1.2.3(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-mentions@2.5.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-rERXsbUTNVrb5T/iDC0ki/SRGWJnOVraDy6O25Us3FSpuUZ3uq2TPZB4fRk0Hss5kyiEPzz2sprhkI4b+F4jUw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/trigger': 1.15.1(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-input: 1.1.1(react-dom@18.2.0)(react@18.2.0) + rc-menu: 9.10.0(react-dom@18.2.0)(react@18.2.0) + rc-textarea: 1.3.4(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-menu@9.10.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-g27kpXaAoJh/fkPZF65/d4V+w4DhDeqomBdPcGnkFAcJnEM4o21TnVccrBUoDedLKzC7wJRw1Q7VTqEsfEufmw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/trigger': 1.15.1(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-motion: 2.7.3(react-dom@18.2.0)(react@18.2.0) + rc-overflow: 1.3.1(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-menu@9.9.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-kVJwaQn5VUu6DIddxd/jz3QupTPg0tNYq+mpFP8wYsRF5JgzPA9fPVw+CfwlTPwA1w7gzEY42S8pj6M3uev5CQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/trigger': 1.15.1(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-motion: 2.7.3(react-dom@18.2.0)(react@18.2.0) + rc-overflow: 1.3.1(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-motion@2.7.3(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-2xUvo8yGHdOHeQbdI8BtBsCIrWKchEmFEIskf0nmHtJsou+meLd/JE+vnvSX2JxcBrJtXY2LuBpxAOxrbY/wMQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-notification@5.0.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-uEz2jggourwv/rR0obe7RHEa63UchqX4k+e+Qt2c3LaY7U9Tc+L6ANhzgCKYSA/afm0ebjmNZHoB5Cv47xEOcA==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-motion: 2.7.3(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-overflow@1.3.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-RY0nVBlfP9CkxrpgaLlGzkSoh9JhjJLu6Icqs9E7CW6Ewh9s0peF9OHIex4OhfoPsR92LR0fN6BlCY9Z4VoUtA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-resize-observer: 1.3.1(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-pagination@3.5.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-lUBVtVVUn7gGsq4mTyVpcZQr+AMcljbMiL/HcCmSdFrcsK0iZVKwwbXDxhz2IV0JXUs9Hzepr5sQFaF+9ad/pQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-picker@3.12.0(dayjs@1.11.9)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-SsEhK4hbjAh3pvlqujIQaMcx6mLAwc0KN0TS9dJ0rtwGuUnSDa/mKgna/LjZlOT7U//b+dIH5BLSZttpklRG9A==} + engines: {node: '>=8.x'} + peerDependencies: + date-fns: '>= 2.x' + dayjs: '>= 1.x' + luxon: '>= 3.x' + moment: '>= 2.x' + react: '>=16.9.0' + react-dom: '>=16.9.0' + peerDependenciesMeta: + date-fns: + optional: true + dayjs: + optional: true + luxon: + optional: true + moment: + optional: true + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/trigger': 1.15.1(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + dayjs: 1.11.9 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-picker@3.13.0(dayjs@1.11.9)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-hJ+1lGkemnvsW+t+PjH9OAehHlj7wdD0G75T1HZj0IeZTqBE/5mmuf8E8MHYATNBqW409lAfk8GwjYm1WVMopg==} + engines: {node: '>=8.x'} + peerDependencies: + date-fns: '>= 2.x' + dayjs: '>= 1.x' + luxon: '>= 3.x' + moment: '>= 2.x' + react: '>=16.9.0' + react-dom: '>=16.9.0' + peerDependenciesMeta: + date-fns: + optional: true + dayjs: + optional: true + luxon: + optional: true + moment: + optional: true + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/trigger': 1.15.1(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + dayjs: 1.11.9 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-picker@3.8.2(dayjs@1.11.9)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-q6jnMwBoOi6tFA4xohrKIhzq80Fc3dH0Kiw5VRx6Tf1db7y27PBFCLwu6f66niXidZKD8F4R0M9VIui/jkL4cg==} + engines: {node: '>=8.x'} + peerDependencies: + date-fns: '>= 2.x' + dayjs: '>= 1.x' + luxon: '>= 3.x' + moment: '>= 2.x' + react: '>=16.9.0' + react-dom: '>=16.9.0' + peerDependenciesMeta: + date-fns: + optional: true + dayjs: + optional: true + luxon: + optional: true + moment: + optional: true + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/trigger': 1.15.1(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + dayjs: 1.11.9 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-progress@3.4.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-iAGhwWU+tsayP+Jkl9T4+6rHeQTG9kDz8JAHZk4XtQOcYN5fj9H34NXNEdRdZx94VUDHMqCb1yOIvi8eJRh67w==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-rate@2.12.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-g092v5iZCdVzbjdn28FzvWebK2IutoVoiTeqoLTj9WM7SjA/gOJIw5/JFZMRyJYYVe1jLAU2UhAfstIpCNRozg==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-resize-observer@1.3.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-iFUdt3NNhflbY3mwySv5CA1TC06zdJ+pfo0oc27xpf4PIOvfZwZGtD9Kz41wGYqC4SLio93RVAirSSpYlV/uYg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + resize-observer-polyfill: 1.5.1 + dev: false + + /rc-segmented@2.2.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Mq52M96QdHMsNdE/042ibT5vkcGcD5jxKp7HgPC2SRofpia99P5fkfHy1pEaajLMF/kj0+2Lkq1UZRvqzo9mSA==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-motion: 2.7.3(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-select@14.5.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Np/lDHvxCnVhVsheQjSV1I/OMJTWJf1n10wq8q1AGy3ytyYLfjNpi6uaz/pmjsbbiSddSWzJnNZCli9LmgBZsA==} + engines: {node: '>=8.x'} + peerDependencies: + react: '*' + react-dom: '*' + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/trigger': 1.15.1(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-motion: 2.7.3(react-dom@18.2.0)(react@18.2.0) + rc-overflow: 1.3.1(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + rc-virtual-list: 3.5.3(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-select@14.7.4(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-qRUpvMVXFy6rdHe+qzHXAqyQAfhErC/oY8dcRtoRjoz0lz2Nx3J+lLL5AnEbjnwlS+/kQTJUZ/65WyCwWwcLwQ==} + engines: {node: '>=8.x'} + peerDependencies: + react: '*' + react-dom: '*' + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/trigger': 1.15.1(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-motion: 2.7.3(react-dom@18.2.0)(react@18.2.0) + rc-overflow: 1.3.1(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + rc-virtual-list: 3.5.3(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-slider@10.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-gn8oXazZISEhnmRinI89Z/JD/joAaM35jp+gDtIVSTD/JJMCCBqThqLk1SVJmvtfeiEF/kKaFY0+qt4SDHFUDw==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-steps@6.0.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-switch@4.1.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-table@7.32.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-fHMQteKMocUC9I9Vex3eBLH7QsiaMR/qtzh3B1Ty2PoNGwVTwVdDFyRL05zch+JU3KnNNczgQeVvtf/p//gdrQ==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/context': 1.3.0(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-resize-observer: 1.3.1(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-tabs@12.7.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-NrltXEYIyiDP5JFu85NQwc9eR+7e50r/6MNXYDyG1EMIFNc7BgDppzdpnD3nW4NHYWw5wLIThCURGib48OCTBg==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-dropdown: 4.1.0(react-dom@18.2.0)(react@18.2.0) + rc-menu: 9.9.2(react-dom@18.2.0)(react@18.2.0) + rc-motion: 2.7.3(react-dom@18.2.0)(react@18.2.0) + rc-resize-observer: 1.3.1(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-tabs@12.9.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-2HnVowgMVrq0DfQtyu4mCd9E6pXlWNdM6VaDvOOHMsLYqPmpY+7zBqUC6YrrQ9xYXHciTS0e7TtjOHIvpVCHLQ==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-dropdown: 4.1.0(react-dom@18.2.0)(react@18.2.0) + rc-menu: 9.10.0(react-dom@18.2.0)(react@18.2.0) + rc-motion: 2.7.3(react-dom@18.2.0)(react@18.2.0) + rc-resize-observer: 1.3.1(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-textarea@1.2.3(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-YvN8IskIVBRRzcS4deT0VAMim31+T3IoVX4yoCJ+b/iVCvw7yf0usR7x8OaHiUOUoURKcn/3lfGjmtzplcy99g==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-input: 1.0.4(react-dom@18.2.0)(react@18.2.0) + rc-resize-observer: 1.3.1(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-textarea@1.3.4(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-wn0YjTpvcVolcfXa0HtzL+jgV2QcwtfB29RwNAKj8hMgZOju1V24M3TfEDjABeQEAQbUGbjMbISREOX/YSVKhg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-input: 1.1.1(react-dom@18.2.0)(react@18.2.0) + rc-resize-observer: 1.3.1(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-tooltip@6.0.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-MdvPlsD1fDSxKp9+HjXrc/CxLmA/s11QYIh1R7aExxfodKP7CZA++DG1AjrW80F8IUdHYcR43HAm0Y2BYPelHA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + '@rc-component/trigger': 1.15.1(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-tree-select@5.11.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-EDG1rYFu1iD2Y8fg0yEmm0LV3XqWOy+SpgOMvO5396NgAZ67t0zVTNK6FQkIxzdXf5ri742BkB/B8+Ah6+0Kxw==} + peerDependencies: + react: '*' + react-dom: '*' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-select: 14.7.4(react-dom@18.2.0)(react@18.2.0) + rc-tree: 5.7.9(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-tree-select@5.9.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-oh3blESzLfLCBPSiVDtZ2irzrWWZUMeHvnSwRvFo79br8Z+K/1OhXhXBZmROvfKwaH8YUugAQy8B2j5EGQbdyA==} + peerDependencies: + react: '*' + react-dom: '*' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-select: 14.5.2(react-dom@18.2.0)(react@18.2.0) + rc-tree: 5.7.9(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-tree@5.7.9(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-1hKkToz/EVjJlMVwmZnpXeLXt/1iQMsaAq9m+GNkUbK746gkc7QpJXSN/TzjhTI5Hi+LOSlrMaXLMT0bHPqILQ==} + engines: {node: '>=10.x'} + peerDependencies: + react: '*' + react-dom: '*' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-motion: 2.7.3(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + rc-virtual-list: 3.5.3(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-upload@4.3.4(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-uVbtHFGNjHG/RyAfm9fluXB6pvArAGyAx8z7XzXXyorEgVIWj6mOlriuDm0XowDHYz4ycNK0nE0oP3cbFnzxiQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-util@5.35.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-MTXlixb3EoSTEchsOc7XWsVyoUQqoCsh2Z1a2IptwNgqleMF6ZgQeY52UzUbNj5CcVBg9YljOWjuOV07jSSm4Q==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.22.6 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-is: 16.13.1 + dev: false + + /rc-virtual-list@3.5.3(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-rG6IuD4EYM8K6oZ8Shu2BC/CmcTdqng4yBWkc/5fjWhB20bl6QwR2Upyt7+MxvfscoVm8zOQY+tcpEO5cu4GaQ==} + engines: {node: '>=8.x'} + peerDependencies: + react: '*' + react-dom: '*' + dependencies: + '@babel/runtime': 7.22.6 + classnames: 2.3.2 + rc-resize-observer: 1.3.1(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.35.0(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + dev: true + + /react-dom@18.2.0(react@18.2.0): + resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} + peerDependencies: + react: ^18.2.0 + dependencies: + loose-envify: 1.4.0 + react: 18.2.0 + scheduler: 0.23.0 + dev: false + + /react-i18next@12.3.1(i18next@22.5.0)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-5v8E2XjZDFzK7K87eSwC7AJcAkcLt5xYZ4+yTPDAW1i7C93oOY1dnr4BaQM7un4Hm+GmghuiPvevWwlca5PwDA==} + peerDependencies: + i18next: '>= 19.0.0' + react: '>= 16.8.0' + react-dom: '*' + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + dependencies: + '@babel/runtime': 7.22.6 + html-parse-stringify: 3.0.1 + i18next: 22.5.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /react-icons@4.10.1(react@18.2.0): + resolution: {integrity: sha512-/ngzDP/77tlCfqthiiGNZeYFACw85fUjZtLbedmJ5DTlNDIwETxhwBzdOJ21zj4iJdvc0J3y7yOsX3PpxAJzrw==} + peerDependencies: + react: '*' + dependencies: + react: 18.2.0 + dev: false + + /react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + dev: false + + /react-refresh@0.14.0: + resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==} + engines: {node: '>=0.10.0'} + dev: true + + /react-router-dom@6.11.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-JNbKtAeh1VSJQnH6RvBDNhxNwemRj7KxCzc5jb7zvDSKRnPWIFj9pO+eXqjM69gQJ0r46hSz1x4l9y0651DKWw==} + engines: {node: '>=14'} + peerDependencies: + react: '>=16.8' + react-dom: '>=16.8' + dependencies: + '@remix-run/router': 1.6.2 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-router: 6.11.2(react@18.2.0) + dev: false + + /react-router-dom@6.14.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-ssF6M5UkQjHK70fgukCJyjlda0Dgono2QGwqGvuk7D+EDGHdacEN3Yke2LTMjkrpHuFwBfDFsEjGVXBDmL+bWw==} + engines: {node: '>=14'} + peerDependencies: + react: '>=16.8' + react-dom: '>=16.8' + dependencies: + '@remix-run/router': 1.7.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-router: 6.14.1(react@18.2.0) + dev: false + + /react-router-dom@6.14.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-5pWX0jdKR48XFZBuJqHosX3AAHjRAzygouMTyimnBPOLdY3WjzUSKhus2FVMihUFWzeLebDgr4r8UeQFAct7Bg==} + engines: {node: '>=14'} + peerDependencies: + react: '>=16.8' + react-dom: '>=16.8' + dependencies: + '@remix-run/router': 1.7.2 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-router: 6.14.2(react@18.2.0) + dev: false + + /react-router@6.11.2(react@18.2.0): + resolution: {integrity: sha512-74z9xUSaSX07t3LM+pS6Un0T55ibUE/79CzfZpy5wsPDZaea1F8QkrsiyRnA2YQ7LwE/umaydzXZV80iDCPkMg==} + engines: {node: '>=14'} + peerDependencies: + react: '>=16.8' + dependencies: + '@remix-run/router': 1.6.2 + react: 18.2.0 + dev: false + + /react-router@6.14.1(react@18.2.0): + resolution: {integrity: sha512-U4PfgvG55LdvbQjg5Y9QRWyVxIdO1LlpYT7x+tMAxd9/vmiPuJhIwdxZuIQLN/9e3O4KFDHYfR9gzGeYMasW8g==} + engines: {node: '>=14'} + peerDependencies: + react: '>=16.8' + dependencies: + '@remix-run/router': 1.7.1 + react: 18.2.0 + dev: false + + /react-router@6.14.2(react@18.2.0): + resolution: {integrity: sha512-09Zss2dE2z+T1D03IheqAFtK4UzQyX8nFPWx6jkwdYzGLXd5ie06A6ezS2fO6zJfEb/SpG6UocN2O1hfD+2urQ==} + engines: {node: '>=14'} + peerDependencies: + react: '>=16.8' + dependencies: + '@remix-run/router': 1.7.2 + react: 18.2.0 + dev: false + + /react@18.2.0: + resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} + engines: {node: '>=0.10.0'} + dependencies: + loose-envify: 1.4.0 + dev: false + + /read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + dev: true + + /read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + dependencies: + '@types/normalize-package-data': 2.4.1 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + dev: true + + /read-yaml-file@1.1.0: + resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} + engines: {node: '>=6'} + dependencies: + graceful-fs: 4.2.11 + js-yaml: 3.14.1 + pify: 4.0.1 + strip-bom: 3.0.0 + dev: true + + /readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /rechoir@0.6.2: + resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} + engines: {node: '>= 0.10'} + dependencies: + resolve: 1.22.2 + dev: true + + /rechoir@0.8.0: + resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} + engines: {node: '>= 10.13.0'} + dependencies: + resolve: 1.22.2 + dev: true + + /redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + dev: true + + /redis-errors@1.2.0: + resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} + engines: {node: '>=4'} + + /redis-parser@3.0.0: + resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} + engines: {node: '>=4'} + dependencies: + redis-errors: 1.2.0 + + /reflect-metadata@0.1.13: + resolution: {integrity: sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==} + + /regenerate-unicode-properties@10.1.0: + resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==} + engines: {node: '>=4'} + dependencies: + regenerate: 1.4.2 + dev: true + + /regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + dev: true + + /regenerator-runtime@0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + + /regenerator-transform@0.15.1: + resolution: {integrity: sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==} + dependencies: + '@babel/runtime': 7.22.6 + dev: true + + /regexp.prototype.flags@1.5.0: + resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + functions-have-names: 1.2.3 + dev: true + + /regexpu-core@5.3.2: + resolution: {integrity: sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==} + engines: {node: '>=4'} + dependencies: + '@babel/regjsgen': 0.8.0 + regenerate: 1.4.2 + regenerate-unicode-properties: 10.1.0 + regjsparser: 0.9.1 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.1.0 + dev: true + + /registry-auth-token@3.3.2: + resolution: {integrity: sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==} + dependencies: + rc: 1.2.8 + safe-buffer: 5.2.1 + dev: true + + /registry-url@3.1.0: + resolution: {integrity: sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==} + engines: {node: '>=0.10.0'} + dependencies: + rc: 1.2.8 + dev: true + + /regjsparser@0.9.1: + resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} + hasBin: true + dependencies: + jsesc: 0.5.0 + dev: true + + /relateurl@0.2.7: + resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} + engines: {node: '>= 0.10'} + dev: true + + /renderkid@3.0.0: + resolution: {integrity: sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==} + dependencies: + css-select: 4.3.0 + dom-converter: 0.2.0 + htmlparser2: 6.1.0 + lodash: 4.17.21 + strip-ansi: 6.0.1 + dev: true + + /repeat-string@1.6.1: + resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} + engines: {node: '>=0.10'} + dev: true + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + /require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + dev: true + + /require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + dev: true + + /requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + dev: true + + /resize-observer-polyfill@1.5.1: + resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} + dev: false + + /resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + dependencies: + resolve-from: 5.0.0 + dev: true + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + dev: true + + /resolve@1.22.2: + resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} + hasBin: true + dependencies: + is-core-module: 2.12.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + dev: true + + /retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + dev: true + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rgbcolor@1.0.1: + resolution: {integrity: sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==} + engines: {node: '>= 0.8.15'} + requiresBuild: true + dev: false + optional: true + + /rimraf@2.7.1: + resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: false + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + + /rimraf@4.4.1: + resolution: {integrity: sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==} + engines: {node: '>=14'} + hasBin: true + dependencies: + glob: 9.3.5 + dev: true + + /rollup-plugin-inject@3.0.2: + resolution: {integrity: sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==} + deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject. + dependencies: + estree-walker: 0.6.1 + magic-string: 0.25.9 + rollup-pluginutils: 2.8.2 + dev: true + + /rollup-plugin-node-polyfills@0.2.1: + resolution: {integrity: sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==} + dependencies: + rollup-plugin-inject: 3.0.2 + dev: true + + /rollup-plugin-terser@7.0.2(rollup@3.21.5): + resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==} + deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser + peerDependencies: + rollup: ^2.0.0 + dependencies: + '@babel/code-frame': 7.22.5 + jest-worker: 26.6.2 + rollup: 3.21.5 + serialize-javascript: 4.0.0 + terser: 5.19.2 + dev: true + + /rollup-plugin-typescript2@0.34.1(rollup@3.21.5)(typescript@5.1.3): + resolution: {integrity: sha512-P4cHLtGikESmqi1CA+tdMDUv8WbQV48mzPYt77TSTOPJpERyZ9TXdDgjSDix8Fkqce6soYz3+fa4lrC93IEkcw==} + peerDependencies: + rollup: '>=1.26.3' + typescript: '>=2.4.0' + dependencies: + '@rollup/pluginutils': 4.2.1 + find-cache-dir: 3.3.2 + fs-extra: 10.1.0 + rollup: 3.21.5 + semver: 7.5.4 + tslib: 2.6.0 + typescript: 5.1.3 + dev: true + + /rollup-pluginutils@2.8.2: + resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} + dependencies: + estree-walker: 0.6.1 + dev: true + + /rollup@3.21.5: + resolution: {integrity: sha512-a4NTKS4u9PusbUJcfF4IMxuqjFzjm6ifj76P54a7cKnvVzJaG12BLVR+hgU2YDGHzyMMQNxLAZWuALsn8q2oQg==} + engines: {node: '>=14.18.0', npm: '>=8.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /rollup@3.27.0: + resolution: {integrity: sha512-aOltLCrYZ0FhJDm7fCqwTjIUEVjWjcydKBV/Zeid6Mn8BWgDCUBBWT5beM5ieForYNo/1ZHuGJdka26kvQ3Gzg==} + engines: {node: '>=14.18.0', npm: '>=8.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /run-async@2.4.1: + resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} + engines: {node: '>=0.12.0'} + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /rxjs@6.6.7: + resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} + engines: {npm: '>=2.0.0'} + dependencies: + tslib: 1.14.1 + dev: true + + /rxjs@7.8.1: + resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + dependencies: + tslib: 2.6.0 + + /safe-array-concat@1.0.0: + resolution: {integrity: sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + has-symbols: 1.0.3 + isarray: 2.0.5 + dev: true + + /safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + /safe-regex-test@1.0.0: + resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-regex: 1.1.4 + dev: true + + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + /sax@1.2.4: + resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} + + /scheduler@0.23.0: + resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} + dependencies: + loose-envify: 1.4.0 + dev: false + + /schema-utils@3.3.0: + resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/json-schema': 7.0.12 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + dev: true + + /schema-utils@4.2.0: + resolution: {integrity: sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==} + engines: {node: '>= 12.13.0'} + dependencies: + '@types/json-schema': 7.0.12 + ajv: 8.12.0 + ajv-formats: 2.1.1(ajv@8.12.0) + ajv-keywords: 5.1.0(ajv@8.12.0) + dev: true + + /scroll-into-view-if-needed@3.0.10: + resolution: {integrity: sha512-t44QCeDKAPf1mtQH3fYpWz8IM/DyvHLjs8wUvvwMYxk5moOqCzrMSxK6HQVD0QVmVjXFavoFIPRVrMuJPKAvtg==} + dependencies: + compute-scroll-into-view: 3.0.3 + dev: false + + /sdk-base@3.6.0: + resolution: {integrity: sha512-jxHUIrRLlAoRFRwiXKhOGjd6BeFWO/jz7tv+E7lbMSef6F9jzFN2Sv3hLW58oDDKscKaBGG6vQdkbXn7isE7fw==} + dependencies: + await-event: 2.1.0 + await-first: 1.0.0 + co: 4.6.0 + is-type-of: 1.4.0 + dev: false + + /select-hose@2.0.0: + resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} + dev: true + + /selfsigned@2.1.1: + resolution: {integrity: sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==} + engines: {node: '>=10'} + dependencies: + node-forge: 1.3.1 + dev: true + + /semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + + /send@0.18.0: + resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + engines: {node: '>= 0.8.0'} + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + + /seq-queue@0.0.5: + resolution: {integrity: sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==} + dev: false + + /serialize-javascript@4.0.0: + resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==} + dependencies: + randombytes: 2.1.0 + dev: true + + /serialize-javascript@6.0.1: + resolution: {integrity: sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==} + dependencies: + randombytes: 2.1.0 + dev: true + + /serialize-json@1.0.3: + resolution: {integrity: sha512-TJvXOXSUEH4Lh2FNy1mYzNkUyBG7Ti5fRKGAbcpaDX3mLq23aT/5unC+cIFc5JTDi4/BHTaYLhynrboCCYrFaQ==} + engines: {node: '>= 4.0.0'} + dependencies: + debug: 3.2.7 + is-type-of: 1.4.0 + utility: 1.18.0 + transitivePeerDependencies: + - supports-color + dev: false + + /serve-handler@6.1.5: + resolution: {integrity: sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==} + dependencies: + bytes: 3.0.0 + content-disposition: 0.5.2 + fast-url-parser: 1.1.3 + mime-types: 2.1.18 + minimatch: 3.1.2 + path-is-inside: 1.0.2 + path-to-regexp: 2.2.1 + range-parser: 1.2.0 + dev: true + + /serve-index@1.9.1: + resolution: {integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==} + engines: {node: '>= 0.8.0'} + dependencies: + accepts: 1.3.8 + batch: 0.6.1 + debug: 2.6.9 + escape-html: 1.0.3 + http-errors: 1.6.3 + mime-types: 2.1.35 + parseurl: 1.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /serve-static@1.15.0: + resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.18.0 + transitivePeerDependencies: + - supports-color + + /serve@14.2.0: + resolution: {integrity: sha512-+HOw/XK1bW8tw5iBilBz/mJLWRzM8XM6MPxL4J/dKzdxq1vfdEWSwhaR7/yS8EJp5wzvP92p1qirysJvnEtjXg==} + engines: {node: '>= 14'} + hasBin: true + dependencies: + '@zeit/schemas': 2.29.0 + ajv: 8.11.0 + arg: 5.0.2 + boxen: 7.0.0 + chalk: 5.0.1 + chalk-template: 0.4.0 + clipboardy: 3.0.0 + compression: 1.7.4 + is-port-reachable: 4.0.0 + serve-handler: 6.1.5 + update-check: 1.5.4 + transitivePeerDependencies: + - supports-color + dev: true + + /set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + + /setprototypeof@1.1.0: + resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==} + dev: true + + /setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + /sha.js@2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /shallow-clone@3.0.1: + resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} + engines: {node: '>=8'} + dependencies: + kind-of: 6.0.3 + dev: true + + /shebang-command@1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + dependencies: + shebang-regex: 1.0.0 + dev: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + + /shebang-regex@1.0.0: + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} + engines: {node: '>=0.10.0'} + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + /shell-quote@1.8.1: + resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} + dev: true + + /shelljs@0.8.5: + resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} + engines: {node: '>=4'} + hasBin: true + dependencies: + glob: 7.2.3 + interpret: 1.4.0 + rechoir: 0.6.2 + dev: true + + /side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + object-inspect: 1.12.3 + + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + /sirv@1.0.19: + resolution: {integrity: sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==} + engines: {node: '>= 10'} + dependencies: + '@polka/url': 1.0.0-next.21 + mrmime: 1.0.1 + totalist: 1.1.0 + dev: true + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /slash@4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} + dev: true + + /smartwrap@2.0.2: + resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==} + engines: {node: '>=6'} + hasBin: true + dependencies: + array.prototype.flat: 1.3.1 + breakword: 1.0.6 + grapheme-splitter: 1.0.4 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + yargs: 15.4.1 + dev: true + + /sockjs@0.3.24: + resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} + dependencies: + faye-websocket: 0.11.4 + uuid: 8.3.2 + websocket-driver: 0.7.4 + dev: true + + /source-map-js@1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map@0.7.3: + resolution: {integrity: sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==} + engines: {node: '>= 8'} + dev: true + + /source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + dev: true + + /sourcemap-codec@1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead + dev: true + + /spawndamnit@2.0.0: + resolution: {integrity: sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==} + dependencies: + cross-spawn: 5.1.0 + signal-exit: 3.0.7 + dev: true + + /spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.13 + dev: true + + /spdx-exceptions@2.3.0: + resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + dev: true + + /spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + dependencies: + spdx-exceptions: 2.3.0 + spdx-license-ids: 3.0.13 + dev: true + + /spdx-license-ids@3.0.13: + resolution: {integrity: sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==} + dev: true + + /spdy-transport@3.0.0: + resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} + dependencies: + debug: 4.3.4 + detect-node: 2.1.0 + hpack.js: 2.1.6 + obuf: 1.1.2 + readable-stream: 3.6.2 + wbuf: 1.7.3 + transitivePeerDependencies: + - supports-color + dev: true + + /spdy@4.0.2: + resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} + engines: {node: '>=6.0.0'} + dependencies: + debug: 4.3.4 + handle-thing: 2.0.1 + http-deceiver: 1.2.7 + select-hose: 2.0.0 + spdy-transport: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /speed-measure-webpack-plugin@1.5.0(webpack@5.75.0): + resolution: {integrity: sha512-Re0wX5CtM6gW7bZA64ONOfEPEhwbiSF/vz6e2GvadjuaPrQcHTQdRGsD8+BE7iUOysXH8tIenkPCQBEcspXsNg==} + engines: {node: '>=6.0.0'} + peerDependencies: + webpack: ^1 || ^2 || ^3 || ^4 || ^5 + dependencies: + chalk: 4.1.2 + webpack: 5.75.0(webpack-cli@5.0.2) + dev: true + + /split-on-first@1.1.0: + resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==} + engines: {node: '>=6'} + dev: false + + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: true + + /sqlstring@2.3.3: + resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==} + engines: {node: '>= 0.6'} + dev: false + + /stackblur-canvas@2.6.0: + resolution: {integrity: sha512-8S1aIA+UoF6erJYnglGPug6MaHYGo1Ot7h5fuXx4fUPvcvQfcdw2o/ppCse63+eZf8PPidSu4v1JnmEVtEDnpg==} + engines: {node: '>=0.1.14'} + requiresBuild: true + dev: false + optional: true + + /stackframe@1.3.4: + resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} + dev: true + + /standard-as-callback@2.1.0: + resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} + + /statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + + /statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + /std-env@3.3.3: + resolution: {integrity: sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==} + dev: true + + /stream-transform@2.1.3: + resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} + dependencies: + mixme: 0.5.9 + dev: true + + /streamsearch@1.1.0: + resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} + engines: {node: '>=10.0.0'} + + /strict-uri-encode@2.0.0: + resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} + engines: {node: '>=4'} + dev: false + + /string-convert@0.2.1: + resolution: {integrity: sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==} + dev: false + + /string-width@2.1.1: + resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} + engines: {node: '>=4'} + dependencies: + is-fullwidth-code-point: 2.0.0 + strip-ansi: 4.0.0 + dev: true + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + dev: true + + /string.prototype.trim@1.2.7: + resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + dev: true + + /string.prototype.trimend@1.0.6: + resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + dev: true + + /string.prototype.trimstart@1.0.6: + resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + dev: true + + /string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + dependencies: + safe-buffer: 5.1.2 + + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + + /strip-ansi@3.0.1: + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-regex: 2.1.1 + dev: true + + /strip-ansi@4.0.0: + resolution: {integrity: sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==} + engines: {node: '>=4'} + dependencies: + ansi-regex: 3.0.1 + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: true + + /strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + dev: true + + /strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: true + + /strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + dependencies: + min-indent: 1.0.1 + dev: true + + /strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /strnum@1.0.5: + resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} + dev: false + + /style-loader@3.3.2(webpack@5.75.0): + resolution: {integrity: sha512-RHs/vcrKdQK8wZliteNK4NKzxvLBzpuHMqYmUVWeKa6MkaIQ97ZTOS0b+zapZhy6GcrgWnvWYCMHRirC3FsUmw==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + dependencies: + webpack: 5.75.0(webpack-cli@5.0.2) + dev: true + + /stylehacks@6.0.0(postcss@8.4.27): + resolution: {integrity: sha512-+UT589qhHPwz6mTlCLSt/vMNTJx8dopeJlZAlBMJPWA3ORqu6wmQY7FBXf+qD+FsqoBJODyqNxOUP3jdntFRdw==} + engines: {node: ^14 || ^16 || >=18.0} + peerDependencies: + postcss: ^8.2.15 + dependencies: + browserslist: 4.21.10 + postcss: 8.4.27 + postcss-selector-parser: 6.0.13 + dev: true + + /stylis@4.3.0: + resolution: {integrity: sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==} + dev: false + + /superagent@8.0.9: + resolution: {integrity: sha512-4C7Bh5pyHTvU33KpZgwrNKh/VQnvgtCSqPRfJAUdmrtSYePVzVg4E4OzsrbkhJj9O7SO6Bnv75K/F8XVZT8YHA==} + engines: {node: '>=6.4.0 <13 || >=14'} + dependencies: + component-emitter: 1.3.0 + cookiejar: 2.1.4 + debug: 4.3.4 + fast-safe-stringify: 2.1.1 + form-data: 4.0.0 + formidable: 2.1.2 + methods: 1.1.2 + mime: 2.6.0 + qs: 6.11.2 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + dev: true + + /supertest@6.3.3: + resolution: {integrity: sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA==} + engines: {node: '>=6.4.0'} + dependencies: + methods: 1.1.2 + superagent: 8.0.9 + transitivePeerDependencies: + - supports-color + dev: true + + /supports-color@2.0.0: + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} + engines: {node: '>=0.8.0'} + dev: true + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + + /supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /svg-pathdata@6.0.3: + resolution: {integrity: sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==} + engines: {node: '>=12.0.0'} + requiresBuild: true + dev: false + optional: true + + /svgo@3.0.2: + resolution: {integrity: sha512-Z706C1U2pb1+JGP48fbazf3KxHrWOsLme6Rv7imFBn5EnuanDW1GPaA/P1/dvObE670JDePC3mnj0k0B7P0jjQ==} + engines: {node: '>=14.0.0'} + hasBin: true + dependencies: + '@trysound/sax': 0.2.0 + commander: 7.2.0 + css-select: 5.1.0 + css-tree: 2.3.1 + csso: 5.0.5 + picocolors: 1.0.0 + dev: true + + /symbol-observable@4.0.0: + resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} + engines: {node: '>=0.10'} + dev: true + + /tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + dev: true + + /tar@6.1.15: + resolution: {integrity: sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==} + engines: {node: '>=10'} + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + dev: false + + /tcp-base@3.1.1: + resolution: {integrity: sha512-6wS2yvxq7xqhlpjHPLCYsuy6hIu1HFP3vDqfa1swjQ14MHIz2TW32CvY3hOrt6eM0tmUmy+1rsy52JKqD9hkjQ==} + engines: {node: '>= 6.0.0'} + dependencies: + is-type-of: 1.4.0 + sdk-base: 3.6.0 + dev: false + + /term-size@2.2.1: + resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} + engines: {node: '>=8'} + dev: true + + /terser-webpack-plugin@5.3.7(webpack@5.73.0): + resolution: {integrity: sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true + dependencies: + '@jridgewell/trace-mapping': 0.3.18 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.1 + terser: 5.19.2 + webpack: 5.73.0 + dev: true + + /terser-webpack-plugin@5.3.7(webpack@5.75.0): + resolution: {integrity: sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true + dependencies: + '@jridgewell/trace-mapping': 0.3.18 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.1 + terser: 5.19.2 + webpack: 5.75.0(webpack-cli@5.0.2) + dev: true + + /terser-webpack-plugin@5.3.7(webpack@5.87.0): + resolution: {integrity: sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true + dependencies: + '@jridgewell/trace-mapping': 0.3.18 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.1 + terser: 5.19.2 + webpack: 5.87.0 + dev: true + + /terser@5.19.2: + resolution: {integrity: sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + '@jridgewell/source-map': 0.3.5 + acorn: 8.10.0 + commander: 2.20.3 + source-map-support: 0.5.21 + dev: true + + /text-segmentation@1.0.3: + resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==} + dependencies: + utrie: 1.0.2 + dev: false + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + dependencies: + thenify: 3.3.1 + dev: false + + /thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + dependencies: + any-promise: 1.3.0 + dev: false + + /throttle-debounce@5.0.0: + resolution: {integrity: sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==} + engines: {node: '>=12.22'} + dev: false + + /through2@4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + dependencies: + readable-stream: 3.6.2 + dev: false + + /through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + + /thunky@1.1.0: + resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} + dev: true + + /tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + dependencies: + os-tmpdir: 1.0.2 + dev: true + + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /toggle-selection@1.0.6: + resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} + dev: false + + /toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + /totalist@1.1.0: + resolution: {integrity: sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==} + engines: {node: '>=6'} + dev: true + + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + /tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + dev: true + + /trim-newlines@3.0.1: + resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} + engines: {node: '>=8'} + dev: true + + /ts-loader@9.4.3(typescript@5.1.3)(webpack@5.75.0): + resolution: {integrity: sha512-n3hBnm6ozJYzwiwt5YRiJZkzktftRpMiBApHaJPoWLA+qetQBAXkHqCLM6nwSdRDimqVtA5ocIkcTRLMTt7yzA==} + engines: {node: '>=12.0.0'} + peerDependencies: + typescript: '*' + webpack: ^5.0.0 + dependencies: + chalk: 4.1.2 + enhanced-resolve: 5.15.0 + micromatch: 4.0.5 + semver: 7.5.4 + typescript: 5.1.3 + webpack: 5.75.0(webpack-cli@5.0.2) + dev: true + + /ts-node@10.9.1(@types/node@18.16.12)(typescript@5.1.3): + resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 18.16.12 + acorn: 8.10.0 + acorn-walk: 8.2.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.1.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + + /ts-node@10.9.1(@types/node@18.16.3)(typescript@5.1.3): + resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 18.16.3 + acorn: 8.10.0 + acorn-walk: 8.2.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.1.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + dev: true + + /ts-node@10.9.1(@types/node@20.3.3)(typescript@5.1.3): + resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.3.3 + acorn: 8.10.0 + acorn-walk: 8.2.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.1.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + + /tsconfig-paths-webpack-plugin@3.5.2: + resolution: {integrity: sha512-EhnfjHbzm5IYI9YPNVIxx1moxMI4bpHD2e0zTXeDNQcwjjRaGepP7IhTHJkyDBG0CAOoxRfe7jCG630Ou+C6Pw==} + dependencies: + chalk: 4.1.2 + enhanced-resolve: 5.15.0 + tsconfig-paths: 3.14.1 + dev: true + + /tsconfig-paths-webpack-plugin@4.0.1: + resolution: {integrity: sha512-m5//KzLoKmqu2MVix+dgLKq70MnFi8YL8sdzQZ6DblmCdfuq/y3OqvJd5vMndg2KEVCOeNz8Es4WVZhYInteLw==} + engines: {node: '>=10.13.0'} + dependencies: + chalk: 4.1.2 + enhanced-resolve: 5.15.0 + tsconfig-paths: 4.2.0 + dev: true + + /tsconfig-paths@3.14.1: + resolution: {integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==} + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + + /tsconfig-paths@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + + /tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: true + + /tslib@2.4.0: + resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} + dev: false + + /tslib@2.5.3: + resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==} + dev: true + + /tslib@2.6.0: + resolution: {integrity: sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==} + + /tsutils@3.21.0(typescript@5.1.3): + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + dependencies: + tslib: 1.14.1 + typescript: 5.1.3 + dev: true + + /tty-table@4.2.1: + resolution: {integrity: sha512-xz0uKo+KakCQ+Dxj1D/tKn2FSyreSYWzdkL/BYhgN6oMW808g8QRMuh1atAV9fjTPbWBjfbkKQpI/5rEcnAc7g==} + engines: {node: '>=8.0.0'} + hasBin: true + dependencies: + chalk: 4.1.2 + csv: 5.5.3 + kleur: 4.1.5 + smartwrap: 2.0.2 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + yargs: 17.7.2 + dev: true + + /tweetnacl@1.0.3: + resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-fest@0.13.1: + resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + dev: true + + /type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + dev: true + + /type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + dev: true + + /type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + /typed-array-buffer@1.0.0: + resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-length@1.0.0: + resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-offset@1.0.0: + resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} + engines: {node: '>= 0.4'} + 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.12 + dev: true + + /typed-array-length@1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + dependencies: + call-bind: 1.0.2 + for-each: 0.3.3 + is-typed-array: 1.1.12 + dev: true + + /typedarray@0.0.6: + resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} + + /typeorm@0.3.16(mysql2@3.3.3)(ts-node@10.9.1): + resolution: {integrity: sha512-wJ4Qy1oqRKNDdZiBTTaVMqwo/XxC52Q7uNPTjltPgLhvIW173bL6Iad0lhptMOsFlpixFPaUu3PNziaRBwX2Zw==} + engines: {node: '>= 12.9.0'} + hasBin: true + peerDependencies: + '@google-cloud/spanner': ^5.18.0 + '@sap/hana-client': ^2.12.25 + better-sqlite3: ^7.1.2 || ^8.0.0 + hdb-pool: ^0.1.6 + ioredis: ^5.0.4 + mongodb: ^5.2.0 + mssql: ^9.1.1 + mysql2: ^2.2.5 || ^3.0.1 + oracledb: ^5.1.0 + pg: ^8.5.1 + pg-native: ^3.0.0 + pg-query-stream: ^4.0.0 + redis: ^3.1.1 || ^4.0.0 + sql.js: ^1.4.0 + sqlite3: ^5.0.3 + ts-node: ^10.7.0 + typeorm-aurora-data-api-driver: ^2.0.0 + peerDependenciesMeta: + '@google-cloud/spanner': + optional: true + '@sap/hana-client': + optional: true + better-sqlite3: + optional: true + hdb-pool: + optional: true + ioredis: + optional: true + mongodb: + optional: true + mssql: + optional: true + mysql2: + optional: true + oracledb: + optional: true + pg: + optional: true + pg-native: + optional: true + pg-query-stream: + optional: true + redis: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + ts-node: + optional: true + typeorm-aurora-data-api-driver: + optional: true + dependencies: + '@sqltools/formatter': 1.2.5 + app-root-path: 3.1.0 + buffer: 6.0.3 + chalk: 4.1.2 + cli-highlight: 2.1.11 + date-fns: 2.30.0 + debug: 4.3.4 + dotenv: 16.0.3 + glob: 8.1.0 + mkdirp: 2.1.6 + mysql2: 3.3.3 + reflect-metadata: 0.1.13 + sha.js: 2.4.11 + ts-node: 10.9.1(@types/node@18.16.12)(typescript@5.1.3) + tslib: 2.6.0 + uuid: 9.0.0 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + dev: false + + /typeorm@0.3.16(ts-node@10.9.1): + resolution: {integrity: sha512-wJ4Qy1oqRKNDdZiBTTaVMqwo/XxC52Q7uNPTjltPgLhvIW173bL6Iad0lhptMOsFlpixFPaUu3PNziaRBwX2Zw==} + engines: {node: '>= 12.9.0'} + hasBin: true + peerDependencies: + '@google-cloud/spanner': ^5.18.0 + '@sap/hana-client': ^2.12.25 + better-sqlite3: ^7.1.2 || ^8.0.0 + hdb-pool: ^0.1.6 + ioredis: ^5.0.4 + mongodb: ^5.2.0 + mssql: ^9.1.1 + mysql2: ^2.2.5 || ^3.0.1 + oracledb: ^5.1.0 + pg: ^8.5.1 + pg-native: ^3.0.0 + pg-query-stream: ^4.0.0 + redis: ^3.1.1 || ^4.0.0 + sql.js: ^1.4.0 + sqlite3: ^5.0.3 + ts-node: ^10.7.0 + typeorm-aurora-data-api-driver: ^2.0.0 + peerDependenciesMeta: + '@google-cloud/spanner': + optional: true + '@sap/hana-client': + optional: true + better-sqlite3: + optional: true + hdb-pool: + optional: true + ioredis: + optional: true + mongodb: + optional: true + mssql: + optional: true + mysql2: + optional: true + oracledb: + optional: true + pg: + optional: true + pg-native: + optional: true + pg-query-stream: + optional: true + redis: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + ts-node: + optional: true + typeorm-aurora-data-api-driver: + optional: true + dependencies: + '@sqltools/formatter': 1.2.5 + app-root-path: 3.1.0 + buffer: 6.0.3 + chalk: 4.1.2 + cli-highlight: 2.1.11 + date-fns: 2.30.0 + debug: 4.3.4 + dotenv: 16.0.3 + glob: 8.1.0 + mkdirp: 2.1.6 + reflect-metadata: 0.1.13 + sha.js: 2.4.11 + ts-node: 10.9.1(@types/node@20.3.3)(typescript@5.1.3) + tslib: 2.6.0 + uuid: 9.0.0 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + dev: false + + /typeorm@0.3.17(ts-node@10.9.1): + resolution: {integrity: sha512-UDjUEwIQalO9tWw9O2A4GU+sT3oyoUXheHJy4ft+RFdnRdQctdQ34L9SqE2p7LdwzafHx1maxT+bqXON+Qnmig==} + engines: {node: '>= 12.9.0'} + hasBin: true + peerDependencies: + '@google-cloud/spanner': ^5.18.0 + '@sap/hana-client': ^2.12.25 + better-sqlite3: ^7.1.2 || ^8.0.0 + hdb-pool: ^0.1.6 + ioredis: ^5.0.4 + mongodb: ^5.2.0 + mssql: ^9.1.1 + mysql2: ^2.2.5 || ^3.0.1 + oracledb: ^5.1.0 + pg: ^8.5.1 + pg-native: ^3.0.0 + pg-query-stream: ^4.0.0 + redis: ^3.1.1 || ^4.0.0 + sql.js: ^1.4.0 + sqlite3: ^5.0.3 + ts-node: ^10.7.0 + typeorm-aurora-data-api-driver: ^2.0.0 + peerDependenciesMeta: + '@google-cloud/spanner': + optional: true + '@sap/hana-client': + optional: true + better-sqlite3: + optional: true + hdb-pool: + optional: true + ioredis: + optional: true + mongodb: + optional: true + mssql: + optional: true + mysql2: + optional: true + oracledb: + optional: true + pg: + optional: true + pg-native: + optional: true + pg-query-stream: + optional: true + redis: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + ts-node: + optional: true + typeorm-aurora-data-api-driver: + optional: true + dependencies: + '@sqltools/formatter': 1.2.5 + app-root-path: 3.1.0 + buffer: 6.0.3 + chalk: 4.1.2 + cli-highlight: 2.1.11 + date-fns: 2.30.0 + debug: 4.3.4 + dotenv: 16.1.4 + glob: 8.1.0 + mkdirp: 2.1.6 + reflect-metadata: 0.1.13 + sha.js: 2.4.11 + ts-node: 10.9.1(@types/node@18.16.12)(typescript@5.1.3) + tslib: 2.6.0 + uuid: 9.0.0 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + dev: false + + /typescript@4.7.4: + resolution: {integrity: sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + + /typescript@5.1.3: + resolution: {integrity: sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==} + engines: {node: '>=14.17'} + hasBin: true + + /uid@2.0.2: + resolution: {integrity: sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==} + engines: {node: '>=8'} + dependencies: + '@lukeed/csprng': 1.1.0 + + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.2 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + + /unescape@1.0.1: + resolution: {integrity: sha512-O0+af1Gs50lyH1nUu3ZyYS1cRh01Q/kUKatTOkSs7jukXE6/NebucDVxyiDsA9AQ4JC1V1jUH9EO8JX2nMDgGQ==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 2.0.1 + dev: false + + /unicode-canonical-property-names-ecmascript@2.0.0: + resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} + engines: {node: '>=4'} + dev: true + + /unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.0 + unicode-property-aliases-ecmascript: 2.1.0 + dev: true + + /unicode-match-property-value-ecmascript@2.1.0: + resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} + engines: {node: '>=4'} + dev: true + + /unicode-property-aliases-ecmascript@2.1.0: + resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} + engines: {node: '>=4'} + dev: true + + /universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + dev: true + + /universalify@2.0.0: + resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} + engines: {node: '>= 10.0.0'} + dev: true + + /unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + /update-browserslist-db@1.0.11(browserslist@4.21.10): + resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.21.10 + escalade: 3.1.1 + picocolors: 1.0.0 + dev: true + + /update-check@1.5.4: + resolution: {integrity: sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==} + dependencies: + registry-auth-token: 3.3.2 + registry-url: 3.1.0 + dev: true + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.0 + dev: true + + /urlencode@1.1.0: + resolution: {integrity: sha512-OOAOh9owHXr/rCN1tteSnYwIvsrGHamSz0hafMhmQa7RcS4+Ets6/2iVClVGjt9jkDW84UqoMw/Gmpc7QolX6A==} + dependencies: + iconv-lite: 0.4.24 + dev: false + + /urllib@2.41.0: + resolution: {integrity: sha512-pNXdxEv52L67jahLT+/7QE+Fup1y2Gc6EdmrAhQ6OpQIC2rl14oWwv9hvk1GXOZqEnJNwRXHABuwgPOs1CtL7g==} + engines: {node: '>= 0.10.0'} + peerDependencies: + proxy-agent: ^5.0.0 + peerDependenciesMeta: + proxy-agent: + optional: true + dependencies: + any-promise: 1.3.0 + content-type: 1.0.5 + debug: 2.6.9 + default-user-agent: 1.0.0 + digest-header: 1.1.0 + ee-first: 1.1.1 + formstream: 1.3.1 + humanize-ms: 1.2.1 + iconv-lite: 0.4.24 + ip: 1.1.8 + pump: 3.0.0 + qs: 6.11.2 + statuses: 1.5.0 + utility: 1.18.0 + transitivePeerDependencies: + - supports-color + dev: false + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + /util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + dependencies: + inherits: 2.0.4 + is-arguments: 1.1.1 + is-generator-function: 1.0.10 + is-typed-array: 1.1.12 + which-typed-array: 1.1.11 + dev: false + + /utila@0.4.0: + resolution: {integrity: sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==} + dev: true + + /utility@1.18.0: + resolution: {integrity: sha512-PYxZDA+6QtvRvm//++aGdmKG/cI07jNwbROz0Ql+VzFV1+Z0Dy55NI4zZ7RHc9KKpBePNFwoErqIuqQv/cjiTA==} + engines: {node: '>= 0.12.0'} + dependencies: + copy-to: 2.0.1 + escape-html: 1.0.3 + mkdirp: 0.5.6 + mz: 2.7.0 + unescape: 1.0.1 + dev: false + + /utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + /utrie@1.0.2: + resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==} + dependencies: + base64-arraybuffer: 1.0.2 + dev: false + + /uuid@3.4.0: + resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} + deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + hasBin: true + dev: false + + /uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + /uuid@9.0.0: + resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} + hasBin: true + dev: false + + /v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + /validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + dev: true + + /validator@13.9.0: + resolution: {integrity: sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==} + engines: {node: '>= 0.10'} + + /vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + /vite@4.4.0: + resolution: {integrity: sha512-Wf+DCEjuM8aGavEYiF77hnbxEZ+0+/jC9nABR46sh5Xi+GYeSvkeEFRiVuI3x+tPjxgZeS91h1jTAQTPFgePpA==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + esbuild: 0.18.17 + postcss: 8.4.27 + rollup: 3.27.0 + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /void-elements@3.1.0: + resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} + engines: {node: '>=0.10.0'} + dev: false + + /watchpack@2.4.0: + resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==} + engines: {node: '>=10.13.0'} + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + dev: true + + /wbuf@1.7.3: + resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==} + dependencies: + minimalistic-assert: 1.0.1 + dev: true + + /wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + dependencies: + defaults: 1.0.4 + dev: true + + /web-encoding@1.1.5: + resolution: {integrity: sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==} + dependencies: + util: 0.12.5 + optionalDependencies: + '@zxing/text-encoding': 0.9.0 + dev: false + + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + /webpack-bundle-analyzer@4.8.0: + resolution: {integrity: sha512-ZzoSBePshOKhr+hd8u6oCkZVwpVaXgpw23ScGLFpR6SjYI7+7iIWYarjN6OEYOfRt8o7ZyZZQk0DuMizJ+LEIg==} + engines: {node: '>= 10.13.0'} + hasBin: true + dependencies: + '@discoveryjs/json-ext': 0.5.7 + acorn: 8.10.0 + acorn-walk: 8.2.0 + chalk: 4.1.2 + commander: 7.2.0 + gzip-size: 6.0.0 + lodash: 4.17.21 + opener: 1.5.2 + sirv: 1.0.19 + ws: 7.5.9 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /webpack-cli@5.0.2(webpack-bundle-analyzer@4.8.0)(webpack-dev-server@4.13.3)(webpack@5.75.0): + resolution: {integrity: sha512-4y3W5Dawri5+8dXm3+diW6Mn1Ya+Dei6eEVAdIduAmYNLzv1koKVAqsfgrrc9P2mhrYHQphx5htnGkcNwtubyQ==} + engines: {node: '>=14.15.0'} + hasBin: true + peerDependencies: + '@webpack-cli/generators': '*' + webpack: 5.x.x + webpack-bundle-analyzer: '*' + webpack-dev-server: '*' + peerDependenciesMeta: + '@webpack-cli/generators': + optional: true + webpack-bundle-analyzer: + optional: true + webpack-dev-server: + optional: true + dependencies: + '@discoveryjs/json-ext': 0.5.7 + '@webpack-cli/configtest': 2.1.1(webpack-cli@5.0.2)(webpack@5.75.0) + '@webpack-cli/info': 2.0.2(webpack-cli@5.0.2)(webpack@5.75.0) + '@webpack-cli/serve': 2.0.5(webpack-cli@5.0.2)(webpack-dev-server@4.13.3)(webpack@5.75.0) + colorette: 2.0.20 + commander: 10.0.1 + cross-spawn: 7.0.3 + envinfo: 7.10.0 + fastest-levenshtein: 1.0.16 + import-local: 3.1.0 + interpret: 3.1.1 + rechoir: 0.8.0 + webpack: 5.75.0(webpack-cli@5.0.2) + webpack-bundle-analyzer: 4.8.0 + webpack-dev-server: 4.13.3(webpack-cli@5.0.2)(webpack@5.75.0) + webpack-merge: 5.8.0 + dev: true + + /webpack-dev-middleware@5.3.3(webpack@5.75.0): + resolution: {integrity: sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + dependencies: + colorette: 2.0.20 + memfs: 3.5.3 + mime-types: 2.1.35 + range-parser: 1.2.1 + schema-utils: 4.2.0 + webpack: 5.75.0(webpack-cli@5.0.2) + dev: true + + /webpack-dev-server@4.13.3(webpack-cli@5.0.2)(webpack@5.75.0): + resolution: {integrity: sha512-KqqzrzMRSRy5ePz10VhjyL27K2dxqwXQLP5rAKwRJBPUahe7Z2bBWzHw37jeb8GCPKxZRO79ZdQUAPesMh/Nug==} + engines: {node: '>= 12.13.0'} + hasBin: true + peerDependencies: + webpack: ^4.37.0 || ^5.0.0 + webpack-cli: '*' + peerDependenciesMeta: + webpack: + optional: true + webpack-cli: + optional: true + dependencies: + '@types/bonjour': 3.5.10 + '@types/connect-history-api-fallback': 1.5.0 + '@types/express': 4.17.17 + '@types/serve-index': 1.9.1 + '@types/serve-static': 1.15.2 + '@types/sockjs': 0.3.33 + '@types/ws': 8.5.5 + ansi-html-community: 0.0.8 + bonjour-service: 1.1.1 + chokidar: 3.5.3 + colorette: 2.0.20 + compression: 1.7.4 + connect-history-api-fallback: 2.0.0 + default-gateway: 6.0.3 + express: 4.18.2 + graceful-fs: 4.2.11 + html-entities: 2.4.0 + http-proxy-middleware: 2.0.6(@types/express@4.17.17) + ipaddr.js: 2.1.0 + launch-editor: 2.6.0 + open: 8.4.2 + p-retry: 4.6.2 + rimraf: 3.0.2 + schema-utils: 4.2.0 + selfsigned: 2.1.1 + serve-index: 1.9.1 + sockjs: 0.3.24 + spdy: 4.0.2 + webpack: 5.75.0(webpack-cli@5.0.2) + webpack-cli: 5.0.2(webpack-bundle-analyzer@4.8.0)(webpack-dev-server@4.13.3)(webpack@5.75.0) + webpack-dev-middleware: 5.3.3(webpack@5.75.0) + ws: 8.13.0 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + dev: true + + /webpack-merge@5.8.0: + resolution: {integrity: sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==} + engines: {node: '>=10.0.0'} + dependencies: + clone-deep: 4.0.1 + wildcard: 2.0.1 + dev: true + + /webpack-node-externals@3.0.0: + resolution: {integrity: sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==} + engines: {node: '>=6'} + dev: true + + /webpack-sources@3.2.3: + resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} + engines: {node: '>=10.13.0'} + dev: true + + /webpack@5.73.0: + resolution: {integrity: sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + dependencies: + '@types/eslint-scope': 3.7.4 + '@types/estree': 0.0.51 + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/wasm-edit': 1.11.1 + '@webassemblyjs/wasm-parser': 1.11.1 + acorn: 8.10.0 + acorn-import-assertions: 1.9.0(acorn@8.10.0) + browserslist: 4.21.10 + chrome-trace-event: 1.0.3 + enhanced-resolve: 5.15.0 + es-module-lexer: 0.9.3 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.3.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.7(webpack@5.73.0) + watchpack: 2.4.0 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + dev: true + + /webpack@5.75.0(webpack-cli@5.0.2): + resolution: {integrity: sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + dependencies: + '@types/eslint-scope': 3.7.4 + '@types/estree': 0.0.51 + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/wasm-edit': 1.11.1 + '@webassemblyjs/wasm-parser': 1.11.1 + acorn: 8.10.0 + acorn-import-assertions: 1.9.0(acorn@8.10.0) + browserslist: 4.21.10 + chrome-trace-event: 1.0.3 + enhanced-resolve: 5.15.0 + es-module-lexer: 0.9.3 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.3.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.7(webpack@5.75.0) + watchpack: 2.4.0 + webpack-cli: 5.0.2(webpack-bundle-analyzer@4.8.0)(webpack-dev-server@4.13.3)(webpack@5.75.0) + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + dev: true + + /webpack@5.87.0: + resolution: {integrity: sha512-GOu1tNbQ7p1bDEoFRs2YPcfyGs8xq52yyPBZ3m2VGnXGtV9MxjrkABHm4V9Ia280OefsSLzvbVoXcfLxjKY/Iw==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + dependencies: + '@types/eslint-scope': 3.7.4 + '@types/estree': 1.0.1 + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/wasm-edit': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + acorn: 8.10.0 + acorn-import-assertions: 1.9.0(acorn@8.10.0) + browserslist: 4.21.10 + chrome-trace-event: 1.0.3 + enhanced-resolve: 5.15.0 + es-module-lexer: 1.3.0 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.3.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.7(webpack@5.87.0) + watchpack: 2.4.0 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + dev: true + + /webpackbar@5.0.2(webpack@5.75.0): + resolution: {integrity: sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ==} + engines: {node: '>=12'} + peerDependencies: + webpack: 3 || 4 || 5 + dependencies: + chalk: 4.1.2 + consola: 2.15.3 + pretty-time: 1.1.0 + std-env: 3.3.3 + webpack: 5.75.0(webpack-cli@5.0.2) + dev: true + + /websocket-driver@0.7.4: + resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} + engines: {node: '>=0.8.0'} + dependencies: + http-parser-js: 0.5.8 + safe-buffer: 5.2.1 + websocket-extensions: 0.1.4 + dev: true + + /websocket-extensions@0.1.4: + resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} + engines: {node: '>=0.8.0'} + dev: true + + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + dev: true + + /which-pm@2.0.0: + resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} + engines: {node: '>=8.15'} + dependencies: + load-yaml-file: 0.2.0 + path-exists: 4.0.0 + dev: true + + /which-typed-array@1.1.11: + resolution: {integrity: sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==} + engines: {node: '>= 0.4'} + 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.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + + /wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + dependencies: + string-width: 4.2.3 + dev: false + + /widest-line@4.0.1: + resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} + engines: {node: '>=12'} + dependencies: + string-width: 5.1.2 + dev: true + + /wildcard@2.0.1: + resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==} + dev: true + + /win-release@1.1.1: + resolution: {integrity: sha512-iCRnKVvGxOQdsKhcQId2PXV1vV3J/sDPXKA4Oe9+Eti2nb2ESEsYHRYls/UjoUW3bIc5ZDO8dTH50A/5iVN+bw==} + engines: {node: '>=0.10.0'} + dependencies: + semver: 5.7.2 + dev: false + + /windows-release@4.0.0: + resolution: {integrity: sha512-OxmV4wzDKB1x7AZaZgXMVsdJ1qER1ed83ZrTYd5Bwq2HfJVg3DJS8nqlAG4sMoJ7mu8cuRmLEYyU13BKwctRAg==} + engines: {node: '>=10'} + dependencies: + execa: 4.1.0 + dev: true + + /wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + /ws@7.5.9: + resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: true + + /ws@8.13.0: + resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: true + + /xml2js@0.5.0: + resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} + engines: {node: '>=4.0.0'} + dependencies: + sax: 1.2.4 + xmlbuilder: 11.0.1 + dev: false + + /xml@1.0.1: + resolution: {integrity: sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==} + dev: false + + /xmlbuilder@11.0.1: + resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} + engines: {node: '>=4.0'} + dev: false + + /xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + + /y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + dev: true + + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + /yallist@2.1.2: + resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + dev: true + + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: true + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + /yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + dev: true + + /yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + dev: true + + /yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + dev: false + + /yargs-parser@21.0.1: + resolution: {integrity: sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==} + engines: {node: '>=12'} + dev: true + + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + /yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 18.1.3 + dev: true + + /yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + dependencies: + cliui: 7.0.4 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + dev: false + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + /yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..5c66c6a --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,7 @@ +packages: + # 基础库级别在 packages/ + - "packages/*" + # 应用级别在 apps/ + - "apps/**" + # 排除测试目录中test + - "!**/test/**" diff --git a/terminal.sh b/terminal.sh new file mode 100755 index 0000000..6c7ad95 --- /dev/null +++ b/terminal.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# 数据管理平台 web +osascript -e "tell app \"Terminal\" to do script \"cd $PWD && pnpm dev:dmp-web\"" + +# 数据管理平台 网关 +osascript -e "tell app \"Terminal\" to do script \"cd $PWD && pnpm dev:dmp-gateway\"" + +# 主动脉 web +osascript -e "tell app \"Terminal\" to do script \"cd $PWD && pnpm dev:aorta\"" + +# 主动脉 网关 +osascript -e "tell app \"Terminal\" to do script \"cd $PWD && pnpm dev:aorta-gateway\"" + +# 认证中心 web +osascript -e "tell app \"Terminal\" to do script \"cd $PWD && pnpm dev:cert-web\"" + +# 认证中心 网关 +osascript -e "tell app \"Terminal\" to do script \"cd $PWD && pnpm dev:cert-gateway\"" + +# 认证中心 认证服务 +osascript -e "tell app \"Terminal\" to do script \"cd $PWD && pnpm dev:authenticate\"" + +# 认证中心 鉴权服务 +osascript -e "tell app \"Terminal\" to do script \"cd $PWD && pnpm dev:authorize\"" + +# 日志服务 +osascript -e "tell app \"Terminal\" to do script \"cd $PWD && pnpm dev:logger\""