From 6f372640479ad683667b832c86ab0e933c507b74 Mon Sep 17 00:00:00 2001 From: Disciple_C Date: Tue, 14 Jul 2026 10:31:17 +0800 Subject: [PATCH] feat: Architecture initialization --- .editorconfig | 15 + .env | 3 + .env.development | 4 + .env.production | 3 + .env.test | 3 + .eslintignore | 6 + .eslintrc.cjs | 45 + .gitignore | 42 + .husky/commit-msg | 4 + .husky/pre-commit | 4 + .prettierignore | 9 + .prettierrc | 14 + .vscode/extensions.json | 10 + .vscode/settings.json | 24 + README.md | 142 + commitlint.config.js | 28 + index.html | 14 + package-lock.json | 5999 +++++++++++++++++++++++++ package.json | 64 + public/favicon.svg | 4 + src/App.tsx | 25 + src/api/index.ts | 29 + src/assets/styles/index.less | 57 + src/assets/styles/variables.less | 19 + src/components/HelloWorld.module.less | 16 + src/components/HelloWorld.tsx | 27 + src/components/index.ts | 5 + src/env.d.ts | 13 + src/hooks/index.ts | 10 + src/hooks/useAuth.ts | 34 + src/hooks/useBasicLayout.ts | 46 + src/hooks/useBreadcrumb.ts | 67 + src/hooks/useContext.ts | 137 + src/hooks/useDebounce.ts | 80 + src/hooks/useEffect.ts | 32 + src/hooks/usePagination.ts | 185 + src/hooks/useRequest.ts | 170 + src/hooks/useState.ts | 17 + src/hooks/useWebSocket.ts | 245 + src/layouts/BasicLayout.module.less | 57 + src/layouts/BasicLayout.tsx | 71 + src/main.ts | 14 + src/pages/login/index.module.less | 20 + src/pages/login/index.tsx | 83 + src/router/index.ts | 40 + src/router/routes.ts | 68 + src/router/utils.ts | 40 + src/types/index.ts | 42 + src/utils/index.ts | 90 + src/utils/request.ts | 164 + src/views/About.module.less | 20 + src/views/About.tsx | 42 + src/views/Dashboard.module.less | 27 + src/views/Dashboard.tsx | 67 + src/views/NotFound.tsx | 32 + start-debug.js | 131 + tsconfig.json | 27 + tsconfig.node.json | 12 + vite.config.ts | 54 + 59 files changed, 8752 insertions(+) create mode 100644 .editorconfig create mode 100644 .env create mode 100644 .env.development create mode 100644 .env.production create mode 100644 .env.test create mode 100644 .eslintignore create mode 100644 .eslintrc.cjs create mode 100644 .gitignore create mode 100755 .husky/commit-msg create mode 100755 .husky/pre-commit create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json create mode 100644 README.md create mode 100644 commitlint.config.js create mode 100644 index.html create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/favicon.svg create mode 100644 src/App.tsx create mode 100644 src/api/index.ts create mode 100644 src/assets/styles/index.less create mode 100644 src/assets/styles/variables.less create mode 100644 src/components/HelloWorld.module.less create mode 100644 src/components/HelloWorld.tsx create mode 100644 src/components/index.ts create mode 100644 src/env.d.ts create mode 100644 src/hooks/index.ts create mode 100644 src/hooks/useAuth.ts create mode 100644 src/hooks/useBasicLayout.ts create mode 100644 src/hooks/useBreadcrumb.ts create mode 100644 src/hooks/useContext.ts create mode 100644 src/hooks/useDebounce.ts create mode 100644 src/hooks/useEffect.ts create mode 100644 src/hooks/usePagination.ts create mode 100644 src/hooks/useRequest.ts create mode 100644 src/hooks/useState.ts create mode 100644 src/hooks/useWebSocket.ts create mode 100644 src/layouts/BasicLayout.module.less create mode 100644 src/layouts/BasicLayout.tsx create mode 100644 src/main.ts create mode 100644 src/pages/login/index.module.less create mode 100644 src/pages/login/index.tsx create mode 100644 src/router/index.ts create mode 100644 src/router/routes.ts create mode 100644 src/router/utils.ts create mode 100644 src/types/index.ts create mode 100644 src/utils/index.ts create mode 100644 src/utils/request.ts create mode 100644 src/views/About.module.less create mode 100644 src/views/About.tsx create mode 100644 src/views/Dashboard.module.less create mode 100644 src/views/Dashboard.tsx create mode 100644 src/views/NotFound.tsx create mode 100644 start-debug.js create mode 100644 tsconfig.json create mode 100644 tsconfig.node.json create mode 100644 vite.config.ts diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..816227e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.{less,css}] +indent_size = 2 diff --git a/.env b/.env new file mode 100644 index 0000000..e8432c9 --- /dev/null +++ b/.env @@ -0,0 +1,3 @@ +# 公共环境变量 (所有模式共享) +VITE_APP_TITLE = CPMS 运营平台 +VITE_BASE_URL = / diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..9cf069a --- /dev/null +++ b/.env.development @@ -0,0 +1,4 @@ +# 开发环境 +VITE_PORT = 5173 +VITE_API_BASE_URL = http://localhost:3000 +VITE_API_PREFIX = /api diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..dc54b4f --- /dev/null +++ b/.env.production @@ -0,0 +1,3 @@ +# 生产环境 +VITE_API_BASE_URL = https://api.cpms.example.com +VITE_API_PREFIX = /api diff --git a/.env.test b/.env.test new file mode 100644 index 0000000..b3621a6 --- /dev/null +++ b/.env.test @@ -0,0 +1,3 @@ +# 测试环境 +VITE_API_BASE_URL = https://test-api.cpms.example.com +VITE_API_PREFIX = /api diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..cc6fa79 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,6 @@ +dist +node_modules +public +*.config.js +*.config.ts +start-debug.js diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..140cd5b --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,45 @@ +/* eslint-env node */ +module.exports = { + root: true, + env: { + browser: true, + node: true, + es2021: true, + }, + extends: [ + 'eslint:recommended', + 'plugin:vue/vue3-recommended', + 'plugin:@typescript-eslint/recommended', + 'prettier', + 'plugin:prettier/recommended', + ], + parser: 'vue-eslint-parser', + parserOptions: { + parser: '@typescript-eslint/parser', + ecmaVersion: 'latest', + sourceType: 'module', + }, + plugins: ['vue', '@typescript-eslint', 'prettier'], + rules: { + 'prettier/prettier': 'warn', + 'vue/multi-word-component-names': 'off', + 'vue/no-v-html': 'off', + 'vue/require-default-prop': 'off', + 'vue/attribute-hyphenation': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/no-unused-vars': [ + 'warn', + { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }, + ], + 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', + 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', + }, + globals: { + defineProps: 'readonly', + defineEmits: 'readonly', + defineExpose: 'readonly', + withDefaults: 'readonly', + }, +}; diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..715094c --- /dev/null +++ b/.gitignore @@ -0,0 +1,42 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +# Dependencies +node_modules +.pnp +.pnp.js + +# Build output +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +!.vscode/settings.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# Test coverage +coverage + +# Env local overrides +.env.local +.env.*.local + +# Misc +.cache +.temp +.tmp diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100755 index 0000000..b567676 --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npx --no -- commitlint --edit "$1" diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..d24fdfc --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npx lint-staged diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..7da6838 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,9 @@ +dist +node_modules +public +*.svg +*.ico +CHANGELOG.md +pnpm-lock.yaml +package-lock.json +yarn.lock diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..375346a --- /dev/null +++ b/.prettierrc @@ -0,0 +1,14 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "semi": true, + "singleQuote": true, + "trailingComma": "all", + "printWidth": 100, + "tabWidth": 2, + "useTabs": false, + "bracketSpacing": true, + "arrowParens": "always", + "endOfLine": "lf", + "vueIndentScriptAndStyle": false, + "htmlWhitespaceSensitivity": "ignore" +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..960e52c --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "Vue.volar", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "EditorConfig.EditorConfig", + "antfu.unocss", + "lokalise.i18n-ally" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ea1e0d1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,24 @@ +{ + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, + "eslint.validate": ["javascript", "typescript", "vue"], + "[vue]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[less]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "files.associations": { + "*.vue": "vue" + }, + "search.exclude": { + "**/node_modules": true, + "**/dist": true + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..3a1dc42 --- /dev/null +++ b/README.md @@ -0,0 +1,142 @@ +# CPMS 运营平台 (cpms_web_admin_pc) + +基于 **Vue 3 + Vite 5 + TypeScript + Ant Design Vue 4** 搭建的中后台管理项目骨架,采用 **TSX 写法**(不使用 `.vue` 单文件组件)。 + +## 技术栈 + +| 技术 | 版本 | 说明 | +| ---------------------- | ------ | ------------------------------- | +| Vue | ^3.3.0 | 渐进式前端框架 | +| Vite | ^5.0.0 | 下一代构建工具 | +| TypeScript | ^5.3.0 | 类型系统 | +| Vue Router | ^4.2.0 | 官方路由 | +| Ant Design Vue | ^4.0.0 | UI 组件库 | +| Less | ^4.6.4 | CSS 预处理器 | +| @vitejs/plugin-vue-jsx | ^4.0.0 | TSX/JSX 编译插件 | +| CSS Modules | - | 组件级样式隔离(`*.module.less`) | +| ESLint + Prettier | - | 代码规范与格式化 | +| Husky + Commitlint | - | Git 提交规范 | + +## 目录结构 + +``` +cpms_operation_platform/ +├── public/ # 静态资源(不参与编译) +│ └── favicon.svg +├── src/ +│ ├── api/ # 接口请求层 +│ ├── assets/ # 静态资源(参与编译) +│ │ └── styles/ # 全局样式 +│ ├── components/ # 公共组件 (.tsx) +│ ├── layouts/ # 布局组件 (.tsx + .module.less) +│ ├── router/ # 路由配置 +│ ├── types/ # 全局类型定义 +│ ├── utils/ # 工具函数 +│ ├── views/ # 页面视图 (.tsx + .module.less) +│ ├── App.tsx # 根组件 +│ ├── main.ts # 应用入口 +│ └── env.d.ts # 环境变量类型声明 +├── .env # 公共环境变量 +├── .env.development # 开发环境 +├── .env.test # 测试环境 +├── .env.production # 生产环境 +├── .eslintrc.cjs # ESLint 配置 +├── .prettierrc # Prettier 配置 +├── commitlint.config.js # 提交规范配置 +├── index.html # HTML 模板 +├── package.json +├── tsconfig.json # TypeScript 配置 +├── vite.config.ts # Vite 配置 +└── start-debug.js # 本地调试服务(express) +``` + +## 快速开始 + +### 安装依赖 + +```bash +npm install +# 或 +pnpm install +``` + +### 开发 + +```bash +npm run dev # 启动开发服务器 +``` + +### 构建 + +```bash +npm run build:dev # 开发环境构建 +npm run build:test # 测试环境构建 +npm run build:prod # 生产环境构建 +``` + +### 预览构建产物 + +```bash +npm run preview +``` + +### 本地调试(基于 express) + +先构建产物,再用 express 托管: + +```bash +npm run build:dev && npm run local +``` + +### 代码检查与格式化 + +```bash +npm run lint # ESLint 检查 +npm run lint:fix # ESLint 自动修复 +npm run format # Prettier 格式化 +npm run type-check # TypeScript 类型检查 +``` + +## Git 提交规范 + +本项目使用 [Conventional Commits](https://www.conventionalcommits.org/) 规范,由 commitlint 强制校验。 + +提交格式: + +``` +(): +``` + +常用 type: + +| type | 说明 | +| -------- | -------------------- | +| feat | 新功能 | +| fix | 修复 Bug | +| docs | 文档变更 | +| style | 代码格式(不影响功能) | +| refactor | 重构 | +| perf | 性能优化 | +| test | 测试 | +| build | 构建系统/依赖变更 | +| ci | CI 配置 | +| chore | 杂项 | +| revert | 回滚 | + +示例: + +```bash +git commit -m "feat(dashboard): 新增工作台数据统计卡片" +``` + +## 环境变量 + +通过 `.env` 系列文件管理环境配置,Vite 中以 `VITE_` 开头的变量会暴露到 `import.meta.env`。 + +| 变量 | 说明 | +| ----------------- | -------------- | +| VITE_APP_TITLE | 应用标题 | +| VITE_BASE_URL | 部署基础路径 | +| VITE_PORT | 开发服务器端口 | +| VITE_API_BASE_URL | 接口基础地址 | +| VITE_API_PREFIX | 接口路径前缀 | diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000..6d3956a --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,28 @@ +module.exports = { + extends: ['@commitlint/config-conventional'], + rules: { + 'type-enum': [ + 2, + 'always', + [ + 'feat', // 新功能 + 'fix', // 修复 bug + 'docs', // 文档变更 + 'style', // 代码格式(不影响功能) + 'refactor', // 重构 + 'perf', // 性能优化 + 'test', // 测试 + 'build', // 构建系统或外部依赖变更 + 'ci', // CI 配置 + 'chore', // 杂项/构建工具 + 'revert', // 回滚 + ], + ], + 'type-case': [2, 'always', 'lower-case'], + 'type-empty': [2, 'never'], + 'scope-case': [2, 'always', 'lower-case'], + 'subject-empty': [2, 'never'], + 'subject-full-stop': [2, 'never', '.'], + 'header-max-length': [2, 'always', 100], + }, +}; diff --git a/index.html b/index.html new file mode 100644 index 0000000..0dedaa8 --- /dev/null +++ b/index.html @@ -0,0 +1,14 @@ + + + + + + + + CPMS 运营平台 + + +
+ + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..f43d517 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5999 @@ +{ + "name": "cpms_web_admin_pc", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "cpms_web_admin_pc", + "version": "1.0.0", + "dependencies": { + "@ant-design/icons-vue": "^7.0.1", + "ant-design-vue": "^4.0.0", + "express": "^5.2.1", + "html2canvas": "^1.4.1", + "qs": "^6.15.0", + "vue": "^3.3.0", + "vue-router": "^4.2.0" + }, + "devDependencies": { + "@commitlint/cli": "^20.4.3", + "@commitlint/config-conventional": "^20.4.3", + "@types/node": "^20.10.0", + "@types/qs": "^6.15.0", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "@vitejs/plugin-vue": "^4.5.0", + "@vitejs/plugin-vue-jsx": "^4.0.0", + "eslint": "^8.0.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "eslint-plugin-vue": "^9.0.0", + "husky": "^9.1.7", + "less": "^4.6.4", + "lint-staged": "^15.0.0", + "prettier": "^3.0.0", + "typescript": "^5.3.0", + "vite": "^5.0.0", + "vue-tsc": "^2.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@ant-design/colors": { + "version": "6.0.0", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^3.4.0" + } + }, + "node_modules/@ant-design/icons-svg": { + "version": "4.5.0", + "license": "MIT" + }, + "node_modules/@ant-design/icons-vue": { + "version": "7.0.1", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^6.0.0", + "@ant-design/icons-svg": "^4.2.1" + }, + "peerDependencies": { + "vue": ">=3.0.3" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/traverse": "^7.29.7", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-syntax-typescript": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@commitlint/cli": { + "version": "20.5.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/format": "^20.5.0", + "@commitlint/lint": "^20.5.3", + "@commitlint/load": "^20.5.3", + "@commitlint/read": "^20.5.0", + "@commitlint/types": "^20.5.0", + "tinyexec": "^1.0.0", + "yargs": "^17.0.0" + }, + "bin": { + "commitlint": "cli.js" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "20.5.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "conventional-changelog-conventionalcommits": "^9.2.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-validator": { + "version": "20.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "ajv": "^8.11.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/ensure": { + "version": "20.5.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "es-toolkit": "^1.46.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/execute-rule": { + "version": "20.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/format": { + "version": "20.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/is-ignored": { + "version": "20.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "semver": "^7.6.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/lint": { + "version": "20.5.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/is-ignored": "^20.5.0", + "@commitlint/parse": "^20.5.0", + "@commitlint/rules": "^20.5.3", + "@commitlint/types": "^20.5.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/load": { + "version": "20.5.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/config-validator": "^20.5.0", + "@commitlint/execute-rule": "^20.0.0", + "@commitlint/resolve-extends": "^20.5.3", + "@commitlint/types": "^20.5.0", + "cosmiconfig": "^9.0.1", + "cosmiconfig-typescript-loader": "^6.1.0", + "es-toolkit": "^1.46.0", + "is-plain-obj": "^4.1.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/message": { + "version": "20.4.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/parse": { + "version": "20.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.5.0", + "conventional-changelog-angular": "^8.2.0", + "conventional-commits-parser": "^6.3.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/read": { + "version": "20.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/top-level": "^20.4.3", + "@commitlint/types": "^20.5.0", + "git-raw-commits": "^5.0.0", + "minimist": "^1.2.8", + "tinyexec": "^1.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/resolve-extends": { + "version": "20.5.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/config-validator": "^20.5.0", + "@commitlint/types": "^20.5.0", + "es-toolkit": "^1.46.0", + "global-directory": "^5.0.0", + "import-meta-resolve": "^4.0.0", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/rules": { + "version": "20.5.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/ensure": "^20.5.3", + "@commitlint/message": "^20.4.3", + "@commitlint/to-lines": "^20.0.0", + "@commitlint/types": "^20.5.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/to-lines": { + "version": "20.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/top-level": { + "version": "20.4.3", + "dev": true, + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/types": { + "version": "20.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-commits-parser": "^6.3.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@conventional-changelog/git-client": { + "version": "2.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@simple-libs/child-process-utils": "^1.0.0", + "@simple-libs/stream-utils": "^1.2.0", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "conventional-commits-filter": "^5.0.0", + "conventional-commits-parser": "^6.4.0" + }, + "peerDependenciesMeta": { + "conventional-commits-filter": { + "optional": true + }, + "conventional-commits-parser": { + "optional": true + } + } + }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "license": "MIT" + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.15.0", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.16", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.5", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.16", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.5", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgr/core": { + "version": "0.3.6", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.2", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@simonwep/pickr": { + "version": "1.8.2", + "license": "MIT", + "dependencies": { + "core-js": "^3.15.1", + "nanopop": "^2.1.0" + } + }, + "node_modules/@simple-libs/child-process-utils": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@simple-libs/stream-utils": "^1.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://ko-fi.com/dangreen" + } + }, + "node_modules/@simple-libs/stream-utils": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://ko-fi.com/dangreen" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.43", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/qs": { + "version": "6.15.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/semver": { + "version": "7.7.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.3", + "dev": true, + "license": "ISC" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "4.6.2", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.0.0 || ^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vitejs/plugin-vue-jsx": { + "version": "4.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.1", + "@babel/plugin-transform-typescript": "^7.27.1", + "@rolldown/pluginutils": "^1.0.0-beta.9", + "@vue/babel-plugin-jsx": "^1.4.0" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.0.0" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.15", + "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.15.tgz", + "integrity": "sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.15" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.15", + "resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.15.tgz", + "integrity": "sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.15", + "resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.15.tgz", + "integrity": "sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.15", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/babel-helper-vue-transform-on": { + "version": "1.5.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/babel-plugin-jsx": { + "version": "1.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.2", + "@vue/babel-helper-vue-transform-on": "1.5.0", + "@vue/babel-plugin-resolve-type": "1.5.0", + "@vue/shared": "^3.5.18" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + } + } + }, + "node_modules/@vue/babel-plugin-resolve-type": { + "version": "1.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/parser": "^7.28.0", + "@vue/compiler-sfc": "^3.5.18" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.39", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@vue/shared": "3.5.39", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.39", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.39", + "@vue/shared": "3.5.39" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.39", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@vue/compiler-core": "3.5.39", + "@vue/compiler-dom": "3.5.39", + "@vue/compiler-ssr": "3.5.39", + "@vue/shared": "3.5.39", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.15", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.39", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.39", + "@vue/shared": "3.5.39" + } + }, + "node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "resolved": "https://registry.npmmirror.com/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", + "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", + "dev": true, + "license": "MIT", + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "license": "MIT" + }, + "node_modules/@vue/language-core": { + "version": "2.2.12", + "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-2.2.12.tgz", + "integrity": "sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.15", + "@vue/compiler-dom": "^3.5.0", + "@vue/compiler-vue2": "^2.7.16", + "@vue/shared": "^3.5.0", + "alien-signals": "^1.0.3", + "minimatch": "^9.0.3", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.39", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.39" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.39", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.39", + "@vue/shared": "3.5.39" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.39", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.39", + "@vue/runtime-core": "3.5.39", + "@vue/shared": "3.5.39", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.39", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.39", + "@vue/shared": "3.5.39" + }, + "peerDependencies": { + "vue": "3.5.39" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.39", + "license": "MIT" + }, + "node_modules/accepts": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.17.0", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/alien-signals": { + "version": "1.0.13", + "resolved": "https://registry.npmmirror.com/alien-signals/-/alien-signals-1.0.13.tgz", + "integrity": "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-escapes": { + "version": "7.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ant-design-vue": { + "version": "4.2.6", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^6.0.0", + "@ant-design/icons-vue": "^7.0.0", + "@babel/runtime": "^7.10.5", + "@ctrl/tinycolor": "^3.5.0", + "@emotion/hash": "^0.9.0", + "@emotion/unitless": "^0.8.0", + "@simonwep/pickr": "~1.8.0", + "array-tree-filter": "^2.1.0", + "async-validator": "^4.0.0", + "csstype": "^3.1.1", + "dayjs": "^1.10.5", + "dom-align": "^1.12.1", + "dom-scroll-into-view": "^2.0.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.15", + "resize-observer-polyfill": "^1.5.1", + "scroll-into-view-if-needed": "^2.2.25", + "shallow-equal": "^1.0.0", + "stylis": "^4.1.3", + "throttle-debounce": "^5.0.0", + "vue-types": "^3.0.0", + "warning": "^4.0.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ant-design-vue" + }, + "peerDependencies": { + "vue": ">=3.2.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-ify": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/array-tree-filter": { + "version": "2.1.0", + "license": "MIT" + }, + "node_modules/array-union": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/async-validator": { + "version": "4.2.5", + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.43", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/body-parser": { + "version": "2.3.0", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^2.0.0", + "debug": "^4.4.3", + "http-errors": "^2.0.1", + "iconv-lite": "^0.7.2", + "on-finished": "^2.4.1", + "qs": "^6.15.2", + "raw-body": "^3.0.2", + "type-is": "^2.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/body-parser/node_modules/content-type": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/brace-expansion": { + "version": "2.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.6", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.42", + "caniuse-lite": "^1.0.30001803", + "electron-to-chromium": "^1.5.389", + "node-releases": "^2.0.51", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001805", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.20", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "13.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/compare-func": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/compute-scroll-into-view": { + "version": "1.0.20", + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/conventional-changelog-angular": { + "version": "8.3.1", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "9.3.1", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/conventional-commits-parser": { + "version": "6.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@simple-libs/stream-utils": "^1.2.0", + "meow": "^13.0.0" + }, + "bin": { + "conventional-commits-parser": "dist/cli/index.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/copy-anything": { + "version": "3.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "is-what": "^4.1.8" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/core-js": { + "version": "3.49.0", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cosmiconfig": { + "version": "9.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig-typescript-loader": { + "version": "6.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "jiti": "2.6.1" + }, + "engines": { + "node": ">=v18" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=9", + "typescript": ">=5" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-line-break": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "utrie": "^1.0.2" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "license": "MIT" + }, + "node_modules/dayjs": { + "version": "1.11.21", + "license": "MIT" + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-align": { + "version": "1.12.4", + "license": "MIT" + }, + "node_modules/dom-scroll-into-view": { + "version": "2.0.1", + "license": "MIT" + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.389", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "10.6.0", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/entities": { + "version": "7.0.1", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/errno": { + "version": "0.1.8", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-toolkit": { + "version": "1.49.0", + "dev": true, + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, + "node_modules/esbuild": { + "version": "0.21.5", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/esbuild/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "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", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "9.1.2", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.5.6", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.1", + "synckit": "^0.11.13" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-vue": { + "version": "9.33.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "globals": "^13.24.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.15", + "semver": "^7.6.3", + "vue-eslint-parser": "^9.4.3", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.15.0", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.16", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.5", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "dev": true, + "license": "MIT" + }, + "node_modules/execa": { + "version": "8.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/express": { + "version": "5.2.1", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.3", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.20.1", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.1.1", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "dev": true, + "license": "ISC" + }, + "node_modules/forwarded": { + "version": "0.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "8.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-raw-commits": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@conventional-changelog/git-client": "^2.6.0", + "meow": "^13.0.0" + }, + "bin": { + "git-raw-commits": "src/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.16", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.5", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/global-directory": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "6.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/html2canvas": { + "version": "1.4.1", + "license": "MIT", + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/human-signals": { + "version": "5.0.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/husky": { + "version": "9.1.7", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.3", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/image-size": { + "version": "0.5.5", + "dev": true, + "license": "MIT", + "optional": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "node_modules/ini": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "3.0.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "license": "MIT" + }, + "node_modules/is-stream": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-what": { + "version": "4.1.16", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/jiti": { + "version": "2.6.1", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.3.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/less": { + "version": "4.6.7", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "copy-anything": "^3.0.5", + "parse-node-version": "^1.0.1" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^5.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "source-map": "~0.6.0" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "dev": true, + "license": "MIT" + }, + "node_modules/lint-staged": { + "version": "15.5.2", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.4.1", + "commander": "^13.1.0", + "debug": "^4.4.0", + "execa": "^8.0.1", + "lilconfig": "^3.1.3", + "listr2": "^8.2.5", + "micromatch": "^4.0.8", + "pidtree": "^0.6.0", + "string-argv": "^0.3.2", + "yaml": "^2.7.0" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.6.2", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/listr2": { + "version": "8.3.3", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.18.1", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update": { + "version": "6.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.2.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/make-dir": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/meow": { + "version": "13.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "dev": true, + "license": "MIT", + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "9.0.3", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "license": "MIT" + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.16", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/nanopop": { + "version": "2.4.2", + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/needle": { + "version": "3.5.0", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/needle/node_modules/iconv-lite": { + "version": "0.6.3", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/negotiator": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-releases": { + "version": "2.0.51", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-to-regexp": { + "version": "8.4.2", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.1", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/postcss": { + "version": "8.5.19", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.9.5", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/prr": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/punycode": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.15.3", + "license": "BSD-3-Clause", + "dependencies": { + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.3.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/raw-body": { + "version": "3.0.2", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "license": "MIT" + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.62.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.62.2", + "@rollup/rollup-android-arm64": "4.62.2", + "@rollup/rollup-darwin-arm64": "4.62.2", + "@rollup/rollup-darwin-x64": "4.62.2", + "@rollup/rollup-freebsd-arm64": "4.62.2", + "@rollup/rollup-freebsd-x64": "4.62.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", + "@rollup/rollup-linux-arm-musleabihf": "4.62.2", + "@rollup/rollup-linux-arm64-gnu": "4.62.2", + "@rollup/rollup-linux-arm64-musl": "4.62.2", + "@rollup/rollup-linux-loong64-gnu": "4.62.2", + "@rollup/rollup-linux-loong64-musl": "4.62.2", + "@rollup/rollup-linux-ppc64-gnu": "4.62.2", + "@rollup/rollup-linux-ppc64-musl": "4.62.2", + "@rollup/rollup-linux-riscv64-gnu": "4.62.2", + "@rollup/rollup-linux-riscv64-musl": "4.62.2", + "@rollup/rollup-linux-s390x-gnu": "4.62.2", + "@rollup/rollup-linux-x64-gnu": "4.62.2", + "@rollup/rollup-linux-x64-musl": "4.62.2", + "@rollup/rollup-openbsd-x64": "4.62.2", + "@rollup/rollup-openharmony-arm64": "4.62.2", + "@rollup/rollup-win32-arm64-msvc": "4.62.2", + "@rollup/rollup-win32-ia32-msvc": "4.62.2", + "@rollup/rollup-win32-x64-gnu": "4.62.2", + "@rollup/rollup-win32-x64-msvc": "4.62.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup/node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", + "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz", + "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz", + "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz", + "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz", + "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz", + "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz", + "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz", + "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz", + "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz", + "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz", + "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz", + "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz", + "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz", + "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz", + "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz", + "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz", + "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz", + "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz", + "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz", + "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz", + "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz", + "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz", + "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/rollup/node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz", + "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/router": { + "version": "2.2.0", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.6.0", + "dev": true, + "license": "BlueOak-1.0.0", + "optional": true, + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/scroll-into-view-if-needed": { + "version": "2.2.31", + "license": "MIT", + "dependencies": { + "compute-scroll-into-view": "^1.0.20" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.1", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serve-static": { + "version": "2.2.1", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "license": "ISC" + }, + "node_modules/shallow-equal": { + "version": "1.2.1", + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string-argv": { + "version": "0.3.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-width": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.2.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stylis": { + "version": "4.4.0", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/synckit": { + "version": "0.11.13", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.3.6" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "license": "MIT", + "dependencies": { + "utrie": "^1.0.2" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/throttle-debounce": { + "version": "5.0.2", + "license": "MIT", + "engines": { + "node": ">=12.22" + } + }, + "node_modules/tinyexec": { + "version": "1.2.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ts-api-utils": { + "version": "1.4.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "content-type": "^2.0.0", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/type-is/node_modules/content-type": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "dev": true, + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/utrie": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vite": { + "version": "5.4.21", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.39", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.39", + "@vue/compiler-sfc": "3.5.39", + "@vue/runtime-dom": "3.5.39", + "@vue/server-renderer": "3.5.39", + "@vue/shared": "3.5.39" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-eslint-parser": { + "version": "9.4.3", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/vue-router": { + "version": "4.6.4", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/vue-tsc": { + "version": "2.2.12", + "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-2.2.12.tgz", + "integrity": "sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "2.4.15", + "@vue/language-core": "2.2.12" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, + "node_modules/vue-types": { + "version": "3.0.2", + "license": "MIT", + "dependencies": { + "is-plain-object": "3.0.1" + }, + "engines": { + "node": ">=10.15.0" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/warning": { + "version": "4.0.3", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "9.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.2.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "license": "ISC" + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.9.0", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "17.7.3", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..f91651a --- /dev/null +++ b/package.json @@ -0,0 +1,64 @@ +{ + "name": "cpms_operation_platform", + "version": "0.0.0", + "description": "CPMS 运营平台前端 PC 端", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "serve": "vite", + "build:dev": "vue-tsc --noEmit && vite build --mode development", + "build:test": "vue-tsc --noEmit && vite build --mode test", + "build:prod": "vue-tsc --noEmit && vite build --mode production", + "preview": "vite preview", + "type-check": "vue-tsc --noEmit", + "local": "node start-debug.js", + "lint": "eslint src --ext .js,.ts,.tsx", + "lint:fix": "eslint src --ext .js,.ts,.tsx --fix", + "format": "prettier --write \"src/**/*.{js,ts,tsx,json,less,css,md}\"", + "prepare": "husky install" + }, + "dependencies": { + "@ant-design/icons-vue": "^7.0.1", + "@yp-component/root": "^0.0.46", + "ant-design-vue": "^4.0.0", + "express": "^5.2.1", + "html2canvas": "^1.4.1", + "qs": "^6.15.0", + "vue": "^3.3.0", + "vue-router": "^4.2.0" + }, + "devDependencies": { + "@commitlint/cli": "^20.4.3", + "@commitlint/config-conventional": "^20.4.3", + "@types/node": "^20.10.0", + "@types/qs": "^6.15.0", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "@vitejs/plugin-vue": "^4.5.0", + "@vitejs/plugin-vue-jsx": "^4.0.0", + "eslint": "^8.0.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "eslint-plugin-vue": "^9.0.0", + "husky": "^9.1.7", + "less": "^4.6.4", + "lint-staged": "^15.0.0", + "prettier": "^3.0.0", + "typescript": "^5.3.0", + "vite": "^5.0.0", + "vue-tsc": "^2.0.0" + }, + "lint-staged": { + "*.{js,ts,tsx}": [ + "eslint --fix", + "prettier --write" + ], + "*.{json,less,css,md}": [ + "prettier --write" + ] + }, + "engines": { + "node": ">=16.0.0" + } +} diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..01ba8cc --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1,4 @@ + + + CP + diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..ba5b391 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,25 @@ +import { defineComponent } from 'vue'; +import { ConfigProvider } from 'ant-design-vue'; +import zhCN from 'ant-design-vue/es/locale/zh_CN'; +import { RouterView } from 'vue-router'; + +/** + * 根组件 + * 通过 ConfigProvider 注入 ant-design-vue 全局配置(语言、主题色) + */ +export default defineComponent({ + name: 'App', + setup() { + const theme = { + token: { + colorPrimary: '#1677ff', + }, + }; + + return () => ( + + + + ); + }, +}); diff --git a/src/api/index.ts b/src/api/index.ts new file mode 100644 index 0000000..85fce63 --- /dev/null +++ b/src/api/index.ts @@ -0,0 +1,29 @@ +/** + * 接口模块示例 + * 实际项目中按业务域拆分:如 api/user.ts、api/order.ts 等 + */ +import { get, post } from '@/utils/request'; + +export interface UserInfo { + id: number; + name: string; + role: string; +} + +/** 获取当前用户信息(示例接口) */ +export function getCurrentUser(): Promise { + return get('/user/current'); +} + +/** 用户列表(示例接口) */ +export function getUserList(params: { + page: number; + size: number; +}): Promise<{ list: UserInfo[]; total: number }> { + return get('/user/list', params); +} + +/** 新建用户(示例接口) */ +export function createUser(data: Omit): Promise { + return post('/user', data); +} diff --git a/src/assets/styles/index.less b/src/assets/styles/index.less new file mode 100644 index 0000000..b5a78cc --- /dev/null +++ b/src/assets/styles/index.less @@ -0,0 +1,57 @@ +// ===== 全局样式入口 ===== + +// CSS Reset 已由 ant-design-vue 的 reset.css 提供,这里补充全局变量与基础样式 + +// 全局 less 变量 +@primary-color: #1677ff; +@text-color: rgba(0, 0, 0, 0.88); +@border-color: #f0f0f0; +@bg-color: #f5f5f5; + +// 基础重置 +* { + box-sizing: border-box; +} + +html, +body, +#app { + height: 100%; + margin: 0; + padding: 0; +} + +body { + font-family: + -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'PingFang SC', + 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; + font-size: 14px; + color: @text-color; + background-color: @bg-color; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +a { + color: @primary-color; + text-decoration: none; + + &:hover { + opacity: 0.85; + } +} + +// 滚动条美化 +::-webkit-scrollbar { + width: 6px; + height: 6px; +} + +::-webkit-scrollbar-thumb { + background: rgba(0, 0, 0, 0.2); + border-radius: 3px; +} + +::-webkit-scrollbar-track { + background: transparent; +} diff --git a/src/assets/styles/variables.less b/src/assets/styles/variables.less new file mode 100644 index 0000000..c8aa980 --- /dev/null +++ b/src/assets/styles/variables.less @@ -0,0 +1,19 @@ +// ===== 主题变量 ===== +// 可在组件中通过 @import 引入复用 + +@primary-color: #1677ff; +@success-color: #52c41a; +@warning-color: #faad14; +@error-color: #ff4d4f; + +@text-color: rgba(0, 0, 0, 0.88); +@text-color-secondary: rgba(0, 0, 0, 0.65); +@text-color-disabled: rgba(0, 0, 0, 0.35); + +@border-radius-base: 6px; +@border-color: #f0f0f0; +@bg-color: #f5f5f5; + +@layout-header-height: 48px; +@layout-sider-width: 200px; +@layout-sider-width-collapsed: 80px; diff --git a/src/components/HelloWorld.module.less b/src/components/HelloWorld.module.less new file mode 100644 index 0000000..eaab200 --- /dev/null +++ b/src/components/HelloWorld.module.less @@ -0,0 +1,16 @@ +.container { + text-align: center; + padding: 16px; +} + +.title { + color: #1677ff; +} + +.desc { + code { + background: #f5f5f5; + padding: 2px 6px; + border-radius: 4px; + } +} diff --git a/src/components/HelloWorld.tsx b/src/components/HelloWorld.tsx new file mode 100644 index 0000000..1b59629 --- /dev/null +++ b/src/components/HelloWorld.tsx @@ -0,0 +1,27 @@ +import { defineComponent } from 'vue'; +import styles from './HelloWorld.module.less'; + +/** + * 公共组件示例 + */ +export default defineComponent({ + name: 'HelloWorld', + props: { + msg: { + type: String, + default: 'Hello World', + }, + }, + setup(props) { + return () => ( +
+

{props.msg}

+

+ 这是一个公共组件示例,采用 TSX 写法。你可以在 + src/components + 下继续扩展。 +

+
+ ); + }, +}); diff --git a/src/components/index.ts b/src/components/index.ts new file mode 100644 index 0000000..17c5079 --- /dev/null +++ b/src/components/index.ts @@ -0,0 +1,5 @@ +/** + * 公共组件统一导出 + * 在业务中可通过 `import { HelloWorld } from '@/components'` 使用 + */ +export { default as HelloWorld } from './HelloWorld'; diff --git a/src/env.d.ts b/src/env.d.ts new file mode 100644 index 0000000..970be26 --- /dev/null +++ b/src/env.d.ts @@ -0,0 +1,13 @@ +/// + +interface ImportMetaEnv { + readonly VITE_APP_TITLE: string; + readonly VITE_BASE_URL: string; + readonly VITE_PORT: string; + readonly VITE_API_BASE_URL: string; + readonly VITE_API_PREFIX: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/src/hooks/index.ts b/src/hooks/index.ts new file mode 100644 index 0000000..78a5410 --- /dev/null +++ b/src/hooks/index.ts @@ -0,0 +1,10 @@ +export * from './useEffect'; +export * from './useState'; +export * from './usePagination'; +export * from './useRequest'; +export * from './useDebounce'; +export * from './useAuth'; +export * from './useWebSocket'; +export * from './useBasicLayout'; +export * from './useBreadcrumb'; +export * from './useContext'; diff --git a/src/hooks/useAuth.ts b/src/hooks/useAuth.ts new file mode 100644 index 0000000..a59e367 --- /dev/null +++ b/src/hooks/useAuth.ts @@ -0,0 +1,34 @@ +// src/hooks/useAuth.ts +import { useState } from './useState'; +import { watch } from 'vue'; + +const TOKEN_KEY = 'MY_APP_AUTH_TOKEN'; + +function createAuth() { + const [token, setToken] = useState(window.localStorage.getItem(TOKEN_KEY)); + + watch(token, (newToken) => { + if (newToken) { + window.localStorage.setItem(TOKEN_KEY, newToken); + } else { + window.localStorage.removeItem(TOKEN_KEY); + } + }); + + const login = (newToken: string) => { + setToken(newToken); + }; + + const logout = () => { + setToken(null); + }; + + return { + token, + isLoggedIn: () => !!token.value, + login, + logout, + }; +} + +export const auth = createAuth(); diff --git a/src/hooks/useBasicLayout.ts b/src/hooks/useBasicLayout.ts new file mode 100644 index 0000000..f0b511d --- /dev/null +++ b/src/hooks/useBasicLayout.ts @@ -0,0 +1,46 @@ +import { h } from 'vue'; +import { useRouter, useRoute } from 'vue-router'; +import { TrophyOutlined, WalletOutlined } from '@ant-design/icons-vue'; +import { useBreadcrumb } from './useBreadcrumb'; + +export function useBasicLayout() { + const router = useRouter(); + const route = useRoute(); + const { breadcrumbItems } = useBreadcrumb(); + + const menuItems = [ + { + key: '/events', + icon: h(TrophyOutlined), + label: '我的赛事', + }, + // { TODO 本期先做隐藏 + // key: '/wallet', + // icon: h(WalletOutlined), + // label: '钱包管理', + // }, + ]; + + const getActiveMenuKey = () => { + const matchedRoutes = route.matched; + for (const r of matchedRoutes) { + if (r.meta?.activeMenu) { + return r.meta.activeMenu as string; + } + } + if (route.path.startsWith('/events')) return '/events'; + if (route.path.startsWith('/wallet')) return '/wallet'; + return route.path; + }; + + const handleMenuClick = (info: any) => { + router.push(String(info.key)); + }; + + return { + breadcrumbItems, + menuItems, + getActiveMenuKey, + handleMenuClick, + }; +} diff --git a/src/hooks/useBreadcrumb.ts b/src/hooks/useBreadcrumb.ts new file mode 100644 index 0000000..ae55850 --- /dev/null +++ b/src/hooks/useBreadcrumb.ts @@ -0,0 +1,67 @@ +import { computed, h } from 'vue'; +import { useRoute, useRouter } from 'vue-router'; + +export function useBreadcrumb() { + const route = useRoute(); + const router = useRouter(); + + /** + * 根据当前路径和记录路径,计算拼接后的路径 + */ + const buildPath = (currentPath: string, recordPath: string): string => { + if (recordPath.startsWith('/')) { + return recordPath; + } + return currentPath ? `${currentPath}/${recordPath}`.replace(/\/+/g, '/') : `/${recordPath}`; + }; + + const breadcrumbs = computed(() => { + const matched = route.matched; + const items: Array<{ title: string; path?: string }> = []; + let currentPath = ''; + + for (const record of matched) { + currentPath = buildPath(currentPath, record.path); + if (record.meta && record.meta.title) { + items.push({ + title: record.meta.title as string, + path: currentPath, + }); + } + } + + return items; + }); + + const breadcrumbItems = computed(() => { + return breadcrumbs.value.map((item, index) => ({ + key: index, + title: + item.path && index !== breadcrumbs.value.length - 1 + ? h( + 'a', + { + onClick: (e: Event) => { + e.preventDefault(); + // 最保守方案:只有当前路径包含 /bracket/ 且目标路径是 /events/bracket 时才保留 query + // 也就是只有:/events/bracket/xxx → /events/bracket 时才保留 + const targetPath = item.path || '/'; + const isBracketChildPage = + route.path.includes('/bracket/') && targetPath === '/events/bracket'; + router.push({ + path: targetPath, + query: isBracketChildPage ? route.query : {}, + }); + }, + }, + item.title, + ) + : item.title, + })); + }); + + return { + breadcrumbs, + breadcrumbItems, + }; +} diff --git a/src/hooks/useContext.ts b/src/hooks/useContext.ts new file mode 100644 index 0000000..8edb823 --- /dev/null +++ b/src/hooks/useContext.ts @@ -0,0 +1,137 @@ +import { reactive, provide, inject, type InjectionKey } from 'vue'; + +/** + * 深合并:将 source 的属性递归合并到 target 中 + * - 对于原始值和数组,直接赋值(数组整体替换,不做元素级 diff) + * - 对于普通对象,递归合并,保留 target 中已有的响应式 Proxy + * - 跳过值为 undefined 的属性 + */ +function deepSyncState>(target: T, source: Partial): void { + const keys = Object.keys(source) as (keyof T)[]; + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + if (!(key in target) || source[key] === undefined) continue; + + const sourceVal = source[key]; + const targetVal = target[key]; + + // 两边都是普通对象 → 递归合并,保留响应式 + if ( + isPlainObject(sourceVal) && + isPlainObject(targetVal) && + !Array.isArray(sourceVal) && + !Array.isArray(targetVal) + ) { + deepSyncState(targetVal as Record, sourceVal as Record); + } else { + // 原始值、数组、或类型不匹配 → 直接赋值 + (target as any)[key] = sourceVal; + } + } +} + +/** + * 判断是否为普通对象(Plain Object) + * 排除 Array、Date、RegExp、Map、Set 等内置类型 + */ +function isPlainObject(val: unknown): val is Record { + if (val === null || typeof val !== 'object') return false; + const proto = Object.getPrototypeOf(val); + // Object.create(null) 的 proto 为 null,也视为普通对象 + return proto === null || proto === Object.prototype; +} + +export interface Context> { + /** + * 在当前组件及所有子组件中提供 Context 数据 + * + * @param value - 可选的部分更新,会深合并到初始值中 + * @returns dispose 清理函数,调用后恢复初始值 + */ + provide: (value?: Partial) => () => void; + /** 在子组件中消费 Context 数据,返回响应式对象 */ + useContext: () => T; + /** 底层 InjectionKey,用于自定义 provide/inject 场景 */ + readonly key: InjectionKey; +} + +/** + * 创建一个 Context 实例 + * + * @param initialValue - 初始状态对象,所有属性将具备响应式能力 + * @param options.displayName - 可选,用于 DevTools 调试时的标识 + */ +export function createContext>( + initialValue: T, + options?: { displayName?: string }, +): Context { + const name = options?.displayName || 'Context'; + const key: InjectionKey = Symbol(name) as InjectionKey; + + // 深拷贝初始值,确保源数据不被污染,同时作为后续恢复的快照 + const snapshot = deepClone(initialValue); + // 创建全局响应式容器 + const initialReactive = reactive(snapshot) as T; + + // 记录当前是否已被 dispose,防止重复调用 + let disposed = false; + + return { + key, + + /** + * 在当前组件树中提供 Context + * 调用后,所有子组件可通过 useContext() 获取到响应式状态 + * + * @param value - 可选的部分更新,会深合并到初始值中 + * @returns 清理函数,调用后将状态恢复为 initialValue + */ + provide(value?: Partial): () => void { + disposed = false; + + // 如果传入了 value,深合并到全局 reactive 对象 + if (value) { + deepSyncState(initialReactive, value); + } + // 通过 Vue 原生 provide 向下注入 + provide(key, initialReactive); + + // 返回清理函数 + return () => { + if (disposed) return; + disposed = true; + // 恢复初始值 + deepSyncState(initialReactive, initialValue); + }; + }, + + /** + * 在子组件中消费 Context + * 必须在 Provider 所在组件的子级 setup 中调用 + */ + useContext(): T { + const injected = inject(key); + if (!injected) { + // 降级返回初始值,保证组件不会崩溃 + return initialReactive; + } + return injected; + }, + }; +} + +/** + * 深拷贝普通对象,保留嵌套结构 + * 仅用于创建初始快照,不处理特殊对象(Date、RegExp 等保持引用) + */ +function deepClone(obj: T): T { + if (obj === null || typeof obj !== 'object') return obj; + if (Array.isArray(obj)) return obj.map((item) => deepClone(item)) as T; + const result = {} as T; + const keys = Object.keys(obj) as (keyof T)[]; + for (let i = 0; i < keys.length; i++) { + const k = keys[i]; + result[k] = deepClone(obj[k]); + } + return result; +} diff --git a/src/hooks/useDebounce.ts b/src/hooks/useDebounce.ts new file mode 100644 index 0000000..aebfad1 --- /dev/null +++ b/src/hooks/useDebounce.ts @@ -0,0 +1,80 @@ +// src/hooks/useDebounce.ts +import { watch, onUnmounted } from 'vue'; +import { useState } from './useState'; + +export interface UseDebounceOptions { + delay?: number; + immediate?: boolean; + maxWait?: number; +} + +export function useDebounce( + source: any, // Ref + options: number | UseDebounceOptions = {}, +) { + const config = typeof options === 'number' ? { delay: options } : options; + const { delay = 300, immediate = false, maxWait } = config; + + const [debouncedValue, setDebouncedValue] = useState(source.value); + const [isPending, setIsPending] = useState(false); + + let timer: any = null; + let maxWaitTimer: any = null; + let isFirstCall = true; // 标记是否为首次调用,用于 immediate 模式 + + // 清理 + const clearTimers = () => { + if (timer) { + clearTimeout(timer); + timer = null; + } + if (maxWaitTimer) { + clearTimeout(maxWaitTimer); + maxWaitTimer = null; + } + }; + + // 更新 + const updateValue = () => { + setDebouncedValue(source.value); + setIsPending(false); + clearTimers(); + // 安静期结束后重置 isFirstCall,使下次触发能立即执行(immediate 模式) + isFirstCall = true; + }; + + watch(source, () => { + setIsPending(true); + + // 处理 maxWait + if (maxWait && !maxWaitTimer) { + maxWaitTimer = setTimeout(() => { + updateValue(); + }, maxWait); + } + + // 处理 delay + if (timer) clearTimeout(timer); + + if (immediate && isFirstCall) { + isFirstCall = false; + updateValue(); + } else { + timer = setTimeout(() => { + updateValue(); + }, delay); + } + }); + + // 卸载 + onUnmounted(() => { + clearTimers(); + }); + + return { + debouncedValue, + isPending, + refresh: updateValue, + cancel: clearTimers, + }; +} diff --git a/src/hooks/useEffect.ts b/src/hooks/useEffect.ts new file mode 100644 index 0000000..79096a7 --- /dev/null +++ b/src/hooks/useEffect.ts @@ -0,0 +1,32 @@ +import { watchEffect, watch, WatchSource, isRef, isReactive } from 'vue'; + +export function useEffect(effect: () => void | (() => void), deps?: WatchSource[]) { + if (!deps) { + return watchEffect((onCleanup) => { + const cleanup = effect(); + if (cleanup) onCleanup(cleanup); + }); + } + + const validDeps = deps.map((dep) => { + if (dep === null || dep === undefined) { + return () => null; + } + if (isRef(dep) || isReactive(dep) || typeof dep === 'function') { + return dep; + } + return () => dep; + }); + + return watch( + validDeps, + () => { + const cleanup = effect(); + return cleanup; + }, + { + immediate: true, + flush: 'post', + }, + ); +} diff --git a/src/hooks/usePagination.ts b/src/hooks/usePagination.ts new file mode 100644 index 0000000..eeafc3c --- /dev/null +++ b/src/hooks/usePagination.ts @@ -0,0 +1,185 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +// src/hooks/usePagination.ts +import { computed, ref, watch, Ref, triggerRef } from 'vue'; + +/** + * 分页配置项 + */ +export interface UsePaginationOptions { + /** 当前页码 (支持 v-model 双向绑定) */ + current?: number; + /** 每页条数 (支持 v-model 双向绑定) */ + pageSize?: number; + /** 数据总条数 (支持 v-model 双向绑定) */ + total?: number; + /** 默认页码 (非受控模式下使用) */ + defaultCurrent?: number; + /** 默认每页条数 (非受控模式下使用) */ + defaultPageSize?: number; + /** 每页条数切换选项 (用于生成下拉菜单) */ + pageSizeOptions?: number[]; + /** 是否显示快速跳转 (可选功能) */ + showQuickJumper?: boolean; +} + +/** + * 分页操作 API + */ +export interface UsePaginationActions { + /** 设置当前页 */ + setCurrent: (current: number) => void; + /** 设置每页条数 (会自动重置页码为 1) */ + setPageSize: (size: number) => void; + /** 设置总条数 */ + setTotal: (total: number) => void; + /** 下一页 */ + next: () => void; + /** 上一页 */ + prev: () => void; + /** 跳转到指定页 */ + jump: (page: number) => void; + /** 重置到初始状态 */ + reset: () => void; + /** 强制刷新 (用于某些极端响应式场景) */ + refresh: () => void; +} + +/** + * 分页计算属性 + */ +export interface UsePaginationComputed { + /** 响应式请求参数对象 (给 API 用的) */ + params: Ref<{ page: number; pageSize: number }>; + /** 总页数 */ + totalPages: Ref; + /** 是否有上一页 */ + hasPrev: Ref; + /** 是否有下一页 */ + hasNext: Ref; + /** 当前页起始索引 (用于显示 "显示 1-10 条") */ + startIndex: Ref; + /** 当前页结束索引 */ + endIndex: Ref; + /** 是否为第一页 */ + isFirstPage: Ref; + /** 是否为最后一页 */ + isLastPage: Ref; +} + +export type UsePaginationReturn = UsePaginationOptions & + UsePaginationActions & + UsePaginationComputed; + +export function usePagination(options: UsePaginationOptions = {}): UsePaginationReturn { + const { defaultCurrent = 1, defaultPageSize = 10, pageSizeOptions = [10, 20, 50, 100] } = options; + + const currentRef = ref(options.current ?? defaultCurrent); + const pageSizeRef = ref(options.pageSize ?? defaultPageSize); + const totalRef = ref(options.total ?? 0); + + watch( + () => options.current, + (val) => { + if (val !== undefined) currentRef.value = val; + }, + ); + watch( + () => options.pageSize, + (val) => { + if (val !== undefined) pageSizeRef.value = val; + }, + ); + watch( + () => options.total, + (val) => { + if (val !== undefined) totalRef.value = val; + }, + ); + + const totalPages = computed(() => { + const total = totalRef.value; + const size = pageSizeRef.value; + return size === 0 ? 0 : Math.ceil(total / size); + }); + + const hasPrev = computed(() => currentRef.value > 1); + const hasNext = computed(() => currentRef.value < totalPages.value); + const isFirstPage = computed(() => currentRef.value === 1); + const isLastPage = computed(() => currentRef.value === totalPages.value); + + const startIndex = computed(() => + totalPages.value === 0 ? 0 : (currentRef.value - 1) * pageSizeRef.value + 1, + ); + + const endIndex = computed(() => Math.min(currentRef.value * pageSizeRef.value, totalRef.value)); + + const params = computed(() => ({ + page: currentRef.value, + pageSize: pageSizeRef.value, + })); + + const setCurrent = (page: number) => { + const safePage = Math.max(1, Math.min(page, totalPages.value || 1)); + if (currentRef.value !== safePage) { + currentRef.value = safePage; + } + }; + + const setPageSize = (size: number) => { + if (pageSizeRef.value !== size) { + pageSizeRef.value = size; + currentRef.value = 1; + } + }; + + const setTotal = (total: number) => { + totalRef.value = total; + const maxPage = Math.max(1, Math.ceil(total / pageSizeRef.value)); + if (currentRef.value > maxPage) { + currentRef.value = maxPage; + } + }; + + const next = () => setCurrent(currentRef.value + 1); + const prev = () => setCurrent(currentRef.value - 1); + + const jump = (page: number) => { + if (!Number.isInteger(page) || page < 1) return; + setCurrent(page); + }; + + const reset = () => { + currentRef.value = defaultCurrent; + pageSizeRef.value = defaultPageSize; + }; + + const refresh = () => { + triggerRef(currentRef); + }; + + return { + // @ts-ignore + current: currentRef, + // @ts-ignore + pageSize: pageSizeRef, + // @ts-ignore + total: totalRef, + pageSizeOptions, + params, + totalPages, + hasPrev, + hasNext, + isFirstPage, + isLastPage, + startIndex, + endIndex, + setCurrent, + setPageSize, + setTotal, + next, + prev, + jump, + reset, + refresh, + }; +} diff --git a/src/hooks/useRequest.ts b/src/hooks/useRequest.ts new file mode 100644 index 0000000..bd1076c --- /dev/null +++ b/src/hooks/useRequest.ts @@ -0,0 +1,170 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +import { ref, Ref, watch, WatchSource, onUnmounted, computed } from 'vue'; + +export interface UseRequestReturn { + /** 纯净的数据,不包含后端外层壳 */ + data: Ref; + /** 加载状态 */ + loading: Ref; + /** 错误对象 */ + error: Ref; + /** 手动触发请求 */ + run: (...args: any[]) => Promise; + /** 取消请求 */ + cancel: () => void; + /** 重置数据 */ + reset: () => void; +} + +export function useRequest( + fetcher: (...args: any[]) => Promise, + options: { + /** 是否手动触发,默认 false (即自动触发) */ + manual?: boolean; + /** 初始数据 */ + initialData?: T; + /** 依赖数组,变化时重新请求 */ + refreshDeps?: WatchSource[]; + /** + * 数据格式化函数 + * 默认逻辑:如果返回是对象且有 data 属性,则返回 res.data,否则返回原数据 + */ + formatResult?: (res: any) => T; + /** 是否准备好可以发起请求,默认 true */ + ready?: Ref; + } = {}, +): UseRequestReturn & { + /** 获取当前 AbortController 的 signal,可传递给 fetcher */ + getSignal: () => AbortSignal | undefined; +} { + const { + manual = false, + initialData, + refreshDeps, + formatResult = (res) => (res && typeof res === 'object' && 'data' in res ? res.data : res), + ready = ref(true), + } = options; + + const data = ref(initialData); + const loading = ref(false); + const error = ref(null); + + let abortController: AbortController | null = null; + let isUnmounted = false; + + onUnmounted(() => { + isUnmounted = true; + if (abortController) { + abortController.abort(); + } + }); + + const run = async (...args: any[]): Promise => { + if (isUnmounted) return undefined; + + // 取消之前的请求 + if (abortController) { + abortController.abort(); + } + + // 创建新的 AbortController + abortController = new AbortController(); + const currentSignal = abortController.signal; + + loading.value = true; + error.value = null; + + try { + // 将 signal 作为最后一个参数传递给 fetcher + // 调用方可以通过最后一个参数获取 signal: async (...args, { signal }) => {...} + const res = await fetcher(...args, { signal: currentSignal }); + + if (currentSignal.aborted || isUnmounted) { + return undefined; + } + + const formattedData = formatResult(res); + + if (!isUnmounted) { + data.value = formattedData; + } + + return formattedData; + } catch (e: any) { + if (e.name === 'AbortError' || e.message?.includes('aborted')) { + return undefined; + } + if (!isUnmounted) { + error.value = e; + } + return undefined; + } finally { + // 只有当前请求未被取消时才重置 loading + if (!currentSignal.aborted && !isUnmounted) { + loading.value = false; + } + // 如果这是当前活动的 controller,清理引用 + if (abortController?.signal === currentSignal) { + abortController = null; + } + } + }; + + const cancel = () => { + if (abortController) { + abortController.abort(); + loading.value = false; + abortController = null; + } + }; + + const reset = () => { + cancel(); + data.value = initialData; + error.value = null; + }; + + // 使用 shouldAutoRun 统一管理自动请求,避免 refreshDeps 和 immediate watch 重复触发 run + const shouldAutoRun = computed(() => !manual && ready.value); + let hasAutoRun = false; // 标记是否已自动执行过,防止重复触发 + + watch( + shouldAutoRun, + (val) => { + if (val && !hasAutoRun) { + hasAutoRun = true; + run(); + } else if (!val) { + // 当条件不满足时重置 hasAutoRun,使下次满足条件时能再次自动执行 + hasAutoRun = false; + } + }, + { immediate: true }, + ); + + // refreshDeps 变化时重新请求(初始化时不再重复触发) + if (refreshDeps && refreshDeps.length > 0) { + watch( + refreshDeps, + () => { + if (shouldAutoRun.value) { + run(); + } + }, + { deep: true }, + ); + } + + const getSignal = () => abortController?.signal; + + return { + // @ts-ignore + data, + loading, + error, + run, + cancel, + reset, + getSignal, + }; +} diff --git a/src/hooks/useState.ts b/src/hooks/useState.ts new file mode 100644 index 0000000..a09d35f --- /dev/null +++ b/src/hooks/useState.ts @@ -0,0 +1,17 @@ +import { ref, Ref } from 'vue'; +/** + * 返回一个 [state, setState] 元组 + */ +export function useState(initialValue: T): [Ref, (newVal: T) => void] { + const state: any = ref(initialValue); + + const setState = (newVal: T) => { + if (typeof newVal === 'function') { + state.value = (newVal as (prev: T) => T)(state.value); + } else { + state.value = newVal; + } + }; + + return [state, setState]; +} diff --git a/src/hooks/useWebSocket.ts b/src/hooks/useWebSocket.ts new file mode 100644 index 0000000..2952105 --- /dev/null +++ b/src/hooks/useWebSocket.ts @@ -0,0 +1,245 @@ +import { ref, watch, onBeforeUnmount, toValue } from 'vue'; +import type { Ref, MaybeRefOrGetter } from 'vue'; + +// --- 类型定义 --- +export type WebSocketStatus = 'connecting' | 'open' | 'closed' | 'error'; + +export interface UseWebSocketOptions { + // 是否自动连接 + autoConnect?: boolean; + // 子协议 + protocols?: string[]; + + // --- 重连配置 --- + reconnectLimit?: number; // 最大重连次数,默认 -1 (无限) + reconnectInterval?: number; // 初始重连间隔 ms + reconnectIncrement?: number; // 每次重连增加的间隔 ms (用于指数退避) + + // --- 心跳配置 --- + heartbeat?: boolean; // 是否开启心跳 + heartbeatInterval?: number; // 心跳间隔 ms + heartbeatMessage?: any; // 心跳发送的数据 + + // --- 回调钩子 --- + onOpen?: (event: Event) => void; + onClose?: (event: CloseEvent) => void; + onMessage?: (data: any, event: MessageEvent) => void; + onError?: (event: Event) => void; +} + +// --- 返回值接口 --- +export interface UseWebSocketReturn { + status: Ref; + latestData: Ref; // 最新接收到的数据 + send: (data: any) => void; // 发送方法 + connect: () => void; // 手动连接 + disconnect: () => void; // 手动断开 +} + +/** + * useWebSocket Hook + * 仿照 ahooks 设计,支持动态配置、指数退避重连、心跳检测 + */ +// 模块级变量,替代 window 全局挂载,避免全局污染和内存泄漏 +const webSocketList: WebSocket[] = []; + +export function useWebSocket( + url: MaybeRefOrGetter, + options: UseWebSocketOptions = {}, +): UseWebSocketReturn { + const { + autoConnect = true, + protocols = [], + reconnectLimit = -1, + reconnectInterval = 1000, + reconnectIncrement = 1000, + heartbeat = true, + heartbeatInterval = 30000, + heartbeatMessage = 'ping', + onOpen, + onClose, + onMessage, + onError, + } = options; + + // --- 响应式状态 --- + const status = ref('closed'); + const latestData = ref(null); + const wsRef = ref(null); + + // --- 内部变量 --- + let reconnectCount = 0; + let reconnectTimer: ReturnType | null = null; + let heartbeatTimer: ReturnType | null = null; + + // --- 辅助函数 --- + + // 清除所有定时器 + const clearTimers = () => { + if (reconnectTimer) clearTimeout(reconnectTimer); + if (heartbeatTimer) clearInterval(heartbeatTimer); + }; + + // 启动心跳 + const startHeartbeat = () => { + if (!heartbeat) return; + stopHeartbeat(); // 防止重复启动 + + heartbeatTimer = setInterval(() => { + if (wsRef.value && wsRef.value.readyState === WebSocket.OPEN) { + wsRef.value.send( + typeof heartbeatMessage === 'string' + ? heartbeatMessage + : JSON.stringify(heartbeatMessage), + ); + } + }, heartbeatInterval); + }; + + // 停止心跳 + const stopHeartbeat = () => { + if (heartbeatTimer) { + clearInterval(heartbeatTimer); + heartbeatTimer = null; + } + }; + + // 建立连接的核心逻辑 + const connect = () => { + // 如果已经有连接且是开启状态,不重复创建 + if (wsRef.value?.readyState === WebSocket.OPEN) return; + + // 关闭旧连接(如果有) + if (wsRef.value) { + wsRef.value.close(); + wsRef.value = null; + } + + status.value = 'connecting'; + + try { + // 使用 toValue 支持响应式 URL + const wsUrl = toValue(url); + wsRef.value = new WebSocket(wsUrl, protocols); + + // 追踪所有 WebSocket 实例用于调试和清理(使用模块级变量,避免全局污染) + webSocketList.push(wsRef.value); + + wsRef.value.onopen = (event) => { + status.value = 'open'; + reconnectCount = 0; // 重置重连计数 + startHeartbeat(); // 启动心跳 + onOpen?.(event); + }; + + wsRef.value.onmessage = (event) => { + // 简单的心跳回显处理:如果收到的消息等于发送的心跳消息,则忽略(或者根据业务协议处理 pong) + // 这里假设服务端会原样返回 ping 或者返回特定的 pong + // 实际项目中建议检查 event.data + + try { + const data = JSON.parse(event.data); + latestData.value = data; + onMessage?.(data, event); + } catch (e) { + latestData.value = event.data; + onMessage?.(event.data, event); + } + }; + + wsRef.value.onerror = (event) => { + status.value = 'error'; + onError?.(event); + }; + + wsRef.value.onclose = (event) => { + status.value = 'closed'; + stopHeartbeat(); + onClose?.(event); + + // 触发重连逻辑 + handleReconnect(); + }; + } catch (err) { + console.error(err); + status.value = 'error'; + onError?.(err as Event); + handleReconnect(); + } + }; + + // 处理重连(指数退避策略) + const handleReconnect = () => { + // 如果是用户手动调用的 disconnect,不应该重连(可以通过标记位控制,这里简化处理:只要没达到限制就重连) + // 如果需要彻底断开,请调用 disconnect() + + if (reconnectLimit !== -1 && reconnectCount >= reconnectLimit) { + return; + } + + // 计算延迟时间:线性增长 1s, 2s, 3s, 4s... (最大 10s) + const delay = Math.min(10000, reconnectInterval + reconnectCount * reconnectIncrement); + + reconnectCount++; + + reconnectTimer = setTimeout(() => { + connect(); + }, delay); + }; + + // 发送消息 + const send = (data: any) => { + if (wsRef.value && wsRef.value.readyState === WebSocket.OPEN) { + const strData = typeof data === 'string' ? data : JSON.stringify(data); + wsRef.value.send(strData); + } else { + console.warn('WebSocket 未连接,无法发送消息'); + } + }; + + // 手动断开(通常意味着不再自动重连,除非再次调用 connect) + const disconnect = () => { + reconnectCount = reconnectLimit; // 设置计数为最大值,阻止后续重连逻辑 + clearTimers(); + if (wsRef.value) { + // 从模块级列表中移除这个实例 + const index = webSocketList.indexOf(wsRef.value); + if (index > -1) { + webSocketList.splice(index, 1); + } + wsRef.value.close(); + wsRef.value = null; + } + status.value = 'closed'; + }; + + // --- 监听与副作用 --- + + // 监听 URL 变化,如果变了则重新连接 + watch( + () => toValue(url), + () => { + if (status.value !== 'closed') { + connect(); + } + }, + ); + + // 组件卸载时清理资源 + onBeforeUnmount(() => { + disconnect(); + }); + + // 初始化:如果不是手动模式,则自动连接 + if (autoConnect) { + connect(); + } + + return { + status, + latestData, + send, + connect, + disconnect, + }; +} diff --git a/src/layouts/BasicLayout.module.less b/src/layouts/BasicLayout.module.less new file mode 100644 index 0000000..a3fc109 --- /dev/null +++ b/src/layouts/BasicLayout.module.less @@ -0,0 +1,57 @@ +.container { + min-height: 100vh; +} + +.sider { + box-shadow: 2px 0 8px rgba(0, 0, 0, 0.08); +} + +.logo { + height: 56px; + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; + color: #fff; + background: rgba(255, 255, 255, 0.08); +} + +.logoText { + font-size: 16px; + font-weight: 600; + white-space: nowrap; +} + +.header { + background: #fff; + padding: 0 16px; + display: flex; + align-items: center; + box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); +} + +.trigger { + font-size: 18px; + cursor: pointer; + transition: color 0.3s; + padding: 0 12px; + display: inline-flex; + align-items: center; + + &:hover { + color: #1677ff; + } +} + +.content { + margin: 16px; + padding: 24px; + background: #fff; + border-radius: 8px; + min-height: 280px; +} + +.footer { + text-align: center; + color: rgba(0, 0, 0, 0.45); +} diff --git a/src/layouts/BasicLayout.tsx b/src/layouts/BasicLayout.tsx new file mode 100644 index 0000000..f01ba2a --- /dev/null +++ b/src/layouts/BasicLayout.tsx @@ -0,0 +1,71 @@ +import { computed, defineComponent, ref } from 'vue'; +import { useRouter, useRoute, RouterView } from 'vue-router'; +import { Layout, Menu } from 'ant-design-vue'; +import type { MenuProps } from 'ant-design-vue'; +import { + DashboardOutlined, + InfoCircleOutlined, + MenuFoldOutlined, + MenuUnfoldOutlined, +} from '@ant-design/icons-vue'; +import styles from './BasicLayout.module.less'; + +const { Header, Sider, Content, Footer } = Layout; + +/** + * 基础布局:左侧导航 + 顶部栏 + 内容区 + 页脚 + */ +export default defineComponent({ + name: 'BasicLayout', + setup() { + const route = useRoute(); + const router = useRouter(); + const collapsed = ref(false); + + const selectedKeys = computed(() => [route.path]); + + const menuItems: MenuProps['items'] = [ + { key: '/dashboard', icon: () => , label: '工作台' }, + { key: '/about', icon: () => , label: '关于' }, + ]; + + const handleMenuClick: MenuProps['onClick'] = ({ key }) => { + router.push(key as string); + }; + + const toggleCollapsed = () => { + collapsed.value = !collapsed.value; + }; + + return () => ( + + +
+ {collapsed.value ? 'CPMS' : 'CPMS 运营平台'} +
+ + + + +
+ + {collapsed.value ? : } + +
+ + + + + +
CPMS 运营平台 ©{new Date().getFullYear()}
+
+ + ); + }, +}); diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..2ed0b1f --- /dev/null +++ b/src/main.ts @@ -0,0 +1,14 @@ +import { createApp } from 'vue'; +import Antd from 'ant-design-vue'; +import 'ant-design-vue/dist/reset.css'; + +import App from './App'; +import router from './router'; +import './assets/styles/index.less'; + +const app = createApp(App); + +app.use(router); +app.use(Antd); + +app.mount('#app'); diff --git a/src/pages/login/index.module.less b/src/pages/login/index.module.less new file mode 100644 index 0000000..7932457 --- /dev/null +++ b/src/pages/login/index.module.less @@ -0,0 +1,20 @@ +.container { + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); +} + +.card { + width: 400px; + max-width: 90vw; + border-radius: 12px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12); + + :global(.ant-card-head-title) { + text-align: center; + font-size: 18px; + font-weight: 600; + } +} diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx new file mode 100644 index 0000000..3f7ea8a --- /dev/null +++ b/src/pages/login/index.tsx @@ -0,0 +1,83 @@ +import { defineComponent, reactive, ref } from 'vue'; +import { Button, Card, Form, FormItem, Input, message } from 'ant-design-vue'; +import { UserOutlined, LockOutlined } from '@ant-design/icons-vue'; +import { useRouter } from 'vue-router'; +import { auth } from '@/hooks/useAuth'; +import styles from './index.module.less'; + +interface LoginForm { + username: string; + password: string; +} + +/** + * 登录页 + */ +export default defineComponent({ + name: 'LoginPage', + setup() { + const router = useRouter(); + const loading = ref(false); + + const form = reactive({ + username: 'admin', + password: '123456', + }); + + const rules = { + username: [{ required: true, message: '请输入用户名' }], + password: [{ required: true, message: '请输入密码' }], + }; + + const handleSubmit = async () => { + if (!form.username || !form.password) { + message.warning('请输入用户名和密码'); + return; + } + + loading.value = true; + + // TODO: 替换为真实登录接口 + // const res = await post('/login', { ...form }); + // auth.login(res.token); + + setTimeout(() => { + auth.login('mock_token_' + Date.now()); + message.success('登录成功'); + loading.value = false; + router.push('/dashboard'); + }, 600); + }; + + return () => ( +
+ +
+ + }} + /> + + + }} + /> + + + + +
+
+
+ ); + }, +}); diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..ae9e49e --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,40 @@ +import { createRouter, createWebHistory } from 'vue-router'; +import { routes } from './routes'; +import { auth } from '@/hooks/useAuth'; + +const router = createRouter({ + history: createWebHistory(import.meta.env.VITE_BASE_URL || '/'), + routes, + scrollBehavior: () => ({ left: 0, top: 0 }), +}); + +// 路由守卫:登录鉴权 + 页面标题 +router.beforeEach((to, _from, next) => { + const isLoggedIn = auth.isLoggedIn(); + + // 设置页面标题 + const appTitle = import.meta.env.VITE_APP_TITLE || 'CPMS 运营平台'; + document.title = to.meta.title ? `${to.meta.title} - ${appTitle}` : appTitle; + + // 如果访问的是登录页 + if (to.path === '/login') { + if (isLoggedIn) { + // 已登录则重定向到首页 + next('/dashboard'); + } else { + // 未登录则允许访问登录页 + next(); + } + } else { + // 访问其他页面 + if (isLoggedIn) { + // 已登录则允许访问 + next(); + } else { + // 未登录则重定向到登录页 + next('/login'); + } + } +}); + +export default router; diff --git a/src/router/routes.ts b/src/router/routes.ts new file mode 100644 index 0000000..af168c7 --- /dev/null +++ b/src/router/routes.ts @@ -0,0 +1,68 @@ +import type { RouteRecordRaw } from 'vue-router'; +import { createRoute } from './utils'; + +/** + * ====== 业务路由模块 ====== + * 实际项目中按模块拆分,如 eventsRoutes、walletRoutes 等, + * 然后在下方 routes 数组的布局 children 中引入。 + * 参考示例(嵌套路由): + * + * const eventsRoutes = { + * path: '/events', + * name: 'EventsModule', + * redirect: '/events/list', + * meta: { title: '我的赛事', activeMenu: '/events' }, + * children: [ + * createRoute('list', () => import('@/pages/events/list'), { title: '赛事列表' }), + * { + * path: 'bracket', + * name: 'BracketPage', + * component: () => import('@/pages/events/bracket'), + * meta: { title: '赛事详情' }, + * children: [ + * createRoute('player-management', () => import('@/pages/events/bracket/player-management'), { title: '选手管理' }), + * createRoute('match-result', () => import('@/pages/events/bracket/match-result'), { title: '比赛结果' }), + * ], + * }, + * ], + * }; + */ + +export const routes: RouteRecordRaw[] = [ + // ── 登录页(不经过布局)── + { + path: '/login', + name: 'Login', + component: () => import('@/pages/login'), + meta: { title: '登录' }, + }, + + // ── 主布局(需要登录)── + { + path: '/', + component: () => import('@/layouts/BasicLayout'), + children: [ + // 业务模块路由在此添加,例如:eventsRoutes, walletRoutes + + createRoute('/dashboard', () => import('@/views/Dashboard'), { + title: '工作台', + icon: 'DashboardOutlined', + }), + createRoute('/about', () => import('@/views/About'), { + title: '关于', + icon: 'InfoCircleOutlined', + }), + + // 默认重定向 + { path: '/', redirect: '/dashboard' }, + ], + }, + + // ── 404 ── + { + path: '/:pathMatch(.*)*', + name: 'NotFound', + component: () => import('@/views/NotFound'), + meta: { title: '页面不存在' }, + }, +]; diff --git a/src/router/utils.ts b/src/router/utils.ts new file mode 100644 index 0000000..03dc5a2 --- /dev/null +++ b/src/router/utils.ts @@ -0,0 +1,40 @@ +import type { RouteRecordRaw } from 'vue-router'; + +/** 路由 meta 类型 */ +export type AppMeta = { + title: string; + icon?: string; + hideInMenu?: boolean; + activeMenu?: string; +}; + +/** + * 快速创建路由记录 + * 根据路径自动生成 PascalCase 路由 name + * + * @example + * createRoute('list', () => import('@/pages/home'), { title: '赛事列表' }) + * // => { path: 'list', name: 'List', meta: {...}, component: ... } + */ +export function createRoute( + path: string, + component: RouteRecordRaw['component'], + meta: AppMeta, + children: RouteRecordRaw[] = [], +): RouteRecordRaw { + const cleanPath = path.replace(/[:/]/g, '-'); + + const name = cleanPath + .split('-') + .filter(Boolean) + .map((p) => p.charAt(0).toUpperCase() + p.slice(1)) + .join(''); + + return { + path, + name: name || undefined, + meta, + component, + children, + }; +} diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000..9182e7d --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,42 @@ +/** + * 全局类型定义 + */ + +/** 分页查询参数 */ +export interface PageParams { + page: number; + size: number; +} + +/** 分页返回结果 */ +export interface PageResult { + list: T[]; + total: number; + page: number; + size: number; +} + +/** 通用下拉选项 */ +export interface SelectOption { + label: string; + value: string | number; + disabled?: boolean; +} + +/** 路由 meta 扩展(与 router/utils.ts 的 AppMeta 保持一致) */ +declare module 'vue-router' { + interface RouteMeta { + title?: string; + icon?: string; + /** 是否需要登录 */ + requiresAuth?: boolean; + /** 是否在菜单中隐藏 */ + hideInMenu?: boolean; + /** 旧字段,等价于 hideInMenu */ + hidden?: boolean; + /** 高亮的菜单路径(用于详情页高亮列表项) */ + activeMenu?: string; + /** 权限标识 */ + permission?: string; + } +} diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..c97158a --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,90 @@ +/** + * 通用工具函数 + */ + +/** + * 生成唯一 ID + */ +export function uniqueId(prefix = ''): string { + const id = Date.now().toString(36) + Math.random().toString(36).slice(2, 8); + return prefix ? `${prefix}_${id}` : id; +} + +/** + * 简易深拷贝(基于 JSON,适用于纯数据对象) + */ +export function deepClone(value: T): T { + return JSON.parse(JSON.stringify(value)); +} + +/** + * 防抖 + */ +export function debounce any>(fn: T, wait = 300) { + let timer: ReturnType | null = null; + const debounced = (...args: Parameters) => { + if (timer) clearTimeout(timer); + timer = setTimeout(() => fn(...args), wait); + }; + debounced.cancel = () => { + if (timer) clearTimeout(timer); + timer = null; + }; + return debounced; +} + +/** + * 节流 + */ +export function throttle any>(fn: T, wait = 300) { + let lastTime = 0; + return (...args: Parameters) => { + const now = Date.now(); + if (now - lastTime >= wait) { + lastTime = now; + fn(...args); + } + }; +} + +/** + * 格式化日期 + */ +export function formatDate(date: Date | string | number, format = 'YYYY-MM-DD HH:mm:ss'): string { + const d = new Date(date); + if (Number.isNaN(d.getTime())) return ''; + + const pad = (n: number) => String(n).padStart(2, '0'); + const map: Record = { + YYYY: String(d.getFullYear()), + MM: pad(d.getMonth() + 1), + DD: pad(d.getDate()), + HH: pad(d.getHours()), + mm: pad(d.getMinutes()), + ss: pad(d.getSeconds()), + }; + + return format.replace(/YYYY|MM|DD|HH|mm|ss/g, (match) => map[match]); +} + +/** + * 树形数据扁平化 + */ +export interface TreeNode { + id: string | number; + children?: TreeNode[]; + [key: string]: any; +} + +export function flattenTree(tree: T[]): T[] { + const result: T[] = []; + const stack = [...tree].reverse(); + while (stack.length) { + const node = stack.pop() as T; + result.push(node); + if (node.children?.length) { + stack.push(...(node.children as T[]).reverse()); + } + } + return result; +} diff --git a/src/utils/request.ts b/src/utils/request.ts new file mode 100644 index 0000000..92b1385 --- /dev/null +++ b/src/utils/request.ts @@ -0,0 +1,164 @@ +import { auth } from '@/hooks/'; +import { message } from 'ant-design-vue'; + +const baseUrl = import.meta.env?.VITE_API_BASE_URL || ''; +const DEFAULT_TIMEOUT = 10000; + +const activeControllers = new Set(); + +/** 统一处理 401 未授权逻辑 */ +const handleUnauthorized = (msg?: string) => { + auth.logout(); + message.error(msg || '登录状态已过期,请重新登录'); + window.location.href = '/login'; +}; + +const request = ( + url: string, + options: RequestInit & { + query?: Record; + responseType?: 'json' | 'blob'; + } = {}, +) => { + let finalUrl = baseUrl + url; + + if (options.query) { + finalUrl += '?' + new URLSearchParams(options.query).toString(); + } + + const token = auth.token.value; + + const headers: Record = {}; + if (!(options.body instanceof FormData)) { + headers['Content-Type'] = 'application/json'; + } + if (token) { + headers['Authorization'] = `Bearer ${token}`; + } + + // 优先使用外部传入的 signal(来自 useRequest 取消机制); + // 无外部 signal 时自建 controller 用于超时取消 + const externalSignal = (options as RequestInit & { signal?: AbortSignal }).signal; + const controller = new AbortController(); + + activeControllers.add(controller); + + // 合并外部 signal 与内部 controller:任一 abort 都会取消请求 + const onExternalAbort = () => controller.abort(); + if (externalSignal) { + if (externalSignal.aborted) { + controller.abort(); + } else { + externalSignal.addEventListener('abort', onExternalAbort, { once: true }); + } + } + + const init: RequestInit = { + ...options, + headers: { ...headers, ...(options.headers as Record) }, + signal: controller.signal, + }; + + const timeoutId = setTimeout(() => { + controller.abort(); // 超时触发 abort + }, DEFAULT_TIMEOUT); + + const cleanupSignal = () => { + clearTimeout(timeoutId); + if (externalSignal) externalSignal.removeEventListener('abort', onExternalAbort); + }; + + return fetch(finalUrl, init) + .then(async (res) => { + cleanupSignal(); + activeControllers.delete(controller); + + if (res.status === 401) { + handleUnauthorized(); + return Promise.reject(new Error('Unauthorized')); + } + + if (res.status === 500) { + message.error('服务器开小差了,请稍后再试'); + const errorData = await res.json().catch(() => ({})); + return Promise.reject(new Error(errorData.message || '服务器内部错误')); + } + + if (!res.ok) { + const errorData = await res.json().catch(() => ({})); + message.error(errorData.message || '请求失败'); + return Promise.reject(new Error(errorData.message || '请求失败')); + } + + if (options.responseType === 'blob') { + return res.blob(); + } + + const data = await res.json(); + + if (data.code === 401) { + handleUnauthorized(data.msg); + return Promise.reject(new Error(data.msg || 'Unauthorized')); + } + + return data; + }) + .catch((err) => { + cleanupSignal(); + + activeControllers.delete(controller); + + if (err.name === 'AbortError' || err.message === 'The user aborted a request.') { + // 使用特殊标记对象区分“请求被取消”和“请求成功但返回 null” + return Promise.resolve({ __aborted: true }); + } + + if (err.message === 'Failed to fetch') { + message.error('网络连接失败,请检查网络'); + } + + return Promise.reject(err); + }); +}; + +export const cancelAllRequests = () => { + activeControllers.forEach((controller) => { + controller.abort(); + }); + activeControllers.clear(); +}; + +export { request }; + +export const get = (url: string, query?: Record, options?: { signal?: AbortSignal }) => + request(url, { method: 'GET', query, signal: options?.signal }); + +export const post = ( + url: string, + body?: any, + query?: Record, + options?: { signal?: AbortSignal }, +) => + request(url, { + method: 'POST', + body: body ? JSON.stringify(body) : undefined, + query, + signal: options?.signal, + }); + +export const put = (url: string, body?: any, query?: Record) => + request(url, { + method: 'PUT', + body: body ? JSON.stringify(body) : undefined, + query, + }); + +export const del = (url: string, query?: Record) => + request(url, { method: 'DELETE', query }); + +export default { + get, + post, + put, + delete: del, +}; diff --git a/src/views/About.module.less b/src/views/About.module.less new file mode 100644 index 0000000..c52f57c --- /dev/null +++ b/src/views/About.module.less @@ -0,0 +1,20 @@ +.container { + // 容器 +} + +.title { + margin-top: 0; + margin-bottom: 24px; + font-size: 20px; + font-weight: 600; +} + +.subtitle { + margin: 16px 0 8px; +} + +.list { + margin: 0; + padding-left: 20px; + line-height: 2; +} diff --git a/src/views/About.tsx b/src/views/About.tsx new file mode 100644 index 0000000..f167c8c --- /dev/null +++ b/src/views/About.tsx @@ -0,0 +1,42 @@ +import { defineComponent } from 'vue'; +import { Card } from 'ant-design-vue'; +import styles from './About.module.less'; + +interface TechItem { + name: string; + version: string; +} + +/** + * 关于页面 + */ +export default defineComponent({ + name: 'About', + setup() { + const techStack: TechItem[] = [ + { name: 'Vue', version: '^3.3.0' }, + { name: 'Vite', version: '^5.0.0' }, + { name: 'TypeScript', version: '^5.3.0' }, + { name: 'Ant Design Vue', version: '^4.0.0' }, + { name: 'Vue Router', version: '^4.2.0' }, + { name: 'Less', version: '^4.6.4' }, + ]; + + return () => ( +
+

关于

+ +

CPMS 运营平台前端 PC 端。

+

技术栈

+
    + {techStack.map((item) => ( +
  • + {item.name} — {item.version} +
  • + ))} +
+
+
+ ); + }, +}); diff --git a/src/views/Dashboard.module.less b/src/views/Dashboard.module.less new file mode 100644 index 0000000..e816330 --- /dev/null +++ b/src/views/Dashboard.module.less @@ -0,0 +1,27 @@ +.container { + // 容器 +} + +.title { + margin-top: 0; + margin-bottom: 24px; + font-size: 20px; + font-weight: 600; +} + +.panel { + margin-top: 16px; + + ul { + margin: 12px 0 0; + padding-left: 20px; + line-height: 2; + } + + code { + padding: 2px 8px; + background: #f5f5f5; + border-radius: 4px; + font-size: 13px; + } +} diff --git a/src/views/Dashboard.tsx b/src/views/Dashboard.tsx new file mode 100644 index 0000000..cf3c62a --- /dev/null +++ b/src/views/Dashboard.tsx @@ -0,0 +1,67 @@ +import { defineComponent } from 'vue'; +import { Card, Col, Row, Statistic } from 'ant-design-vue'; +import styles from './Dashboard.module.less'; + +interface StatItem { + title: string; + value: number; + suffix: string; + precision?: number; +} + +/** + * 工作台 / 仪表盘 + */ +export default defineComponent({ + name: 'Dashboard', + setup() { + const stats: StatItem[] = [ + { title: '今日访问', value: 1280, suffix: '次' }, + { title: '活跃用户', value: 368, suffix: '人' }, + { title: '订单总数', value: 9920, suffix: '单' }, + { title: '处理率', value: 96.8, suffix: '%', precision: 1 }, + ]; + + return () => ( +
+

工作台

+ + + {stats.map((item) => ( + + + + + + ))} + + + +

+ 欢迎使用 CPMS 运营平台。这是一个基于 Vue 3 + Vite + TypeScript + Ant Design Vue + 搭建的中后台管理项目骨架,采用 TSX 写法,你可以在此基础上继续开发业务功能。 +

+
    +
  • + 开发命令:npm run dev +
  • +
  • + 构建(测试环境):npm run build:test +
  • +
  • + 构建(生产环境):npm run build:prod +
  • +
  • + 代码检查:npm run lint +
  • +
+
+
+ ); + }, +}); diff --git a/src/views/NotFound.tsx b/src/views/NotFound.tsx new file mode 100644 index 0000000..7070442 --- /dev/null +++ b/src/views/NotFound.tsx @@ -0,0 +1,32 @@ +import { defineComponent } from 'vue'; +import { useRouter } from 'vue-router'; +import { Button, Result } from 'ant-design-vue'; + +/** + * 404 页面 + */ +export default defineComponent({ + name: 'NotFound', + setup() { + const router = useRouter(); + + const goHome = () => router.push('/'); + + return () => ( + + {{ + extra: () => ( + + ), + }} + + ); + }, +}); diff --git a/start-debug.js b/start-debug.js new file mode 100644 index 0000000..1b9f491 --- /dev/null +++ b/start-debug.js @@ -0,0 +1,131 @@ +#!/usr/bin/env node + +const { execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); +const readline = require('readline'); + +function loadEnv(filePath) { + if (!fs.existsSync(filePath)) return {}; + const content = fs.readFileSync(filePath, 'utf8'); + const env = {}; + content.split('\n').forEach((line) => { + const match = line.match(/^([^=:#]+?)=(.*)$/); + if (match) { + env[match[1].trim()] = match[2].trim().replace(/^['"](.*)['"]$/, '$1'); + } + }); + return env; +} + +function getComponentLibs(env) { + const libs = []; + + libs.push({ + name: 'cpms_web_component (默认)', + path: path.resolve(__dirname, '../cpms_web_component'), + useKey: null, + usePath: null, + }); + + for (const key in env) { + if (key.startsWith('COMPONENT_LIB_') && key !== 'COMPONENT_LIB_PATH') { + libs.push({ + name: key.replace('COMPONENT_LIB_', ''), + path: path.resolve(__dirname, env[key]), + useKey: key.replace('COMPONENT_LIB_', ''), + usePath: null, + }); + } + } + + if (env.COMPONENT_LIB_PATH) { + libs.push({ + name: '自定义路径', + path: path.resolve(__dirname, env.COMPONENT_LIB_PATH), + useKey: null, + usePath: env.COMPONENT_LIB_PATH, + }); + } + + return libs; +} + +async function selectLib(libs) { + if (libs.length === 1) return libs[0]; + + console.log('📦 请选择要使用的组件库:'); + libs.forEach((lib, i) => { + const exists = fs.existsSync(lib.path) ? '✅' : '❌'; + console.log(` ${i + 1}. ${lib.name} ${exists}`); + console.log(` ${lib.path}`); + }); + console.log(' 0. 使用 npm 版本'); + + const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); + return new Promise((resolve) => { + rl.question(`\n请输入选项 (0-${libs.length},回车默认): `, (answer) => { + rl.close(); + if (answer === '0') resolve(null); + else if (answer && /^\d+$/.test(answer)) { + const idx = parseInt(answer) - 1; + resolve(idx >= 0 && idx < libs.length ? libs[idx] : libs[0]); + } else { + resolve(libs[0]); + } + }); + }); +} + +async function main() { + const localEnv = loadEnv(path.resolve(__dirname, '.env.local')); + const libs = getComponentLibs(localEnv); + + console.log('🚀 启动本地调试模式...\n'); + const selected = await selectLib(libs); + + const mergedEnv = { ...process.env, ...localEnv, LOCAL_DEBUG: 'true' }; + + if (!selected) { + console.log('\n📦 使用 npm 版本'); + delete mergedEnv.COMPONENT_LIB; + delete mergedEnv.COMPONENT_LIB_PATH; + } else { + const exists = fs.existsSync(selected.path); + if (!exists) { + console.warn(`\n⚠️ 组件库不存在: ${selected.name}`); + console.warn(` ${selected.path}`); + console.warn(' 将使用 npm 版本'); + delete mergedEnv.COMPONENT_LIB; + delete mergedEnv.COMPONENT_LIB_PATH; + } else { + console.log(`\n📦 ${selected.name}`); + console.log(`📍 ${selected.path}`); + if (selected.useKey) { + mergedEnv.COMPONENT_LIB = selected.useKey; + delete mergedEnv.COMPONENT_LIB_PATH; + } else if (selected.usePath) { + mergedEnv.COMPONENT_LIB_PATH = selected.usePath; + delete mergedEnv.COMPONENT_LIB; + } else { + delete mergedEnv.COMPONENT_LIB; + delete mergedEnv.COMPONENT_LIB_PATH; + } + } + } + + console.log('\n⏳ 启动 Vite...\n'); + + try { + execSync('npx vite --port 3000 --open --strictPort false', { + stdio: 'inherit', + cwd: process.cwd(), + env: mergedEnv, + }); + } catch (error) { + console.error('❌ 启动失败:', error.message); + process.exit(1); + } +} + +main(); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..0c162e4 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "jsx": "preserve", + "jsxImportSource": "vue", + "resolveJsonModule": true, + "isolatedModules": true, + "esModuleInterop": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + "noEmit": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + }, + "types": ["node", "vite/client"] + }, + "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx"], + "exclude": ["node_modules", "dist", "src/router copy"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..1a555ac --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "strict": true, + "types": ["node"] + }, + "include": ["vite.config.ts"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..21e6065 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,54 @@ +import { defineConfig, loadEnv } from 'vite'; +import vue from '@vitejs/plugin-vue'; +import vueJsx from '@vitejs/plugin-vue-jsx'; +import { resolve } from 'path'; + +// https://vitejs.dev/config/ +export default defineConfig(({ mode }) => { + const env = loadEnv(mode, process.cwd(), ''); + + return { + base: env.VITE_BASE_URL || '/', + plugins: [vue(), vueJsx()], + resolve: { + alias: { + '@': resolve(__dirname, 'src'), + }, + }, + css: { + modules: { + localsConvention: 'camelCaseOnly', + }, + preprocessorOptions: { + less: { + javascriptEnabled: true, + }, + }, + }, + server: { + host: '0.0.0.0', + port: Number(env.VITE_PORT) || 5173, + open: true, + proxy: { + '/api': { + target: env.VITE_API_BASE_URL || 'http://localhost:3000', + changeOrigin: true, + rewrite: (path) => path.replace(/^\/api/, ''), + }, + }, + }, + build: { + outDir: 'dist', + sourcemap: mode !== 'production', + chunkSizeWarningLimit: 1500, + rollupOptions: { + output: { + manualChunks: { + vue: ['vue', 'vue-router'], + antd: ['ant-design-vue'], + }, + }, + }, + }, + }; +});