commit d759a9e7405df689043b0f5717c33e91abdfeaf3 Author: dcr_xuxgc Date: Fri Jun 12 17:49:54 2026 +0800 init diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..1962d82 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,30 @@ +{ + "permissions": { + "allow": [ + "Bash(npm run *)", + "Bash(git stash *)", + "Bash(npm install *)", + "Bash(node src/scripts/initDb.js)", + "Bash(node -e \"require\\('dotenv'\\).config\\(\\); console.log\\('DB_HOST:', process.env.DB_HOST\\); console.log\\('DB_PORT:', process.env.DB_PORT\\); console.log\\('DB_USER:', process.env.DB_USER\\); console.log\\('DB_NAME:', process.env.DB_NAME\\);\")", + "Bash(node -e ' *)", + "Bash(curl -s http://localhost:3000/api/settings)", + "Bash(curl *)", + "Bash(node src/scripts/migrateColumns.js)", + "Bash(mysql *)", + "Bash(node -e \"const d=require\\('fs'\\).readFileSync\\(0,'utf8'\\); const j=JSON.parse\\(d\\); console.log\\('uploadedImages length:', j.uploadedImages?.length\\); console.log\\('uploadedImages[0] id:', j.uploadedImages?.[0]?.id\\);\")", + "Bash(node -e \"const j=require\\('/tmp/settings.json'\\); console.log\\('uploadedImages length:', j.uploadedImages?.length\\); console.log\\('uploadedImages[0] id:', j.uploadedImages?.[0]?.id\\);\")", + "Bash(node -p \"const j=JSON.parse\\(require\\('fs'\\).readFileSync\\(0,'utf8'\\)\\); j.uploadedImages?.length\")", + "Bash(node src/index.js)", + "Bash(netstat -ano)", + "Bash(grep3000)", + "Bash(node src/scripts/addSamplePosts.js)", + "Bash(node src/scripts/insertPosts.js)", + "Bash(npm list *)", + "Bash(node -e \"require\\('./src/index.js'\\)\")", + "Bash(npx pkg *)", + "Bash(node package.js)", + "Bash(npm view *)", + "Bash(git restore *)" + ] + } +} diff --git a/.env b/.env new file mode 100644 index 0000000..7e77aa7 --- /dev/null +++ b/.env @@ -0,0 +1,8 @@ +# 本地开发环境配置 +# npm run dev 使用此配置(mode=development) + +# 后端端口 +VITE_API_PORT=4501 + +# 留空,使用本地代理模式 +VITE_SERVER_URL= \ No newline at end of file diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..dc14e77 --- /dev/null +++ b/.env.development @@ -0,0 +1,7 @@ +# 本地开发环境配置 + +# 后端端口 +VITE_API_PORT=4501 + +# 留空,使用本地代理模式 +VITE_SERVER_URL= \ No newline at end of file diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..2289b06 --- /dev/null +++ b/.env.example @@ -0,0 +1,8 @@ +# 前端环境变量配置模板 +# 实际配置请使用 .env.development(本地)或 .env.production(远程) + +# 后端端口 +VITE_API_PORT=4501 + +# 远程服务器地址(为空时使用本地代理模式) +VITE_SERVER_URL=http://43.156.91.115:4501 \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..5f34bab --- /dev/null +++ b/.env.production @@ -0,0 +1,7 @@ +# 远程生产环境配置 + +# 后端端口 +VITE_API_PORT=4501 + +# 远程服务器地址(直接连接,不走代理) +VITE_SERVER_URL=http://43.156.91.115:4501 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..133da84 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..1c5c4f2 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,138 @@ +# 修改记录 + +## 2026-06-10 + +### 1. 优化图片上传性能 +**文件**: `server/src/routes/settings.js` + +**问题**: 批量上传图片到 RUSTFS 时串行执行,每张图片需等待上一张完成,导致上传时间过长。 + +**解决方案**: 将 `for...of` 串行上传改为 `Promise.all` 并行上传。 + +**改动内容**: +- 将批量上传接口 `/upload-images` 的串行逻辑改为并行 +- 使用 `Promise.all()` 同时上传所有图片 + +--- + +### 2. 新增服务端配置页面 +**目标**: 在前端设置界面添加配置页面,支持动态修改 .env 配置并重启后端服务。 + +#### 后端新增文件 + +**`server/src/config/envManager.js`** +- `readEnv()` - 读取并解析 .env 文件 +- `writeEnv(config)` - 将配置对象写入 .env 文件 +- `getSafeConfig()` - 返回安全展示的配置(密码用 `******` 替代) + +**`server/src/routes/config.js`** +- `GET /api/config` - 获取当前配置(密码隐藏) +- `PUT /api/config` - 更新配置并写入 .env 文件 +- `POST /api/config/restart` - 优雅重启后端服务 + +#### 后端修改文件 + +**`server/src/index.js`** +- 注册新路由 `app.use('/api/config', configRouter)` + +#### 前端新增文件 + +**`src/views/ServerConfigView.vue`** +- 配置分组显示:数据库、RUSTFS、服务器 +- 密码字段显示为 `******`,修改时留空则不修改原密码 +- 保存按钮 - 调用 API 保存配置到 .env +- 重启按钮 - 调用 API 优雅重启服务(需 PM2 等进程管理器) + +#### 前端修改文件 + +**`src/router/index.js`** +- 添加路由 `/server-config` -> ServerConfigView(懒加载) + +**`src/i18n/index.js`** +- 添加 `serverConfig` 中英文翻译 + +**`src/components/SiteHeader.vue`** +- 导航栏添加"服务端配置"链接 + +--- + +### 使用说明 + +1. **启动后端**(需使用 PM2 管理进程): + ```bash + pm2 start npm -- run dev + ``` + +2. **访问配置页面**: 启动后端后访问 `/server-config` + +3. **保存配置**: 点击"保存配置"按钮,配置会写入 `.env` 文件 + +4. **重启服务**: 点击"重启服务"按钮,后端会优雅退出(`process.exit(0)`),PM2 会自动重启 + +### 注意事项 + +- 密码字段显示为 `******`,如需修改请输入新密码,留空则保持原密码不变 +- 重启功能需要配合 PM2 等进程管理器使用,否则服务将无法自动恢复 + +--- + +### 3. 新增文章编辑功能 + +**目标**: 提供完整的文章新建和编辑功能。 + +#### 前端新增文件 + +**`src/views/PostEditorView.vue`** +- 新建文章页面 (`/post/new`) +- 编辑文章页面 (`/post/edit/:id`) +- 包含标题、日期、摘要、正文等字段 +- 保存后自动返回文章列表 + +#### 前端修改文件 + +**`src/views/HomeView.vue`** +- 页面头部添加"新建文章"按钮 + +**`src/views/PostDetail.vue`** +- 添加"编辑"和"删除"按钮 +- 支持从文章详情页直接编辑或删除 + +**`src/router/index.js`** +- 添加路由 `/post/new` -> PostEditorView +- 添加路由 `/post/edit/:id` -> PostEditorView + +**`src/i18n/index.js`** +- 添加 `home.newPost` 翻译 +- 添加 `postEditor` 完整翻译(中英文) + +--- + +### 4. 后端定时任务调度器 + +**目标**: 将定时任务调度逻辑从前端移到后端,确保即使没有人打开页面,任务也会按计划执行。 + +#### 新增文件 + +**`server/src/config/cronScheduler.js`** +- `start()` - 启动调度器,每 10 秒检查一次到期任务 +- `stop()` - 停止调度器 +- `checkAndRunTasks()` - 检查并执行到期的任务 +- `executeTask(task)` - 执行单个定时任务 + +#### 后端修改文件 + +**`server/src/index.js`** +- 导入 `cronScheduler` 模块 +- 在服务器启动时调用 `cronScheduler.start()` + +#### 功能说明 + +- 调度器每 10 秒检查一次所有已启用的定时任务 +- 当任务的 `nextRun` 时间已到,立即执行任务 +- 执行后自动计算下一次执行时间并更新数据库 +- 任务在后端运行,不依赖前端页面打开 + +### 注意事项 + +- 定时任务由后端调度,前端 CronView 仍可手动执行和查看任务状态 +- 后端调度需在服务器运行期间持续工作(由 PM2 等进程管理器保持) \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..f2ed78f --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,61 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## 项目命令 + +```sh +npm install # 安装依赖 +npm run dev # 启动开发服务器(热重载) +npm run build # 构建生产版本 +npm run preview # 预览生产构建(端口 5050) +``` + +## 架构 + +- **Vue 3** 单页应用,使用组合式 API(` + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..dbf074f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1393 @@ +{ + "name": "jnote-ui", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "jnote-ui", + "version": "0.0.0", + "dependencies": { + "marked": "^18.0.5", + "pinia": "^2.0.4", + "vue": "^3.2.22", + "vue-router": "^4.0.12" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^1.10.0", + "vite": "^2.6.14" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.25.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz", + "integrity": "sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "1.10.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vitejs/plugin-vue/-/plugin-vue-1.10.2.tgz", + "integrity": "sha512-/QJ0Z9qfhAFtKRY+r57ziY4BSbGUTGsPRMpB/Ron3QPwBZM4OZAZHdTa4a8PafCwU5DTatXG8TMDoP8z+oDqJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "vite": "^2.5.10" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-core/-/compiler-core-3.4.38.tgz", + "integrity": "sha512-8IQOTCWnLFqfHzOGm9+P8OPSEDukgg3Huc92qSG49if/xI2SAwLHQO2qaPQbjCWPBcQoO1WYfXfTACUrWV3c5A==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.24.7", + "@vue/shared": "3.4.38", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-dom/-/compiler-dom-3.4.38.tgz", + "integrity": "sha512-Osc/c7ABsHXTsETLgykcOwIxFktHfGSUDkb05V61rocEfsFDcjDLH/IHJSNJP+/Sv9KeN2Lx1V6McZzlSb9EhQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.4.38", + "@vue/shared": "3.4.38" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-sfc/-/compiler-sfc-3.4.38.tgz", + "integrity": "sha512-s5QfZ+9PzPh3T5H4hsQDJtI8x7zdJaew/dCGgqZ2630XdzaZ3AD8xGZfBqpT8oaD/p2eedd+pL8tD5vvt5ZYJQ==", + "dependencies": { + "@babel/parser": "^7.24.7", + "@vue/compiler-core": "3.4.38", + "@vue/compiler-dom": "3.4.38", + "@vue/compiler-ssr": "3.4.38", + "@vue/shared": "3.4.38", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.10", + "postcss": "^8.4.40", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-ssr/-/compiler-ssr-3.4.38.tgz", + "integrity": "sha512-YXznKFQ8dxYpAz9zLuVvfcXhc31FSPFDcqr0kyujbOwNhlmaNvL2QfIy+RZeJgSn5Fk54CWoEUeW+NVBAogGaw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.4.38", + "@vue/shared": "3.4.38" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/devtools-api/-/devtools-api-6.6.3.tgz", + "integrity": "sha512-0MiMsFma/HqA6g3KLKn+AGpL1kgKhFWszC9U29NfpWK5LE7bjeXxySWJrOJ77hBz+TBrBQ7o4QJqbPbqbs8rJw==" + }, + "node_modules/@vue/reactivity": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/reactivity/-/reactivity-3.4.38.tgz", + "integrity": "sha512-4vl4wMMVniLsSYYeldAKzbk72+D3hUnkw9z8lDeJacTxAkXeDAP1uE9xr2+aKIN0ipOL8EG2GPouVTH6yF7Gnw==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.4.38" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/runtime-core/-/runtime-core-3.4.38.tgz", + "integrity": "sha512-21z3wA99EABtuf+O3IhdxP0iHgkBs1vuoCAsCKLVJPEjpVqvblwBnTj42vzHRlWDCyxu9ptDm7sI2ZMcWrQqlA==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.4.38", + "@vue/shared": "3.4.38" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/runtime-dom/-/runtime-dom-3.4.38.tgz", + "integrity": "sha512-afZzmUreU7vKwKsV17H1NDThEEmdYI+GCAK/KY1U957Ig2NATPVjCROv61R19fjZNzMmiU03n79OMnXyJVN0UA==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.4.38", + "@vue/runtime-core": "3.4.38", + "@vue/shared": "3.4.38", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/server-renderer/-/server-renderer-3.4.38.tgz", + "integrity": "sha512-NggOTr82FbPEkkUvBm4fTGcwUY8UuTsnWC/L2YZBmvaQ4C4Jl/Ao4HHTB+l7WnFCt5M/dN3l0XLuyjzswGYVCA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.4.38", + "@vue/shared": "3.4.38" + }, + "peerDependencies": { + "vue": "3.4.38" + } + }, + "node_modules/@vue/shared": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/shared/-/shared-3.4.38.tgz", + "integrity": "sha512-q0xCiLkuWWQLzVrecPb0RMsNWyxICOjPrcrwxTUEHb1fsnvni4dcuyG7RT/Ie7VPTvnjzIaWzRMUBsrqNj/hhw==", + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild/-/esbuild-0.14.54.tgz", + "integrity": "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/linux-loong64": "0.14.54", + "esbuild-android-64": "0.14.54", + "esbuild-android-arm64": "0.14.54", + "esbuild-darwin-64": "0.14.54", + "esbuild-darwin-arm64": "0.14.54", + "esbuild-freebsd-64": "0.14.54", + "esbuild-freebsd-arm64": "0.14.54", + "esbuild-linux-32": "0.14.54", + "esbuild-linux-64": "0.14.54", + "esbuild-linux-arm": "0.14.54", + "esbuild-linux-arm64": "0.14.54", + "esbuild-linux-mips64le": "0.14.54", + "esbuild-linux-ppc64le": "0.14.54", + "esbuild-linux-riscv64": "0.14.54", + "esbuild-linux-s390x": "0.14.54", + "esbuild-netbsd-64": "0.14.54", + "esbuild-openbsd-64": "0.14.54", + "esbuild-sunos-64": "0.14.54", + "esbuild-windows-32": "0.14.54", + "esbuild-windows-64": "0.14.54", + "esbuild-windows-arm64": "0.14.54" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz", + "integrity": "sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz", + "integrity": "sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz", + "integrity": "sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz", + "integrity": "sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz", + "integrity": "sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz", + "integrity": "sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz", + "integrity": "sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz", + "integrity": "sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz", + "integrity": "sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz", + "integrity": "sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz", + "integrity": "sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz", + "integrity": "sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz", + "integrity": "sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz", + "integrity": "sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz", + "integrity": "sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz", + "integrity": "sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz", + "integrity": "sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz", + "integrity": "sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz", + "integrity": "sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz", + "integrity": "sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": 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", + "resolved": "https://mirrors.cloud.tencent.com/npm/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/magic-string": { + "version": "0.30.11", + "resolved": "https://mirrors.cloud.tencent.com/npm/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/marked": { + "version": "18.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/marked/-/marked-18.0.5.tgz", + "integrity": "sha512-S6GcvALHg6K4ohtu4E7x0a1AqhAjp6cV8KhLSyN9qVapnzJkusVBxZRcIU9AeYsbe6P1hKDusSbEOzGyyuce6w==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "license": "ISC" + }, + "node_modules/pinia": { + "version": "2.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/pinia/-/pinia-2.2.2.tgz", + "integrity": "sha512-ja2XqFWZC36mupU4z1ZzxeTApV7DOw44cV4dhQ9sGwun+N89v/XP7+j7q6TanS1u1tdbK4r+1BUx7heMaIdagA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.3", + "vue-demi": "^0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "@vue/composition-api": "^1.4.0", + "typescript": ">=4.4.4", + "vue": "^2.6.14 || ^3.3.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/postcss": { + "version": "8.4.41", + "resolved": "https://mirrors.cloud.tencent.com/npm/postcss/-/postcss-8.4.41.tgz", + "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", + "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.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rollup": { + "version": "2.77.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/rollup/-/rollup-2.77.3.tgz", + "integrity": "sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/vite": { + "version": "2.9.18", + "resolved": "https://mirrors.cloud.tencent.com/npm/vite/-/vite-2.9.18.tgz", + "integrity": "sha512-sAOqI5wNM9QvSEE70W3UGMdT8cyEn0+PmJMTFvTB8wB0YbYUWw3gUbY62AOyrXosGieF2htmeLATvNxpv/zNyQ==", + "dev": true, + "dependencies": { + "esbuild": "^0.14.27", + "postcss": "^8.4.13", + "resolve": "^1.22.0", + "rollup": ">=2.59.0 <2.78.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": ">=12.2.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "less": "*", + "sass": "*", + "stylus": "*" + }, + "peerDependenciesMeta": { + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/vue/-/vue-3.4.38.tgz", + "integrity": "sha512-f0ZgN+mZ5KFgVv9wz0f4OgVKukoXtS3nwET4c2vLBGQR50aI8G0cqbFtLlX9Yiyg3LFGBitruPHt2PxwTduJEw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.4.38", + "@vue/compiler-sfc": "3.4.38", + "@vue/runtime-dom": "3.4.38", + "@vue/server-renderer": "3.4.38", + "@vue/shared": "3.4.38" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://mirrors.cloud.tencent.com/npm/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/vue-router": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/vue-router/-/vue-router-4.4.3.tgz", + "integrity": "sha512-sv6wmNKx2j3aqJQDMxLFzs/u/mjA9Z5LCgy6BE0f7yFWMjrPLnS/sPNn8ARY/FXw6byV18EFutn5lTO6+UsV5A==", + "dependencies": { + "@vue/devtools-api": "^6.6.3" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + } + }, + "dependencies": { + "@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==" + }, + "@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==" + }, + "@babel/parser": { + "version": "7.25.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "requires": { + "@babel/types": "^7.25.6" + } + }, + "@babel/types": { + "version": "7.25.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "requires": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + } + }, + "@esbuild/linux-loong64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz", + "integrity": "sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==", + "dev": true, + "optional": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "@vitejs/plugin-vue": { + "version": "1.10.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vitejs/plugin-vue/-/plugin-vue-1.10.2.tgz", + "integrity": "sha512-/QJ0Z9qfhAFtKRY+r57ziY4BSbGUTGsPRMpB/Ron3QPwBZM4OZAZHdTa4a8PafCwU5DTatXG8TMDoP8z+oDqJw==", + "dev": true, + "requires": {} + }, + "@vue/compiler-core": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-core/-/compiler-core-3.4.38.tgz", + "integrity": "sha512-8IQOTCWnLFqfHzOGm9+P8OPSEDukgg3Huc92qSG49if/xI2SAwLHQO2qaPQbjCWPBcQoO1WYfXfTACUrWV3c5A==", + "requires": { + "@babel/parser": "^7.24.7", + "@vue/shared": "3.4.38", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "@vue/compiler-dom": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-dom/-/compiler-dom-3.4.38.tgz", + "integrity": "sha512-Osc/c7ABsHXTsETLgykcOwIxFktHfGSUDkb05V61rocEfsFDcjDLH/IHJSNJP+/Sv9KeN2Lx1V6McZzlSb9EhQ==", + "requires": { + "@vue/compiler-core": "3.4.38", + "@vue/shared": "3.4.38" + } + }, + "@vue/compiler-sfc": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-sfc/-/compiler-sfc-3.4.38.tgz", + "integrity": "sha512-s5QfZ+9PzPh3T5H4hsQDJtI8x7zdJaew/dCGgqZ2630XdzaZ3AD8xGZfBqpT8oaD/p2eedd+pL8tD5vvt5ZYJQ==", + "requires": { + "@babel/parser": "^7.24.7", + "@vue/compiler-core": "3.4.38", + "@vue/compiler-dom": "3.4.38", + "@vue/compiler-ssr": "3.4.38", + "@vue/shared": "3.4.38", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.10", + "postcss": "^8.4.40", + "source-map-js": "^1.2.0" + } + }, + "@vue/compiler-ssr": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-ssr/-/compiler-ssr-3.4.38.tgz", + "integrity": "sha512-YXznKFQ8dxYpAz9zLuVvfcXhc31FSPFDcqr0kyujbOwNhlmaNvL2QfIy+RZeJgSn5Fk54CWoEUeW+NVBAogGaw==", + "requires": { + "@vue/compiler-dom": "3.4.38", + "@vue/shared": "3.4.38" + } + }, + "@vue/devtools-api": { + "version": "6.6.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/devtools-api/-/devtools-api-6.6.3.tgz", + "integrity": "sha512-0MiMsFma/HqA6g3KLKn+AGpL1kgKhFWszC9U29NfpWK5LE7bjeXxySWJrOJ77hBz+TBrBQ7o4QJqbPbqbs8rJw==" + }, + "@vue/reactivity": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/reactivity/-/reactivity-3.4.38.tgz", + "integrity": "sha512-4vl4wMMVniLsSYYeldAKzbk72+D3hUnkw9z8lDeJacTxAkXeDAP1uE9xr2+aKIN0ipOL8EG2GPouVTH6yF7Gnw==", + "requires": { + "@vue/shared": "3.4.38" + } + }, + "@vue/runtime-core": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/runtime-core/-/runtime-core-3.4.38.tgz", + "integrity": "sha512-21z3wA99EABtuf+O3IhdxP0iHgkBs1vuoCAsCKLVJPEjpVqvblwBnTj42vzHRlWDCyxu9ptDm7sI2ZMcWrQqlA==", + "requires": { + "@vue/reactivity": "3.4.38", + "@vue/shared": "3.4.38" + } + }, + "@vue/runtime-dom": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/runtime-dom/-/runtime-dom-3.4.38.tgz", + "integrity": "sha512-afZzmUreU7vKwKsV17H1NDThEEmdYI+GCAK/KY1U957Ig2NATPVjCROv61R19fjZNzMmiU03n79OMnXyJVN0UA==", + "requires": { + "@vue/reactivity": "3.4.38", + "@vue/runtime-core": "3.4.38", + "@vue/shared": "3.4.38", + "csstype": "^3.1.3" + } + }, + "@vue/server-renderer": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/server-renderer/-/server-renderer-3.4.38.tgz", + "integrity": "sha512-NggOTr82FbPEkkUvBm4fTGcwUY8UuTsnWC/L2YZBmvaQ4C4Jl/Ao4HHTB+l7WnFCt5M/dN3l0XLuyjzswGYVCA==", + "requires": { + "@vue/compiler-ssr": "3.4.38", + "@vue/shared": "3.4.38" + } + }, + "@vue/shared": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/shared/-/shared-3.4.38.tgz", + "integrity": "sha512-q0xCiLkuWWQLzVrecPb0RMsNWyxICOjPrcrwxTUEHb1fsnvni4dcuyG7RT/Ie7VPTvnjzIaWzRMUBsrqNj/hhw==" + }, + "csstype": { + "version": "3.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "entities": { + "version": "4.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" + }, + "esbuild": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild/-/esbuild-0.14.54.tgz", + "integrity": "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==", + "dev": true, + "requires": { + "@esbuild/linux-loong64": "0.14.54", + "esbuild-android-64": "0.14.54", + "esbuild-android-arm64": "0.14.54", + "esbuild-darwin-64": "0.14.54", + "esbuild-darwin-arm64": "0.14.54", + "esbuild-freebsd-64": "0.14.54", + "esbuild-freebsd-arm64": "0.14.54", + "esbuild-linux-32": "0.14.54", + "esbuild-linux-64": "0.14.54", + "esbuild-linux-arm": "0.14.54", + "esbuild-linux-arm64": "0.14.54", + "esbuild-linux-mips64le": "0.14.54", + "esbuild-linux-ppc64le": "0.14.54", + "esbuild-linux-riscv64": "0.14.54", + "esbuild-linux-s390x": "0.14.54", + "esbuild-netbsd-64": "0.14.54", + "esbuild-openbsd-64": "0.14.54", + "esbuild-sunos-64": "0.14.54", + "esbuild-windows-32": "0.14.54", + "esbuild-windows-64": "0.14.54", + "esbuild-windows-arm64": "0.14.54" + } + }, + "esbuild-android-64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz", + "integrity": "sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==", + "dev": true, + "optional": true + }, + "esbuild-android-arm64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz", + "integrity": "sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz", + "integrity": "sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz", + "integrity": "sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz", + "integrity": "sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz", + "integrity": "sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz", + "integrity": "sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz", + "integrity": "sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz", + "integrity": "sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz", + "integrity": "sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz", + "integrity": "sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz", + "integrity": "sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz", + "integrity": "sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==", + "dev": true, + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz", + "integrity": "sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz", + "integrity": "sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz", + "integrity": "sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz", + "integrity": "sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==", + "dev": true, + "optional": true + }, + "esbuild-windows-32": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz", + "integrity": "sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz", + "integrity": "sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.14.54", + "resolved": "https://mirrors.cloud.tencent.com/npm/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz", + "integrity": "sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==", + "dev": true, + "optional": true + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + } + }, + "is-core-module": { + "version": "2.15.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "requires": { + "hasown": "^2.0.2" + } + }, + "magic-string": { + "version": "0.30.11", + "resolved": "https://mirrors.cloud.tencent.com/npm/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "requires": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "marked": { + "version": "18.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/marked/-/marked-18.0.5.tgz", + "integrity": "sha512-S6GcvALHg6K4ohtu4E7x0a1AqhAjp6cV8KhLSyN9qVapnzJkusVBxZRcIU9AeYsbe6P1hKDusSbEOzGyyuce6w==" + }, + "nanoid": { + "version": "3.3.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "picocolors": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + }, + "pinia": { + "version": "2.2.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/pinia/-/pinia-2.2.2.tgz", + "integrity": "sha512-ja2XqFWZC36mupU4z1ZzxeTApV7DOw44cV4dhQ9sGwun+N89v/XP7+j7q6TanS1u1tdbK4r+1BUx7heMaIdagA==", + "requires": { + "@vue/devtools-api": "^6.6.3", + "vue-demi": "^0.14.10" + } + }, + "postcss": { + "version": "8.4.41", + "resolved": "https://mirrors.cloud.tencent.com/npm/postcss/-/postcss-8.4.41.tgz", + "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", + "requires": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + } + }, + "resolve": { + "version": "1.22.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "rollup": { + "version": "2.77.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/rollup/-/rollup-2.77.3.tgz", + "integrity": "sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "source-map-js": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==" + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" + }, + "vite": { + "version": "2.9.18", + "resolved": "https://mirrors.cloud.tencent.com/npm/vite/-/vite-2.9.18.tgz", + "integrity": "sha512-sAOqI5wNM9QvSEE70W3UGMdT8cyEn0+PmJMTFvTB8wB0YbYUWw3gUbY62AOyrXosGieF2htmeLATvNxpv/zNyQ==", + "dev": true, + "requires": { + "esbuild": "^0.14.27", + "fsevents": "~2.3.2", + "postcss": "^8.4.13", + "resolve": "^1.22.0", + "rollup": ">=2.59.0 <2.78.0" + } + }, + "vue": { + "version": "3.4.38", + "resolved": "https://mirrors.cloud.tencent.com/npm/vue/-/vue-3.4.38.tgz", + "integrity": "sha512-f0ZgN+mZ5KFgVv9wz0f4OgVKukoXtS3nwET4c2vLBGQR50aI8G0cqbFtLlX9Yiyg3LFGBitruPHt2PxwTduJEw==", + "requires": { + "@vue/compiler-dom": "3.4.38", + "@vue/compiler-sfc": "3.4.38", + "@vue/runtime-dom": "3.4.38", + "@vue/server-renderer": "3.4.38", + "@vue/shared": "3.4.38" + } + }, + "vue-demi": { + "version": "0.14.10", + "resolved": "https://mirrors.cloud.tencent.com/npm/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "requires": {} + }, + "vue-router": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/vue-router/-/vue-router-4.4.3.tgz", + "integrity": "sha512-sv6wmNKx2j3aqJQDMxLFzs/u/mjA9Z5LCgy6BE0f7yFWMjrPLnS/sPNn8ARY/FXw6byV18EFutn5lTO6+UsV5A==", + "requires": { + "@vue/devtools-api": "^6.6.3" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..a9afaca --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "jnote-ui", + "version": "0.0.0", + "scripts": { + "dev": "vite", + "build": "vite build", + "build:prod": "vite build --mode production", + "preview": "vite preview --port 5050" + }, + "dependencies": { + "marked": "^18.0.5", + "pinia": "^2.0.4", + "vue": "^3.2.22", + "vue-router": "^4.0.12" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^1.10.0", + "vite": "^2.6.14" + } +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..df36fcf Binary files /dev/null and b/public/favicon.ico differ diff --git a/server/.env b/server/.env new file mode 100644 index 0000000..06959c2 --- /dev/null +++ b/server/.env @@ -0,0 +1,17 @@ +# 数据库配置 +DB_HOST=43.156.91.115 +DB_PORT=53306 +DB_USER=root +# DB_PASSWORD=mysql_sX4mrh +DB_PASSWORD=mariadb_hJbME5 +DB_NAME=jnote + +# RUSTFS 对象存储配置 +RUSTFS_ENDPOINT=http://43.156.91.115:9001 +RUSTFS_REGION=us-east-1 +RUSTFS_BUCKET=setting +RUSTFS_ACCESS_KEY=rustfsadmin +RUSTFS_SECRET_KEY=rustfsadmin + +# 服务器配置 +PORT=4501 diff --git a/server/README.md b/server/README.md new file mode 100644 index 0000000..9361cce --- /dev/null +++ b/server/README.md @@ -0,0 +1,76 @@ +# Jnote Server + +博客后端 API 服务 + +## 安装 + +```bash +npm install +``` + +## 配置 + +编辑 `.env` 文件,填入数据库连接信息: + +``` +DB_HOST=localhost +DB_PORT=3306 +DB_USER=root +DB_PASSWORD=your_password +DB_NAME=jnote +PORT=3000 +``` + +如果不配置数据库,将使用内存存储作为后备方案。 + +## 启动 + +```bash +# 开发模式(热重载) +npm run dev + +# 生产模式 +npm start +``` + +## API 端点 + +### 文章 + +| 端点 | 方法 | 说明 | +|------|------|------| +| `/api/posts` | GET | 获取所有文章 | +| `/api/posts/:id` | GET | 获取单篇文章 | +| `/api/posts` | POST | 创建文章 | +| `/api/posts/:id` | PUT | 更新文章 | +| `/api/posts/:id` | DELETE | 删除文章 | + +### 关于 + +| 端点 | 方法 | 说明 | +|------|------|------| +| `/api/about` | GET | 获取关于内容 | +| `/api/about` | PUT | 更新关于内容 | + +### 设置 + +| 端点 | 方法 | 说明 | +|------|------|------| +| `/api/settings` | GET | 获取设置 | +| `/api/settings` | PUT | 更新设置 | + +### 定时任务 + +| 端点 | 方法 | 说明 | +|------|------|------| +| `/api/cron-tasks` | GET | 获取所有任务 | +| `/api/cron-tasks` | POST | 创建任务 | +| `/api/cron-tasks/:id` | PUT | 更新任务 | +| `/api/cron-tasks/:id` | DELETE | 删除任务 | +| `/api/cron-tasks/:id/run` | POST | 立即执行任务 | + +### 健康检查 + +| 端点 | 方法 | 说明 | +|------|------|------| +| `/api/health` | GET | 服务健康状态 | \ No newline at end of file diff --git a/server/build.js b/server/build.js new file mode 100644 index 0000000..95f838a --- /dev/null +++ b/server/build.js @@ -0,0 +1,89 @@ +/** + * JNote 后端打包脚本 + * 支持 Node.js 16.x + */ + +const { execSync } = require('child_process'); +const fs = require('fs'); +const path = require('path'); + +const serverDir = __dirname; + +// Node 16.x -> pkg 5.8.1 +const PKG_VERSION = '5.8.1'; +const TARGET_NODE_VERSION = 'node16'; + +function log(msg) { + console.log(`[Build] ${msg}`); +} + +function run(cmd) { + log(`执行: ${cmd}`); + execSync(cmd, { cwd: serverDir, stdio: 'inherit' }); +} + +function checkNodeVersion() { + const version = execSync('node --version', { encoding: 'utf8' }).trim(); + const match = version.match(/^v(\d+)\./); + if (match) { + return parseInt(match[1]); + } + return null; +} + +function main() { + console.log('========================================='); + console.log(' JNote 后端打包工具'); + console.log(` 当前平台: ${isWindows ? 'Windows' : 'Linux'}`); + console.log('========================================='); + + // 检查 Node.js 环境 + const nodeMajor = checkNodeVersion(); + if (!nodeMajor) { + console.error('❌ 错误: 未找到 Node.js'); + process.exit(1); + } + log(`✓ Node.js 版本: v${nodeMajor}.x`); + + // 安装依赖 + console.log(''); + log('📦 安装依赖...'); + run('npm install'); + + // 安装 pkg + try { + execSync('pkg --version', { encoding: 'utf8', stdio: 'ignore' }); + log('✓ pkg 已安装'); + } catch { + console.log(''); + log(`📦 安装 pkg ${PKG_VERSION}...`); + run(`npm install -g pkg@${PKG_VERSION}`); + } + + // 创建 dist 目录 + const distDir = path.join(serverDir, 'dist'); + if (!fs.existsSync(distDir)) { + fs.mkdirSync(distDir, { recursive: true }); + } + + // 打包 Linux 版本 + console.log(''); + log(`🔨 打包 Linux 版本 (${TARGET_NODE_VERSION}-linux-x64)...`); + run(`pkg src/index.js --targets ${TARGET_NODE_VERSION}-linux-x64 --output dist/jnote-api`); + + console.log(''); + console.log('========================================='); + console.log(' 打包完成!'); + console.log('========================================='); + console.log(''); + console.log('输出文件:'); + console.log(' - dist/jnote-api (Linux 可执行文件)'); + console.log(''); + console.log('下一步:'); + console.log(' 1. 将 dist/ 目录下的文件上传到服务器'); + console.log(' 2. 修改 .env 配置数据库等信息'); + console.log(' 3. 运行: chmod +x jnote-api && ./jnote-api'); + console.log(''); +} + +main(); \ No newline at end of file diff --git a/server/package-lock.json b/server/package-lock.json new file mode 100644 index 0000000..4c14bb0 --- /dev/null +++ b/server/package-lock.json @@ -0,0 +1,5732 @@ +{ + "name": "jnote-server", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "jnote-server", + "version": "1.0.0", + "dependencies": { + "@aws-sdk/client-s3": "^3.1064.0", + "@aws-sdk/s3-request-presigner": "^3.1064.0", + "cors": "^2.8.5", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "mysql2": "^3.22.5" + }, + "devDependencies": { + "nodemon": "^3.0.2", + "pkg": "5.8.1" + } + }, + "node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/crc32c": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", + "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha1-browser": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", + "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "dependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/checksums": { + "version": "3.1000.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/checksums/-/checksums-3.1000.3.tgz", + "integrity": "sha512-vkPd3NMJf6Gw4QjBBdiUdu2uo4P0HfHrx5+1hqjDYZhZAF4HWkMHXoQtxHQmDi/LyysUgTU5uNhcZLCkpF9LKg==", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-crypto/util": "5.2.0", + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/client-s3": { + "version": "3.1064.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/client-s3/-/client-s3-3.1064.0.tgz", + "integrity": "sha512-6OQhE4Qpt94oTw7ruBHE2E6/PS57alsCSdemMf4c3gBSUM0emoXRRykYffFSL56oluL49AZh/DLWRnQafynbLg==", + "dependencies": { + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/credential-provider-node": "^3.972.53", + "@aws-sdk/middleware-flexible-checksums": "^3.974.28", + "@aws-sdk/middleware-sdk-s3": "^3.972.49", + "@aws-sdk/signature-v4-multi-region": "^3.996.33", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/fetch-http-handler": "^5.4.6", + "@smithy/node-http-handler": "^4.7.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.974.19", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/core/-/core-3.974.19.tgz", + "integrity": "sha512-SMNfLCU/41xxfFaC5Slwy8V/f1FRhakvyeeMeDeIxqNF0DzhDlXsXnJDELJYke1EtnJbfzfilW7tvulGfxMY6A==", + "dependencies": { + "@aws-sdk/types": "^3.973.12", + "@aws-sdk/xml-builder": "^3.972.29", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/core": "^3.24.6", + "@smithy/signature-v4": "^5.4.6", + "@smithy/types": "^4.14.3", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.972.45", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.45.tgz", + "integrity": "sha512-ZPsnLyrpDRmojKrBbJykASyLLVFkjyD+fWATeSuYgaqablijGOzxPxEKyrwUvNg+bgSQ7PkW2FTu65Xco19Gag==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.972.47", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.47.tgz", + "integrity": "sha512-1XdgHDIPbARHuzZXM7ouzIbSUZFU9dTi9k+ryMhiZU4QCam4dvwOyUEFjEHNxAZehCYUIOmsSUZ2un6BIgUkWg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/fetch-http-handler": "^5.4.6", + "@smithy/node-http-handler": "^4.7.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.972.51", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.51.tgz", + "integrity": "sha512-f8sRTVyM+9BbzQKPlUP9dVVpgNEu65jFckNAAGzRfCrlaSi5AWUbCKEHIMcIYokv8pWblSKEqHkqKYZtwINnhw==", + "dependencies": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/credential-provider-env": "^3.972.45", + "@aws-sdk/credential-provider-http": "^3.972.47", + "@aws-sdk/credential-provider-login": "^3.972.50", + "@aws-sdk/credential-provider-process": "^3.972.45", + "@aws-sdk/credential-provider-sso": "^3.972.50", + "@aws-sdk/credential-provider-web-identity": "^3.972.50", + "@aws-sdk/nested-clients": "^3.997.18", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/credential-provider-imds": "^4.3.7", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login": { + "version": "3.972.50", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.50.tgz", + "integrity": "sha512-NHHsKoMhw6UylSU0XDnDc87+IQW8tRBTIe6vnOX12GSIlBDtoce6bSzONleIglCyu8d3H9bmTSfk+sIN5yh3WA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/nested-clients": "^3.997.18", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.972.53", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.53.tgz", + "integrity": "sha512-z/JJ8Qvf2GiTn4bw+x8k7wQjxmPpNsiwZ7ls/h1cZHikrSpS0+65lB+lafnXZlxv1lqH4k6rQwh+2UsycC662g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "^3.972.45", + "@aws-sdk/credential-provider-http": "^3.972.47", + "@aws-sdk/credential-provider-ini": "^3.972.51", + "@aws-sdk/credential-provider-process": "^3.972.45", + "@aws-sdk/credential-provider-sso": "^3.972.50", + "@aws-sdk/credential-provider-web-identity": "^3.972.50", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/credential-provider-imds": "^4.3.7", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.972.45", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.45.tgz", + "integrity": "sha512-QMJXjTGLmHE4Ie03T5H4hHOLfcvMc9DaODO6b5dgte3S8ECf5bBuHUJW4cQREcYZyRkOU8iymqtiBxqF4icxZg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.972.50", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.50.tgz", + "integrity": "sha512-pQ9ww4G53gwHlon1NMz25JhaBo13E9Jv+VVgjh39C/yzvby+xhSnEOb+VDYShKNCh1TbttMF/5CFCHkZrIqOcA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/nested-clients": "^3.997.18", + "@aws-sdk/token-providers": "3.1064.0", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.972.50", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.50.tgz", + "integrity": "sha512-9DbaPaT2aMbz18wtSpq9HVBErjBQwxykqTFgG6n8Bn05GN68mITz+G1869ekYx0mVT/BDjETj5czz/3cPgLwxA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/nested-clients": "^3.997.18", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.974.28", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.974.28.tgz", + "integrity": "sha512-XkHArJreL8hnpKrBTlnwrIcynZT4kDiAF6BF/z7AVxV7VUvojrjL2RzeK8QLVNyfzkEJGIYBKoufOIOSSpd6nQ==", + "dependencies": { + "@aws-sdk/checksums": "^3.1000.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.972.49", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.49.tgz", + "integrity": "sha512-9CQoJfMZMqGJVBqFO/C8Gwke6WM7CLskQBiAjGU5LyXsVtqhymAATfqFnIa87Dw23ssfgGzqBHpSSwSchldFXw==", + "dependencies": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/signature-v4-multi-region": "^3.996.33", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients": { + "version": "3.997.18", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/nested-clients/-/nested-clients-3.997.18.tgz", + "integrity": "sha512-xBWrodBvW5SHCZV11UZUJG0pSHkLCEREIBoNbff1C1sacOUCmxJnTCPE80sCGLCtqgXg98I2MQJe2z28tcZSsw==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/signature-v4-multi-region": "^3.996.33", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/fetch-http-handler": "^5.4.6", + "@smithy/node-http-handler": "^4.7.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner": { + "version": "3.1064.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.1064.0.tgz", + "integrity": "sha512-BYha6t2emy50ld7wvtLkrhMsibaGNlgg1TzMXrbkof3QP+9usjikabdOI429uGyhUzklC4amPnxWLzWxP+AjIw==", + "dependencies": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/signature-v4-multi-region": "^3.996.33", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.996.33", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.33.tgz", + "integrity": "sha512-Hn0RThJEbyOZWV2PV9Z4YD3nitGPxybmyU17dSe9b61WOBcKnqS0WTtM3c1zyZq9WnGiyrfi/i+UBPUk7cM8Ug==", + "dependencies": { + "@aws-sdk/types": "^3.973.12", + "@smithy/signature-v4": "^5.4.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.1064.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/token-providers/-/token-providers-3.1064.0.tgz", + "integrity": "sha512-sjI+iA4JtgeckBgKwPQF7KzWillRoNDmtpiM0TRa0syiAKFHKUSf84kPXSO3+gA7aMMSxrcxzOM2oPSecaJvEA==", + "dependencies": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/nested-clients": "^3.997.18", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.973.12", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/types/-/types-3.973.12.tgz", + "integrity": "sha512-43ajd1NF0RMgX5k0hxCNUyEdrtFUsb2aHT2QvpktSC/2Eyb2Jr/JPVqdp0XIoaHWikZJq5tNWSLO6kB5q2eMCA==", + "dependencies": { + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.965.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/util-locate-window/-/util-locate-window-3.965.7.tgz", + "integrity": "sha512-M0D6oIpohdNHjc7udzTHEQyot0+0iuA36jc2I9Hps+f/GtKi2HO/pyijQnCnNcwZqLB5+rtn81z3eZK/GyjAmA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.972.29", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/xml-builder/-/xml-builder-3.972.29.tgz", + "integrity": "sha512-fk0niuGFxfi8yIJuMVM4mhwObkiQSuwZFj3tAPrLVx64Pk3BkrEIpqjzHKY4hKoEBUD6Jg/S74Zj9jy+5F3DnQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.14.3", + "fast-xml-parser": "5.7.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws/lambda-invoke-store": { + "version": "0.2.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.4.tgz", + "integrity": "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.18.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/generator/-/generator-7.18.2.tgz", + "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.2", + "@jridgewell/gen-mapping": "^0.3.0", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.18.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/parser/-/parser-7.18.4.tgz", + "integrity": "sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.19.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/types/-/types-7.19.0.tgz", + "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodable/entities": { + "version": "2.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/@nodable/entities/-/entities-2.1.1.tgz", + "integrity": "sha512-Pig3HxDIoMgjdEH8OCf/dkcTmLFjJRjWuq8jSnklu284/TKOPibSRERmOykiwmyXTtv61mP+44f3GMx0tLAyjg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nodable" + } + ] + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@smithy/core": { + "version": "3.24.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@smithy/core/-/core-3.24.6.tgz", + "integrity": "sha512-wBXDRup6UU97VKyaiRo8AssnfStPtG0oAAfpq/bC0a1YYau8pM86YB4kM6ccoVi1mS8l/UHbn9oDM+7uozr/ug==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "4.3.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/@smithy/credential-provider-imds/-/credential-provider-imds-4.3.8.tgz", + "integrity": "sha512-5cAM+KZC02sTqDt6NaLXyu50M/GNMd1eTzDVR8Lb0BBsVtu7RWHo47VPPEEv1vt3Yub6uzr+M5FHC+GtoT0USg==", + "dependencies": { + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "5.4.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@smithy/fetch-http-handler/-/fetch-http-handler-5.4.6.tgz", + "integrity": "sha512-FEwEYJ1jlBKdhe9TPzfghEi1bP55ZeEImlDkEa62bBBYzUcnB6RUCyuiS2mqKt6ZVjUbBgcNhzfIctH+Hevx9g==", + "dependencies": { + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "4.7.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/@smithy/node-http-handler/-/node-http-handler-4.7.7.tgz", + "integrity": "sha512-ZAFvHXrEk6K180EVhmZVg8GU5pUH5BSFqRs27JW3j1qEFx9YyYwWFx17x/MHcjALYimGAji7qEOlF1++be+G5A==", + "dependencies": { + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "5.4.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@smithy/signature-v4/-/signature-v4-5.4.6.tgz", + "integrity": "sha512-Ojg4B6oIDlIr1R86xCDJt1zJWnYa0VINmqdjfe9qxWjdRivHalZ3iSlQgVqYbW0MdpFOC5XfHEWsnbmdnpIILQ==", + "dependencies": { + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "4.14.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/@smithy/types/-/types-4.14.3.tgz", + "integrity": "sha512-YupL0ZWmFtJexUN2cHzkvvF/b9pKrtAIfT1o7/oY/Ppu8IYeZ+lDPM5vZdQJaSeA132dJCqojjGC9NhXeF71VQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@types/node": { + "version": "25.9.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/node/-/node-25.9.2.tgz", + "integrity": "sha512-G05zqtJhcDLb8uslf5EjCxXg9G1KQxiV8OS0R26IC//Eoyitzqe8z37I7cqvnZlrlSfgocQRfSn/AHBZJJFyGw==", + "peer": true, + "dependencies": { + "undici-types": ">=7.24.0 <7.24.7" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "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/anymatch": { + "version": "3.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/aws-ssl-profiles": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", + "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "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/binary-extensions": { + "version": "2.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/body-parser": { + "version": "1.20.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bowser": { + "version": "2.14.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/bowser/-/bowser-2.14.1.tgz", + "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "dev": true, + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "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": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "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", + "resolved": "https://mirrors.cloud.tencent.com/npm/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "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/chalk": { + "version": "4.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "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/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true, + "license": "ISC" + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "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", + "resolved": "https://mirrors.cloud.tencent.com/npm/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/express": { + "version": "4.22.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.5", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.15.1", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "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-xml-builder": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz", + "integrity": "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "dependencies": { + "path-expression-matcher": "^1.5.0", + "xml-naming": "^0.1.0" + } + }, + "node_modules/fast-xml-parser": { + "version": "5.7.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/fast-xml-parser/-/fast-xml-parser-5.7.3.tgz", + "integrity": "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "dependencies": { + "@nodable/entities": "^2.1.0", + "fast-xml-builder": "^1.1.7", + "path-expression-matcher": "^1.5.0", + "strnum": "^2.2.3" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/from2/-/from2-2.3.0.tgz", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": 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", + "resolved": "https://mirrors.cloud.tencent.com/npm/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "license": "MIT", + "dependencies": { + "is-property": "^1.0.2" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "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", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "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", + "resolved": "https://mirrors.cloud.tencent.com/npm/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://mirrors.cloud.tencent.com/npm/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/has/-/has-1.0.4.tgz", + "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "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/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://mirrors.cloud.tencent.com/npm/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "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": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, + "node_modules/into-stream": { + "version": "6.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/into-stream/-/into-stream-6.0.0.tgz", + "integrity": "sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA==", + "dev": true, + "dependencies": { + "from2": "^2.3.0", + "p-is-promise": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.9.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "license": "MIT" + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==" + }, + "node_modules/lru.min": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/lru.min/-/lru.min-1.1.4.tgz", + "integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==", + "license": "MIT", + "engines": { + "bun": ">=1.0.0", + "deno": ">=1.30.0", + "node": ">=8.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wellwelwel" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://mirrors.cloud.tencent.com/npm/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/multistream": { + "version": "4.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/multistream/-/multistream-4.1.0.tgz", + "integrity": "sha512-J1XDiAmmNpRCBfIWJv+n0ymC4ABcf/Pl+5YvC5B/D2f/2+8PtHvCNxMPKiQcZyi922Hq69J2YOpb1pTywfifyw==", + "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" + } + ], + "dependencies": { + "once": "^1.4.0", + "readable-stream": "^3.6.0" + } + }, + "node_modules/multistream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/mysql2": { + "version": "3.22.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/mysql2/-/mysql2-3.22.5.tgz", + "integrity": "sha512-95uZ2TrPWAZdwpB3vvvDbmEMcNG8yIeNCyu6GUcr/QnWEE/wXm7+mhOCsdQfWQDTV7qYT/PDUZ4U4UPP4AsXqQ==", + "license": "MIT", + "dependencies": { + "aws-ssl-profiles": "^1.1.2", + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.7.2", + "long": "^5.3.2", + "lru.min": "^1.1.4", + "named-placeholders": "^1.1.6", + "sql-escaper": "^1.3.3" + }, + "engines": { + "node": ">= 8.0" + }, + "peerDependencies": { + "@types/node": ">= 8" + } + }, + "node_modules/mysql2/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "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/named-placeholders": { + "version": "1.1.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/named-placeholders/-/named-placeholders-1.1.6.tgz", + "integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==", + "dependencies": { + "lru.min": "^1.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-abi": { + "version": "3.92.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/node-abi/-/node-abi-3.92.0.tgz", + "integrity": "sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/nodemon": { + "version": "3.1.14", + "resolved": "https://mirrors.cloud.tencent.com/npm/nodemon/-/nodemon-3.1.14.tgz", + "integrity": "sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^10.2.1", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-is-promise": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/p-is-promise/-/p-is-promise-3.0.0.tgz", + "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-expression-matcher": { + "version": "1.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz", + "integrity": "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "0.1.13", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg": { + "version": "5.8.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/pkg/-/pkg-5.8.1.tgz", + "integrity": "sha512-CjBWtFStCfIiT4Bde9QpJy0KeH19jCfwZRJqHFDFXfhUklCx8JoFmMj3wgnEYIwGmZVNkhsStPHEOnrtrQhEXA==", + "dev": true, + "dependencies": { + "@babel/generator": "7.18.2", + "@babel/parser": "7.18.4", + "@babel/types": "7.19.0", + "chalk": "^4.1.2", + "fs-extra": "^9.1.0", + "globby": "^11.1.0", + "into-stream": "^6.0.0", + "is-core-module": "2.9.0", + "minimist": "^1.2.6", + "multistream": "^4.1.0", + "pkg-fetch": "3.4.2", + "prebuild-install": "7.1.1", + "resolve": "^1.22.0", + "stream-meter": "^1.0.4" + }, + "bin": { + "pkg": "lib-es5/bin.js" + }, + "peerDependencies": { + "node-notifier": ">=9.0.1" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/pkg-fetch": { + "version": "3.4.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/pkg-fetch/-/pkg-fetch-3.4.2.tgz", + "integrity": "sha512-0+uijmzYcnhC0hStDjm/cl2VYdrmVVBpe7Q8k9YBojxmR5tG8mvR9/nooQq3QSXiQqORDVOTY3XqMEqJVIzkHA==", + "dev": true, + "dependencies": { + "chalk": "^4.1.2", + "fs-extra": "^9.1.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.6", + "progress": "^2.0.3", + "semver": "^7.3.5", + "tar-fs": "^2.1.1", + "yargs": "^16.2.0" + }, + "bin": { + "pkg-fetch": "lib-es5/bin.js" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/prebuild-install/-/prebuild-install-7.1.1.tgz", + "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "dev": true, + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true, + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/qs": { + "version": "6.15.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "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.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://mirrors.cloud.tencent.com/npm/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve/node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "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/safe-buffer": { + "version": "5.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "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/safer-buffer": { + "version": "2.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.8.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-7.8.3.tgz", + "integrity": "sha512-wnilbGyMxzbY7dNOl7jpKbLSjcfeweJWU5j4+u5qW+6/wuGD9KzIGOyZnQVSBM9E7DtWaaH3CyHkppYrKYoxwg==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "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", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "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", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "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", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "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/simple-concat": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "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/simple-get": { + "version": "4.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "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": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sql-escaper": { + "version": "1.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/sql-escaper/-/sql-escaper-1.3.3.tgz", + "integrity": "sha512-BsTCV265VpTp8tm1wyIm1xqQCS+Q9NHx2Sr+WcnUrgLrQ6yiDIvHYJV5gHxsj1lMBy2zm5twLaZao8Jd+S8JJw==", + "engines": { + "bun": ">=1.0.0", + "deno": ">=2.0.0", + "node": ">=12.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/mysqljs/sql-escaper?sponsor=1" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stream-meter": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/stream-meter/-/stream-meter-1.0.4.tgz", + "integrity": "sha512-4sOEtrbgFotXwnEuzzsQBYEV1elAeFSO8rSGeTwabuX1RRn/kEq9JVH7I0MRBhKVRR0sJkr0M0QCH7yOLf9fhQ==", + "dev": true, + "dependencies": { + "readable-stream": "^2.1.4" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "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/strip-ansi": { + "version": "6.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strnum": { + "version": "2.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/strnum/-/strnum-2.3.0.tgz", + "integrity": "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ] + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://mirrors.cloud.tencent.com/npm/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/undici-types": { + "version": "7.24.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "license": "MIT", + "peer": true + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "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/wrappy": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/xml-naming": { + "version": "0.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/xml-naming/-/xml-naming-0.1.0.tgz", + "integrity": "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + } + }, + "dependencies": { + "@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "requires": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "@aws-crypto/crc32c": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", + "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", + "requires": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "@aws-crypto/sha1-browser": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", + "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", + "requires": { + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "requires": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "requires": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "requires": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/checksums": { + "version": "3.1000.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/checksums/-/checksums-3.1000.3.tgz", + "integrity": "sha512-vkPd3NMJf6Gw4QjBBdiUdu2uo4P0HfHrx5+1hqjDYZhZAF4HWkMHXoQtxHQmDi/LyysUgTU5uNhcZLCkpF9LKg==", + "requires": { + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-crypto/util": "5.2.0", + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/client-s3": { + "version": "3.1064.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/client-s3/-/client-s3-3.1064.0.tgz", + "integrity": "sha512-6OQhE4Qpt94oTw7ruBHE2E6/PS57alsCSdemMf4c3gBSUM0emoXRRykYffFSL56oluL49AZh/DLWRnQafynbLg==", + "requires": { + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/credential-provider-node": "^3.972.53", + "@aws-sdk/middleware-flexible-checksums": "^3.974.28", + "@aws-sdk/middleware-sdk-s3": "^3.972.49", + "@aws-sdk/signature-v4-multi-region": "^3.996.33", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/fetch-http-handler": "^5.4.6", + "@smithy/node-http-handler": "^4.7.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/core": { + "version": "3.974.19", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/core/-/core-3.974.19.tgz", + "integrity": "sha512-SMNfLCU/41xxfFaC5Slwy8V/f1FRhakvyeeMeDeIxqNF0DzhDlXsXnJDELJYke1EtnJbfzfilW7tvulGfxMY6A==", + "requires": { + "@aws-sdk/types": "^3.973.12", + "@aws-sdk/xml-builder": "^3.972.29", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/core": "^3.24.6", + "@smithy/signature-v4": "^5.4.6", + "@smithy/types": "^4.14.3", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-env": { + "version": "3.972.45", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.45.tgz", + "integrity": "sha512-ZPsnLyrpDRmojKrBbJykASyLLVFkjyD+fWATeSuYgaqablijGOzxPxEKyrwUvNg+bgSQ7PkW2FTu65Xco19Gag==", + "requires": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-http": { + "version": "3.972.47", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.47.tgz", + "integrity": "sha512-1XdgHDIPbARHuzZXM7ouzIbSUZFU9dTi9k+ryMhiZU4QCam4dvwOyUEFjEHNxAZehCYUIOmsSUZ2un6BIgUkWg==", + "requires": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/fetch-http-handler": "^5.4.6", + "@smithy/node-http-handler": "^4.7.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-ini": { + "version": "3.972.51", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.51.tgz", + "integrity": "sha512-f8sRTVyM+9BbzQKPlUP9dVVpgNEu65jFckNAAGzRfCrlaSi5AWUbCKEHIMcIYokv8pWblSKEqHkqKYZtwINnhw==", + "requires": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/credential-provider-env": "^3.972.45", + "@aws-sdk/credential-provider-http": "^3.972.47", + "@aws-sdk/credential-provider-login": "^3.972.50", + "@aws-sdk/credential-provider-process": "^3.972.45", + "@aws-sdk/credential-provider-sso": "^3.972.50", + "@aws-sdk/credential-provider-web-identity": "^3.972.50", + "@aws-sdk/nested-clients": "^3.997.18", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/credential-provider-imds": "^4.3.7", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-login": { + "version": "3.972.50", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.50.tgz", + "integrity": "sha512-NHHsKoMhw6UylSU0XDnDc87+IQW8tRBTIe6vnOX12GSIlBDtoce6bSzONleIglCyu8d3H9bmTSfk+sIN5yh3WA==", + "requires": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/nested-clients": "^3.997.18", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-node": { + "version": "3.972.53", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.53.tgz", + "integrity": "sha512-z/JJ8Qvf2GiTn4bw+x8k7wQjxmPpNsiwZ7ls/h1cZHikrSpS0+65lB+lafnXZlxv1lqH4k6rQwh+2UsycC662g==", + "requires": { + "@aws-sdk/credential-provider-env": "^3.972.45", + "@aws-sdk/credential-provider-http": "^3.972.47", + "@aws-sdk/credential-provider-ini": "^3.972.51", + "@aws-sdk/credential-provider-process": "^3.972.45", + "@aws-sdk/credential-provider-sso": "^3.972.50", + "@aws-sdk/credential-provider-web-identity": "^3.972.50", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/credential-provider-imds": "^4.3.7", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-process": { + "version": "3.972.45", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.45.tgz", + "integrity": "sha512-QMJXjTGLmHE4Ie03T5H4hHOLfcvMc9DaODO6b5dgte3S8ECf5bBuHUJW4cQREcYZyRkOU8iymqtiBxqF4icxZg==", + "requires": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-sso": { + "version": "3.972.50", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.50.tgz", + "integrity": "sha512-pQ9ww4G53gwHlon1NMz25JhaBo13E9Jv+VVgjh39C/yzvby+xhSnEOb+VDYShKNCh1TbttMF/5CFCHkZrIqOcA==", + "requires": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/nested-clients": "^3.997.18", + "@aws-sdk/token-providers": "3.1064.0", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-web-identity": { + "version": "3.972.50", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.50.tgz", + "integrity": "sha512-9DbaPaT2aMbz18wtSpq9HVBErjBQwxykqTFgG6n8Bn05GN68mITz+G1869ekYx0mVT/BDjETj5czz/3cPgLwxA==", + "requires": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/nested-clients": "^3.997.18", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-flexible-checksums": { + "version": "3.974.28", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.974.28.tgz", + "integrity": "sha512-XkHArJreL8hnpKrBTlnwrIcynZT4kDiAF6BF/z7AVxV7VUvojrjL2RzeK8QLVNyfzkEJGIYBKoufOIOSSpd6nQ==", + "requires": { + "@aws-sdk/checksums": "^3.1000.3", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-sdk-s3": { + "version": "3.972.49", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.49.tgz", + "integrity": "sha512-9CQoJfMZMqGJVBqFO/C8Gwke6WM7CLskQBiAjGU5LyXsVtqhymAATfqFnIa87Dw23ssfgGzqBHpSSwSchldFXw==", + "requires": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/signature-v4-multi-region": "^3.996.33", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/nested-clients": { + "version": "3.997.18", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/nested-clients/-/nested-clients-3.997.18.tgz", + "integrity": "sha512-xBWrodBvW5SHCZV11UZUJG0pSHkLCEREIBoNbff1C1sacOUCmxJnTCPE80sCGLCtqgXg98I2MQJe2z28tcZSsw==", + "requires": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/signature-v4-multi-region": "^3.996.33", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/fetch-http-handler": "^5.4.6", + "@smithy/node-http-handler": "^4.7.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/s3-request-presigner": { + "version": "3.1064.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.1064.0.tgz", + "integrity": "sha512-BYha6t2emy50ld7wvtLkrhMsibaGNlgg1TzMXrbkof3QP+9usjikabdOI429uGyhUzklC4amPnxWLzWxP+AjIw==", + "requires": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/signature-v4-multi-region": "^3.996.33", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/signature-v4-multi-region": { + "version": "3.996.33", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.33.tgz", + "integrity": "sha512-Hn0RThJEbyOZWV2PV9Z4YD3nitGPxybmyU17dSe9b61WOBcKnqS0WTtM3c1zyZq9WnGiyrfi/i+UBPUk7cM8Ug==", + "requires": { + "@aws-sdk/types": "^3.973.12", + "@smithy/signature-v4": "^5.4.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/token-providers": { + "version": "3.1064.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/token-providers/-/token-providers-3.1064.0.tgz", + "integrity": "sha512-sjI+iA4JtgeckBgKwPQF7KzWillRoNDmtpiM0TRa0syiAKFHKUSf84kPXSO3+gA7aMMSxrcxzOM2oPSecaJvEA==", + "requires": { + "@aws-sdk/core": "^3.974.19", + "@aws-sdk/nested-clients": "^3.997.18", + "@aws-sdk/types": "^3.973.12", + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/types": { + "version": "3.973.12", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/types/-/types-3.973.12.tgz", + "integrity": "sha512-43ajd1NF0RMgX5k0hxCNUyEdrtFUsb2aHT2QvpktSC/2Eyb2Jr/JPVqdp0XIoaHWikZJq5tNWSLO6kB5q2eMCA==", + "requires": { + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/util-locate-window": { + "version": "3.965.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/util-locate-window/-/util-locate-window-3.965.7.tgz", + "integrity": "sha512-M0D6oIpohdNHjc7udzTHEQyot0+0iuA36jc2I9Hps+f/GtKi2HO/pyijQnCnNcwZqLB5+rtn81z3eZK/GyjAmA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@aws-sdk/xml-builder": { + "version": "3.972.29", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws-sdk/xml-builder/-/xml-builder-3.972.29.tgz", + "integrity": "sha512-fk0niuGFxfi8yIJuMVM4mhwObkiQSuwZFj3tAPrLVx64Pk3BkrEIpqjzHKY4hKoEBUD6Jg/S74Zj9jy+5F3DnQ==", + "requires": { + "@smithy/types": "^4.14.3", + "fast-xml-parser": "5.7.3", + "tslib": "^2.6.2" + } + }, + "@aws/lambda-invoke-store": { + "version": "0.2.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.4.tgz", + "integrity": "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==" + }, + "@babel/generator": { + "version": "7.18.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/generator/-/generator-7.18.2.tgz", + "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", + "dev": true, + "requires": { + "@babel/types": "^7.18.2", + "@jridgewell/gen-mapping": "^0.3.0", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true + }, + "@babel/parser": { + "version": "7.18.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/parser/-/parser-7.18.4.tgz", + "integrity": "sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==", + "dev": true + }, + "@babel/types": { + "version": "7.19.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/types/-/types-7.19.0.tgz", + "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "requires": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@nodable/entities": { + "version": "2.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/@nodable/entities/-/entities-2.1.1.tgz", + "integrity": "sha512-Pig3HxDIoMgjdEH8OCf/dkcTmLFjJRjWuq8jSnklu284/TKOPibSRERmOykiwmyXTtv61mP+44f3GMx0tLAyjg==" + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@smithy/core": { + "version": "3.24.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@smithy/core/-/core-3.24.6.tgz", + "integrity": "sha512-wBXDRup6UU97VKyaiRo8AssnfStPtG0oAAfpq/bC0a1YYau8pM86YB4kM6ccoVi1mS8l/UHbn9oDM+7uozr/ug==", + "requires": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@smithy/credential-provider-imds": { + "version": "4.3.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/@smithy/credential-provider-imds/-/credential-provider-imds-4.3.8.tgz", + "integrity": "sha512-5cAM+KZC02sTqDt6NaLXyu50M/GNMd1eTzDVR8Lb0BBsVtu7RWHo47VPPEEv1vt3Yub6uzr+M5FHC+GtoT0USg==", + "requires": { + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@smithy/fetch-http-handler": { + "version": "5.4.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@smithy/fetch-http-handler/-/fetch-http-handler-5.4.6.tgz", + "integrity": "sha512-FEwEYJ1jlBKdhe9TPzfghEi1bP55ZeEImlDkEa62bBBYzUcnB6RUCyuiS2mqKt6ZVjUbBgcNhzfIctH+Hevx9g==", + "requires": { + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/node-http-handler": { + "version": "4.7.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/@smithy/node-http-handler/-/node-http-handler-4.7.7.tgz", + "integrity": "sha512-ZAFvHXrEk6K180EVhmZVg8GU5pUH5BSFqRs27JW3j1qEFx9YyYwWFx17x/MHcjALYimGAji7qEOlF1++be+G5A==", + "requires": { + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@smithy/signature-v4": { + "version": "5.4.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/@smithy/signature-v4/-/signature-v4-5.4.6.tgz", + "integrity": "sha512-Ojg4B6oIDlIr1R86xCDJt1zJWnYa0VINmqdjfe9qxWjdRivHalZ3iSlQgVqYbW0MdpFOC5XfHEWsnbmdnpIILQ==", + "requires": { + "@smithy/core": "^3.24.6", + "@smithy/types": "^4.14.3", + "tslib": "^2.6.2" + } + }, + "@smithy/types": { + "version": "4.14.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/@smithy/types/-/types-4.14.3.tgz", + "integrity": "sha512-YupL0ZWmFtJexUN2cHzkvvF/b9pKrtAIfT1o7/oY/Ppu8IYeZ+lDPM5vZdQJaSeA132dJCqojjGC9NhXeF71VQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "requires": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "requires": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + } + }, + "@types/node": { + "version": "25.9.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/@types/node/-/node-25.9.2.tgz", + "integrity": "sha512-G05zqtJhcDLb8uslf5EjCxXg9G1KQxiV8OS0R26IC//Eoyitzqe8z37I7cqvnZlrlSfgocQRfSn/AHBZJJFyGw==", + "peer": true, + "requires": { + "undici-types": ">=7.24.0 <7.24.7" + } + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true + }, + "aws-ssl-profiles": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", + "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==" + }, + "balanced-match": { + "version": "4.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, + "binary-extensions": { + "version": "2.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true + }, + "bl": { + "version": "4.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "body-parser": { + "version": "1.20.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", + "requires": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + } + }, + "bowser": { + "version": "2.14.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/bowser/-/bowser-2.14.1.tgz", + "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==" + }, + "brace-expansion": { + "version": "5.0.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "dev": true, + "requires": { + "balanced-match": "^4.0.2" + } + }, + "braces": { + "version": "3.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "requires": { + "fill-range": "^7.1.1" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "bytes": { + "version": "3.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + } + }, + "call-bound": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "chokidar": { + "version": "3.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "requires": { + "safe-buffer": "5.2.1" + } + }, + "content-type": { + "version": "1.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" + }, + "cookie": { + "version": "0.7.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==" + }, + "cookie-signature": { + "version": "1.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "cors": { + "version": "2.8.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "denque": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "detect-libc": { + "version": "2.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "dotenv": { + "version": "16.6.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==" + }, + "dunder-proto": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "requires": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "encodeurl": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" + }, + "end-of-stream": { + "version": "1.4.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "es-define-property": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + "es-object-atoms": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "requires": { + "es-errors": "^1.3.0" + } + }, + "escalade": { + "version": "3.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true + }, + "express": { + "version": "4.22.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.5", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.15.1", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "fast-glob": { + "version": "3.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "requires": { + "@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" + } + }, + "fast-xml-builder": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz", + "integrity": "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==", + "requires": { + "path-expression-matcher": "^1.5.0", + "xml-naming": "^0.1.0" + } + }, + "fast-xml-parser": { + "version": "5.7.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/fast-xml-parser/-/fast-xml-parser-5.7.3.tgz", + "integrity": "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg==", + "requires": { + "@nodable/entities": "^2.1.0", + "fast-xml-builder": "^1.1.7", + "path-expression-matcher": "^1.5.0", + "strnum": "^2.2.3" + } + }, + "fastq": { + "version": "1.20.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "fill-range": { + "version": "7.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "from2": { + "version": "2.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/from2/-/from2-2.3.0.tgz", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "requires": { + "is-property": "^1.0.2" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-intrinsic": { + "version": "1.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + } + }, + "get-proto": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "requires": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "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" + } + }, + "gopd": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://mirrors.cloud.tencent.com/npm/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "has": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/has/-/has-1.0.4.tgz", + "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "has-symbols": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" + }, + "hasown": { + "version": "2.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "requires": { + "function-bind": "^1.1.2" + } + }, + "http-errors": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "requires": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://mirrors.cloud.tencent.com/npm/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "ignore": { + "version": "5.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true + }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "into-stream": { + "version": "6.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/into-stream/-/into-stream-6.0.0.tgz", + "integrity": "sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA==", + "dev": true, + "requires": { + "from2": "^2.3.0", + "p-is-promise": "^3.0.0" + } + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-core-module": { + "version": "2.9.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "jsonfile": { + "version": "6.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "long": { + "version": "5.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==" + }, + "lru.min": { + "version": "1.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/lru.min/-/lru.min-1.1.4.tgz", + "integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==" + }, + "math-intrinsics": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "merge-descriptors": { + "version": "1.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==" + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "micromatch": { + "version": "4.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "requires": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://mirrors.cloud.tencent.com/npm/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true + }, + "minimatch": { + "version": "10.2.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "requires": { + "brace-expansion": "^5.0.5" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "multistream": { + "version": "4.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/multistream/-/multistream-4.1.0.tgz", + "integrity": "sha512-J1XDiAmmNpRCBfIWJv+n0ymC4ABcf/Pl+5YvC5B/D2f/2+8PtHvCNxMPKiQcZyi922Hq69J2YOpb1pTywfifyw==", + "dev": true, + "requires": { + "once": "^1.4.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mysql2": { + "version": "3.22.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/mysql2/-/mysql2-3.22.5.tgz", + "integrity": "sha512-95uZ2TrPWAZdwpB3vvvDbmEMcNG8yIeNCyu6GUcr/QnWEE/wXm7+mhOCsdQfWQDTV7qYT/PDUZ4U4UPP4AsXqQ==", + "requires": { + "aws-ssl-profiles": "^1.1.2", + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.7.2", + "long": "^5.3.2", + "lru.min": "^1.1.4", + "named-placeholders": "^1.1.6", + "sql-escaper": "^1.3.3" + }, + "dependencies": { + "iconv-lite": { + "version": "0.7.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "named-placeholders": { + "version": "1.1.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/named-placeholders/-/named-placeholders-1.1.6.tgz", + "integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==", + "requires": { + "lru.min": "^1.1.0" + } + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "dev": true + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "node-abi": { + "version": "3.92.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/node-abi/-/node-abi-3.92.0.tgz", + "integrity": "sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ==", + "dev": true, + "requires": { + "semver": "^7.3.5" + } + }, + "node-fetch": { + "version": "2.7.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "nodemon": { + "version": "3.1.14", + "resolved": "https://mirrors.cloud.tencent.com/npm/nodemon/-/nodemon-3.1.14.tgz", + "integrity": "sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw==", + "dev": true, + "requires": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^10.2.1", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "dependencies": { + "debug": { + "version": "4.4.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "object-inspect": { + "version": "1.13.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "p-is-promise": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/p-is-promise/-/p-is-promise-3.0.0.tgz", + "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==", + "dev": true + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-expression-matcher": { + "version": "1.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz", + "integrity": "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.13", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==" + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picomatch": { + "version": "2.3.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true + }, + "pkg": { + "version": "5.8.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/pkg/-/pkg-5.8.1.tgz", + "integrity": "sha512-CjBWtFStCfIiT4Bde9QpJy0KeH19jCfwZRJqHFDFXfhUklCx8JoFmMj3wgnEYIwGmZVNkhsStPHEOnrtrQhEXA==", + "dev": true, + "requires": { + "@babel/generator": "7.18.2", + "@babel/parser": "7.18.4", + "@babel/types": "7.19.0", + "chalk": "^4.1.2", + "fs-extra": "^9.1.0", + "globby": "^11.1.0", + "into-stream": "^6.0.0", + "is-core-module": "2.9.0", + "minimist": "^1.2.6", + "multistream": "^4.1.0", + "pkg-fetch": "3.4.2", + "prebuild-install": "7.1.1", + "resolve": "^1.22.0", + "stream-meter": "^1.0.4" + } + }, + "pkg-fetch": { + "version": "3.4.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/pkg-fetch/-/pkg-fetch-3.4.2.tgz", + "integrity": "sha512-0+uijmzYcnhC0hStDjm/cl2VYdrmVVBpe7Q8k9YBojxmR5tG8mvR9/nooQq3QSXiQqORDVOTY3XqMEqJVIzkHA==", + "dev": true, + "requires": { + "chalk": "^4.1.2", + "fs-extra": "^9.1.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.6", + "progress": "^2.0.3", + "semver": "^7.3.5", + "tar-fs": "^2.1.1", + "yargs": "^16.2.0" + } + }, + "prebuild-install": { + "version": "7.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/prebuild-install/-/prebuild-install-7.1.1.tgz", + "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", + "dev": true, + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://mirrors.cloud.tencent.com/npm/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "pstree.remy": { + "version": "1.1.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "pump": { + "version": "3.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "qs": { + "version": "6.15.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "requires": { + "side-channel": "^1.1.0" + } + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.5.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "requires": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "resolve": { + "version": "1.22.12", + "resolved": "https://mirrors.cloud.tencent.com/npm/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "dependencies": { + "is-core-module": { + "version": "2.16.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "requires": { + "hasown": "^2.0.3" + } + } + } + }, + "reusify": { + "version": "1.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "7.8.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-7.8.3.tgz", + "integrity": "sha512-wnilbGyMxzbY7dNOl7jpKbLSjcfeweJWU5j4+u5qW+6/wuGD9KzIGOyZnQVSBM9E7DtWaaH3CyHkppYrKYoxwg==", + "dev": true + }, + "send": { + "version": "0.19.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "serve-static": { + "version": "1.16.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "requires": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + } + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "side-channel": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "requires": { + "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" + } + }, + "side-channel-list": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + } + }, + "side-channel-map": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + } + }, + "side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "requires": { + "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" + } + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "requires": { + "semver": "^7.5.3" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "sql-escaper": { + "version": "1.3.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/sql-escaper/-/sql-escaper-1.3.3.tgz", + "integrity": "sha512-BsTCV265VpTp8tm1wyIm1xqQCS+Q9NHx2Sr+WcnUrgLrQ6yiDIvHYJV5gHxsj1lMBy2zm5twLaZao8Jd+S8JJw==" + }, + "statuses": { + "version": "2.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==" + }, + "stream-meter": { + "version": "1.0.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/stream-meter/-/stream-meter-1.0.4.tgz", + "integrity": "sha512-4sOEtrbgFotXwnEuzzsQBYEV1elAeFSO8rSGeTwabuX1RRn/kEq9JVH7I0MRBhKVRR0sJkr0M0QCH7yOLf9fhQ==", + "dev": true, + "requires": { + "readable-stream": "^2.1.4" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true + }, + "strnum": { + "version": "2.3.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/strnum/-/strnum-2.3.0.tgz", + "integrity": "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "tar-fs": { + "version": "2.1.4", + "resolved": "https://mirrors.cloud.tencent.com/npm/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "touch": { + "version": "3.1.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://mirrors.cloud.tencent.com/npm/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "tslib": { + "version": "2.8.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://mirrors.cloud.tencent.com/npm/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "undefsafe": { + "version": "2.0.5", + "resolved": "https://mirrors.cloud.tencent.com/npm/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "undici-types": { + "version": "7.24.6", + "resolved": "https://mirrors.cloud.tencent.com/npm/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "peer": true + }, + "universalify": { + "version": "2.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://mirrors.cloud.tencent.com/npm/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://mirrors.cloud.tencent.com/npm/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "xml-naming": { + "version": "0.1.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/xml-naming/-/xml-naming-0.1.0.tgz", + "integrity": "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==" + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://mirrors.cloud.tencent.com/npm/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://mirrors.cloud.tencent.com/npm/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://mirrors.cloud.tencent.com/npm/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + } + } +} diff --git a/server/package.js b/server/package.js new file mode 100644 index 0000000..17ef95d --- /dev/null +++ b/server/package.js @@ -0,0 +1,193 @@ +/** + * JNote 后端分发包打包脚本 + * 在 Windows 上运行,打包 Linux 和 Windows 两个版本 + * 优化:Linux 生成 sh 脚本,Windows 生成 bat 脚本,原生直接执行 + */ + +const { execSync } = require('child_process'); +const fs = require('fs'); +const path = require('path'); +const os = require('os'); + +const serverDir = __dirname; +const isWindows = os.platform() === 'win32'; + +function log(msg) { + console.log(`[Package] ${msg}`); +} + +function run(cmd) { + log(`执行: ${cmd}`); + execSync(cmd, { cwd: serverDir, stdio: 'inherit' }); +} + +function main() { + console.log('========================================='); + console.log(' JNote 后端分发包打包工具'); + console.log(` 当前平台: ${isWindows ? 'Windows' : 'Linux'}`); + console.log('========================================='); + + // 检查 Node.js 环境 + try { + const nodeVersion = execSync('node --version', { encoding: 'utf8' }).trim(); + log(`✓ Node.js 版本: ${nodeVersion}`); + } catch { + console.error('❌ 错误: 未找到 Node.js'); + process.exit(1); + } + + // 安装依赖 + console.log(''); + log('📦 安装依赖...'); + run('npm install'); + + // 安装 pkg (如果未安装) + try { + execSync('pkg --version', { encoding: 'utf8', stdio: 'ignore' }); + log('✓ pkg 已安装'); + } catch { + console.log(''); + log('📦 安装 pkg...'); + run('npm install -g pkg'); + } + + // 创建输出目录 + const distDir = path.join(serverDir, 'dist'); + const releaseDir = path.join(serverDir, 'release'); + + // 清空并重建目录 + if (fs.existsSync(distDir)) fs.rmSync(distDir, { recursive: true, force: true }); + if (fs.existsSync(releaseDir)) fs.rmSync(releaseDir, { recursive: true, force: true }); + fs.mkdirSync(distDir, { recursive: true }); + fs.mkdirSync(releaseDir, { recursive: true }); + + const releaseLinux = path.join(releaseDir, 'linux'); + const releaseWindows = path.join(releaseDir, 'windows'); + fs.mkdirSync(releaseLinux, { recursive: true }); + fs.mkdirSync(releaseWindows, { recursive: true }); + + // 打包 Linux 版本(适配你的 Node16) + console.log(''); + log('🔨 打包 Linux 版本...'); + run('pkg src/index.js --targets node16-linux-x64 --output dist/jnote-api'); + + // 打包 Windows 版本(适配你的 Node16) + console.log(''); + log('🔨 打包 Windows 版本...'); + run('pkg src/index.js --targets node16-win-x64 --output dist/jnote-api.exe'); + + // ===================== 核心优化 ===================== + // 1. 复制 Linux 可执行文件 + 生成 .sh 启动脚本 + const linuxExe = path.join(distDir, 'jnote-api'); + if (fs.existsSync(linuxExe)) { + const targetLinuxExe = path.join(releaseLinux, 'jnote-api'); + fs.copyFileSync(linuxExe, targetLinuxExe); + fs.chmodSync(targetLinuxExe, 0o755); + + // 生成 Linux 原生启动脚本 start.sh + const shScript = `#!/bin/bash +# JNote 后端服务启动脚本 +cd "$(dirname "$0")" +./jnote-api +`; + const shPath = path.join(releaseLinux, 'start.sh'); + fs.writeFileSync(shPath, shScript, 'utf8'); + fs.chmodSync(shPath, 0o755); // 赋可执行权限 + log('✓ linux/jnote-api + start.sh (可直接执行)'); + } + + // 2. 复制 Windows 可执行文件 + 生成 .bat 启动脚本 + const winExe = path.join(distDir, 'jnote-api.exe'); + if (fs.existsSync(winExe)) { + fs.copyFileSync(winExe, path.join(releaseWindows, 'jnote-api.exe')); + + // 生成 Windows 原生启动脚本 start.bat + const batScript = `@echo off +:: JNote 后端服务启动脚本 +cd /d "%~dp0" +jnote-api.exe +pause +`; + const batPath = path.join(releaseWindows, 'start.bat'); + // ✅ 修复:Node16 兼容 UTF-8 编码 + fs.writeFileSync(batPath, batScript, 'utf8'); + log('✓ windows/jnote-api.exe + start.bat (双击运行)'); + } + // ==================================================== + + // 复制环境配置 + const envSrc = path.join(serverDir, '.env'); + const defaultEnv = `# 数据库配置 +DB_HOST=localhost +DB_PORT=3306 +DB_USER=root +DB_PASSWORD=your_password +DB_NAME=jnote + +# RUSTFS 对象存储配置 +RUSTFS_ENDPOINT=http://localhost:9001 +RUSTFS_BUCKET=setting +RUSTFS_ACCESS_KEY=rustfsadmin +RUSTFS_SECRET_KEY=rustfsadmin + +# 服务器配置 +PORT=3000 +`; + + if (fs.existsSync(envSrc)) { + fs.copyFileSync(envSrc, path.join(releaseLinux, '.env')); + fs.copyFileSync(envSrc, path.join(releaseLinux, '.env.example')); + fs.copyFileSync(envSrc, path.join(releaseWindows, '.env')); + fs.copyFileSync(envSrc, path.join(releaseWindows, '.env.example')); + } else { + fs.writeFileSync(path.join(releaseLinux, '.env'), defaultEnv, 'utf8'); + fs.writeFileSync(path.join(releaseWindows, '.env'), defaultEnv, 'utf8'); + } + log('✓ .env 配置文件生成完成'); + + // 创建 README + const readme = `JNote 后端服务部署说明 +===================== + +目录结构: +├── linux/ # Linux 服务器部署包 +│ ├── jnote-api # Linux 可执行二进制文件 +│ ├── start.sh # Linux 原生启动脚本 +│ └── .env # 环境配置 +│ +└── windows/ # Windows 服务器部署包 + ├── jnote-api.exe # Windows 可执行程序 + ├── start.bat # Windows 原生启动脚本 + └── .env # 环境配置 + +部署步骤: + +【Linux 服务器】 + 1. 上传 linux/ 目录到服务器 + 2. 修改 .env 中的数据库配置 + 3. 直接运行: ./start.sh + +【Windows 服务器】 + 1. 上传 windows/ 目录到服务器 + 2. 修改 .env 中的数据库配置 + 3. 双击运行 start.bat 即可 +`; + + fs.writeFileSync(path.join(releaseDir, 'README.txt'), readme, 'utf8'); + log('✓ README.txt 生成完成'); + + // 清理临时文件 + console.log(''); + log('🧹 清理临时文件...'); + try { fs.unlinkSync(linuxExe); } catch {} + try { fs.unlinkSync(winExe); } catch {} + try { fs.rmSync(distDir, { recursive: true, force: true }); } catch {} + + console.log(''); + console.log('========================================='); + console.log(' 打包完成!'); + console.log('========================================='); + console.log(`分发包目录: ${releaseDir}`); +} + +main(); \ No newline at end of file diff --git a/server/package.json b/server/package.json new file mode 100644 index 0000000..231210d --- /dev/null +++ b/server/package.json @@ -0,0 +1,24 @@ +{ + "name": "jnote-server", + "version": "1.0.0", + "description": "Jnote-ui backend API server", + "main": "src/index.js", + "scripts": { + "dev": "nodemon src/index.js", + "start": "node src/index.js", + "build": "node build.js", + "package": "node package.js" + }, + "dependencies": { + "@aws-sdk/client-s3": "^3.1064.0", + "@aws-sdk/s3-request-presigner": "^3.1064.0", + "cors": "^2.8.5", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "mysql2": "^3.22.5" + }, + "devDependencies": { + "nodemon": "^3.0.2", + "pkg": "5.8.1" + } +} \ No newline at end of file diff --git a/server/release/README.txt b/server/release/README.txt new file mode 100644 index 0000000..2d8a208 --- /dev/null +++ b/server/release/README.txt @@ -0,0 +1,25 @@ +JNote 后端服务部署说明 +===================== + +目录结构: +├── linux/ # Linux 服务器部署包 +│ ├── jnote-api # Linux 可执行二进制文件 +│ ├── start.sh # Linux 原生启动脚本 +│ └── .env # 环境配置 +│ +└── windows/ # Windows 服务器部署包 + ├── jnote-api.exe # Windows 可执行程序 + ├── start.bat # Windows 原生启动脚本 + └── .env # 环境配置 + +部署步骤: + +【Linux 服务器】 + 1. 上传 linux/ 目录到服务器 + 2. 修改 .env 中的数据库配置 + 3. 直接运行: ./start.sh + +【Windows 服务器】 + 1. 上传 windows/ 目录到服务器 + 2. 修改 .env 中的数据库配置 + 3. 双击运行 start.bat 即可 diff --git a/server/release/linux/.env b/server/release/linux/.env new file mode 100644 index 0000000..06959c2 --- /dev/null +++ b/server/release/linux/.env @@ -0,0 +1,17 @@ +# 数据库配置 +DB_HOST=43.156.91.115 +DB_PORT=53306 +DB_USER=root +# DB_PASSWORD=mysql_sX4mrh +DB_PASSWORD=mariadb_hJbME5 +DB_NAME=jnote + +# RUSTFS 对象存储配置 +RUSTFS_ENDPOINT=http://43.156.91.115:9001 +RUSTFS_REGION=us-east-1 +RUSTFS_BUCKET=setting +RUSTFS_ACCESS_KEY=rustfsadmin +RUSTFS_SECRET_KEY=rustfsadmin + +# 服务器配置 +PORT=4501 diff --git a/server/release/linux/.env.example b/server/release/linux/.env.example new file mode 100644 index 0000000..06959c2 --- /dev/null +++ b/server/release/linux/.env.example @@ -0,0 +1,17 @@ +# 数据库配置 +DB_HOST=43.156.91.115 +DB_PORT=53306 +DB_USER=root +# DB_PASSWORD=mysql_sX4mrh +DB_PASSWORD=mariadb_hJbME5 +DB_NAME=jnote + +# RUSTFS 对象存储配置 +RUSTFS_ENDPOINT=http://43.156.91.115:9001 +RUSTFS_REGION=us-east-1 +RUSTFS_BUCKET=setting +RUSTFS_ACCESS_KEY=rustfsadmin +RUSTFS_SECRET_KEY=rustfsadmin + +# 服务器配置 +PORT=4501 diff --git a/server/release/linux/jnote-api b/server/release/linux/jnote-api new file mode 100644 index 0000000..bd9c4a0 Binary files /dev/null and b/server/release/linux/jnote-api differ diff --git a/server/release/linux/start.sh b/server/release/linux/start.sh new file mode 100644 index 0000000..630fbea --- /dev/null +++ b/server/release/linux/start.sh @@ -0,0 +1,4 @@ +#!/bin/bash +# JNote 后端服务启动脚本 +cd "$(dirname "$0")" +./jnote-api diff --git a/server/release/windows/.env b/server/release/windows/.env new file mode 100644 index 0000000..06959c2 --- /dev/null +++ b/server/release/windows/.env @@ -0,0 +1,17 @@ +# 数据库配置 +DB_HOST=43.156.91.115 +DB_PORT=53306 +DB_USER=root +# DB_PASSWORD=mysql_sX4mrh +DB_PASSWORD=mariadb_hJbME5 +DB_NAME=jnote + +# RUSTFS 对象存储配置 +RUSTFS_ENDPOINT=http://43.156.91.115:9001 +RUSTFS_REGION=us-east-1 +RUSTFS_BUCKET=setting +RUSTFS_ACCESS_KEY=rustfsadmin +RUSTFS_SECRET_KEY=rustfsadmin + +# 服务器配置 +PORT=4501 diff --git a/server/release/windows/.env.example b/server/release/windows/.env.example new file mode 100644 index 0000000..06959c2 --- /dev/null +++ b/server/release/windows/.env.example @@ -0,0 +1,17 @@ +# 数据库配置 +DB_HOST=43.156.91.115 +DB_PORT=53306 +DB_USER=root +# DB_PASSWORD=mysql_sX4mrh +DB_PASSWORD=mariadb_hJbME5 +DB_NAME=jnote + +# RUSTFS 对象存储配置 +RUSTFS_ENDPOINT=http://43.156.91.115:9001 +RUSTFS_REGION=us-east-1 +RUSTFS_BUCKET=setting +RUSTFS_ACCESS_KEY=rustfsadmin +RUSTFS_SECRET_KEY=rustfsadmin + +# 服务器配置 +PORT=4501 diff --git a/server/release/windows/jnote-api.exe b/server/release/windows/jnote-api.exe new file mode 100644 index 0000000..2785a38 Binary files /dev/null and b/server/release/windows/jnote-api.exe differ diff --git a/server/release/windows/start.bat b/server/release/windows/start.bat new file mode 100644 index 0000000..7347e8d --- /dev/null +++ b/server/release/windows/start.bat @@ -0,0 +1,5 @@ +@echo off +:: JNote 后端服务启动脚本 +cd /d "%~dp0" +jnote-api.exe +pause diff --git a/server/src/config/cronScheduler.js b/server/src/config/cronScheduler.js new file mode 100644 index 0000000..d1d5c06 --- /dev/null +++ b/server/src/config/cronScheduler.js @@ -0,0 +1,166 @@ +/** + * 定时任务调度器 + * 后端运行,周期性检查并执行到期的任务 + */ +const { getPool } = require('./database'); +const memoryStore = require('./memoryStore'); + +let schedulerInterval = null; +let isRunning = false; + +function parseHeaders(headers) { + if (!headers) return {}; + if (typeof headers === 'object') return headers; + try { + return JSON.parse(headers); + } catch { + return {}; + } +} + +function calculateNextRun(cron) { + const parts = cron.trim().split(/\s+/); + if (parts.length < 5) return null; + + const now = new Date(); + const next = new Date(now); + + const [minute, hour, day, month, weekDay] = parts; + + // 设置分钟 + if (minute === '*') { + next.setMinutes(now.getMinutes() + 1, 0, 0); + } else if (minute.includes('/')) { + const step = parseInt(minute.split('/')[1]); + next.setMinutes(Math.ceil(now.getMinutes() / step) * step, 0, 0); + } else { + next.setMinutes(parseInt(minute), 0, 0); + if (next <= now) { + next.setHours(next.getHours() + 1); + } + } + + // 设置小时 + if (hour !== '*') { + if (hour.includes('/')) { + const step = parseInt(hour.split('/')[1]); + next.setHours(Math.ceil(now.getHours() / step) * step, 0, 0, 0); + } else { + next.setHours(parseInt(hour), 0, 0, 0); + } + if (next <= now) { + next.setDate(next.getDate() + 1); + } + } + + return next; +} + +async function executeTask(task) { + console.log(`[CronScheduler] 执行任务: ${task.name} (${task.id})`); + + const options = { + method: task.method || 'GET', + headers: parseHeaders(task.headers) + }; + + if (task.body && ['POST', 'PUT', 'PATCH'].includes(task.method)) { + options.body = task.body; + } + + try { + const response = await fetch(task.url, options); + const now = new Date(); + const nextRun = calculateNextRun(task.cron); + + console.log(`[CronScheduler] 任务 ${task.name} 执行完成: ${response.status}`); + + // 更新数据库 + const pool = getPool(); + if (pool) { + await pool.execute( + 'UPDATE cron_tasks SET last_run = ?, next_run = ?, run_count = run_count + 1 WHERE id = ?', + [now, nextRun, task.id] + ); + } else { + // 更新内存存储 + const idx = memoryStore.cronTasks.findIndex(t => t.id === task.id); + if (idx !== -1) { + memoryStore.cronTasks[idx].lastRun = now.toLocaleString('zh-CN'); + memoryStore.cronTasks[idx].nextRun = nextRun; + memoryStore.cronTasks[idx].runCount = (memoryStore.cronTasks[idx].runCount || 0) + 1; + } + } + } catch (error) { + console.error(`[CronScheduler] 任务 ${task.name} 执行失败:`, error.message); + + const now = new Date(); + const nextRun = calculateNextRun(task.cron); + + const pool = getPool(); + if (pool) { + await pool.execute( + 'UPDATE cron_tasks SET last_run = ?, next_run = ?, run_count = run_count + 1 WHERE id = ?', + [now, nextRun, task.id] + ); + } + } +} + +async function checkAndRunTasks() { + if (isRunning) return; + isRunning = true; + + try { + const pool = getPool(); + let tasks = []; + + if (pool) { + const [rows] = await pool.execute('SELECT * FROM cron_tasks WHERE enabled = 1'); + tasks = rows; + } else { + tasks = memoryStore.cronTasks.filter(t => t.enabled); + } + + const now = new Date(); + + for (const task of tasks) { + if (!task.next_run && !task.nextRun) continue; + + const nextRun = new Date(task.next_run || task.nextRun); + if (now >= nextRun) { + executeTask(task); + } + } + } catch (error) { + console.error('[CronScheduler] 检查任务失败:', error.message); + } finally { + isRunning = false; + } +} + +function start() { + if (schedulerInterval) { + console.log('[CronScheduler] 已启动'); + return; + } + + console.log('[CronScheduler] 启动定时任务调度器 (每10秒检查一次)'); + schedulerInterval = setInterval(checkAndRunTasks, 10000); + + // 立即执行一次检查 + checkAndRunTasks(); +} + +function stop() { + if (schedulerInterval) { + clearInterval(schedulerInterval); + schedulerInterval = null; + console.log('[CronScheduler] 已停止'); + } +} + +module.exports = { + start, + stop +}; \ No newline at end of file diff --git a/server/src/config/database.js b/server/src/config/database.js new file mode 100644 index 0000000..865dcdd --- /dev/null +++ b/server/src/config/database.js @@ -0,0 +1,207 @@ +const mysql = require('mysql2/promise'); +const { DB_NAME, TABLE_DEFINITIONS, DEFAULT_DATA } = require('./schema'); +const memoryStore = require('./memoryStore'); + +let pool = null; + +const config = { + host: process.env.DB_HOST || 'localhost', + port: process.env.DB_PORT || 3306, + user: process.env.DB_USER || 'root', + password: process.env.DB_PASSWORD || '', + waitForConnections: true, + connectionLimit: 10, + queueLimit: 0, + enableKeepAlive: true, + keepAliveInitialDelay: 0 +}; + +async function initDatabase() { + const dbHost = process.env.DB_HOST; + const dbPassword = process.env.DB_PASSWORD; + + if (!dbHost || !dbPassword) { + console.log('⚠️ 数据库未配置,部分功能将使用内存存储'); + console.log(' DB_HOST:', dbHost || '未设置'); + console.log(' DB_PASSWORD:', dbPassword ? '已设置' : '未设置'); + return null; + } + + try { + // Step 1: 连接数据库服务器(不指定数据库) + const initConfig = { ...config }; + delete initConfig.database; + const initConnection = await mysql.createConnection(initConfig); + console.log('🔌 已连接数据库服务器'); + + // Step 2: 创建数据库(如果不存在) + await initConnection.query( + `CREATE DATABASE IF NOT EXISTS \`${DB_NAME}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci` + ); + console.log(`📦 数据库 ${DB_NAME} ${await databaseExists(initConnection) ? '已存在' : '已创建'}`); + + // Step 3: 选择数据库 + await initConnection.query(`USE \`${DB_NAME}\``); + + // Step 4: 创建所有表 + for (const table of TABLE_DEFINITIONS) { + await initConnection.query(table.sql); + console.log(`📋 ${table.name} 表 ${await tableExists(initConnection, table.name) ? '已存在' : '已创建'}`); + } + + // Step 5: 初始化默认数据 + await ensureDefaultData(initConnection); + + await initConnection.end(); + + // Step 6: 创建连接池 + const poolConfig = { ...config, database: DB_NAME }; + pool = mysql.createPool(poolConfig); + + // 测试连接池 + const connection = await pool.getConnection(); + console.log('✅ 数据库连接池创建成功'); + connection.release(); + + // 预热缓存(不阻塞启动) + warmUpCache().catch(err => console.error('预热失败:', err.message)); + + return pool; + } catch (error) { + console.error('❌ 数据库初始化失败:', error.message); + console.log('⚠️ 将使用内存存储作为后备'); + return null; + } +} + +// 检查数据库是否存在 +async function databaseExists(connection) { + const [rows] = await connection.query( + `SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = ?`, + [DB_NAME] + ); + return rows.length > 0; +} + +// 检查表是否存在 +async function tableExists(connection, tableName) { + const [rows] = await connection.query( + `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?`, + [DB_NAME, tableName] + ); + return rows.length > 0; +} + +// 确保默认数据存在 +async function ensureDefaultData(connection) { + try { + // 检查 settings 是否存在 + const [settingsRows] = await connection.query('SELECT id FROM settings WHERE id = 1'); + if (settingsRows.length === 0) { + await connection.query( + 'INSERT INTO settings (id, bg_type, bg_color, bg_opacity, language) VALUES (1, ?, ?, ?, ?)', + [DEFAULT_DATA.settings.bg_type, DEFAULT_DATA.settings.bg_color, DEFAULT_DATA.settings.bg_opacity, DEFAULT_DATA.settings.language] + ); + console.log(' settings 默认数据已创建'); + } + + // 检查 about 是否存在 + const [aboutRows] = await connection.query('SELECT id FROM about WHERE id = 1'); + if (aboutRows.length === 0) { + await connection.query( + 'INSERT INTO about (id, title, intro, blog, tech, features, contact, filing_number) VALUES (1, ?, ?, ?, ?, ?, ?, ?)', + [ + DEFAULT_DATA.about.title, + DEFAULT_DATA.about.intro, + DEFAULT_DATA.about.blog, + DEFAULT_DATA.about.tech, + DEFAULT_DATA.about.features, + DEFAULT_DATA.about.contact, + DEFAULT_DATA.about.filing_number + ] + ); + console.log(' about 默认数据已创建'); + } + } catch (error) { + if (error.code !== 'ER_DUP_ENTRY') { + console.error(' 默认数据初始化失败:', error.message); + } + } +} + +// 数据预热 - 启动时加载常用数据到内存 +async function warmUpCache() { + if (!pool) return; + + try { + const [posts] = await pool.execute('SELECT * FROM posts ORDER BY date DESC'); + const [settings] = await pool.execute('SELECT * FROM settings WHERE id = 1'); + const [about] = await pool.execute('SELECT * FROM about WHERE id = 1'); + + memoryStore.posts = posts; + if (settings.length > 0) { + memoryStore.settings = formatSettings(settings[0]); + } + if (about.length > 0) { + memoryStore.about = formatAbout(about[0]); + } + + console.log('✅ 数据预热完成'); + } catch (error) { + console.error('数据预热失败:', error.message); + } +} + +function formatSettings(row) { + if (!row) return memoryStore.settings; + + return { + bgType: row.bg_type, + bgColor: row.bg_color, + bgImage: row.bg_image, + bgOpacity: row.bg_opacity, + language: row.language, + favicon: row.favicon, + uploadedImages: parseJSON(row.uploaded_images, []), + uploadedIcons: parseJSON(row.uploaded_icons, []) + }; +} + +function formatAbout(row) { + if (!row) return memoryStore.about; + const about = { ...row }; + if (about.tech && typeof about.tech === 'string') { + about.techList = about.tech.split(',').map(t => t.trim()); + } + if (about.features && typeof about.features === 'string') { + try { + about.featuresList = JSON.parse(about.features); + } catch { + about.featuresList = []; + } + } + if (about.contact && typeof about.contact === 'string') { + try { + about.contactObj = JSON.parse(about.contact); + } catch { + about.contactObj = {}; + } + } + return about; +} + +function parseJSON(str, defaultValue) { + if (!str) return defaultValue; + if (typeof str === 'object') return str; + try { + return JSON.parse(str); + } catch { + return defaultValue; + } +} + +function getPool() { + return pool; +} + +module.exports = { initDatabase, getPool }; \ No newline at end of file diff --git a/server/src/config/envManager.js b/server/src/config/envManager.js new file mode 100644 index 0000000..454df76 --- /dev/null +++ b/server/src/config/envManager.js @@ -0,0 +1,110 @@ +/** + * .env 文件管理器 + * 读取和写入环境配置 + */ +const fs = require('fs'); +const path = require('path'); + +const ENV_PATH = path.join(__dirname, '../../.env'); + +// 配置字段定义 +const CONFIG_FIELDS = { + db: ['DB_HOST', 'DB_PORT', 'DB_USER', 'DB_PASSWORD', 'DB_NAME'], + rustfs: ['RUSTFS_ENDPOINT', 'RUSTFS_REGION', 'RUSTFS_BUCKET', 'RUSTFS_ACCESS_KEY', 'RUSTFS_SECRET_KEY'], + server: ['PORT'] +}; + +// 读取 .env 文件 +function readEnv() { + try { + if (!fs.existsSync(ENV_PATH)) { + return {}; + } + const content = fs.readFileSync(ENV_PATH, 'utf-8'); + const result = {}; + + content.split('\n').forEach(line => { + line = line.trim(); + if (!line || line.startsWith('#')) return; + + const idx = line.indexOf('='); + if (idx > 0) { + const key = line.substring(0, idx).trim(); + const value = line.substring(idx + 1).trim(); + result[key] = value; + } + }); + + return result; + } catch (error) { + console.error('读取 .env 失败:', error); + return {}; + } +} + +// 写入 .env 文件 +function writeEnv(config) { + try { + const lines = []; + + // 数据库配置 + lines.push('# 数据库配置'); + lines.push(`DB_HOST=${config.DB_HOST || 'localhost'}`); + lines.push(`DB_PORT=${config.DB_PORT || 3306}`); + lines.push(`DB_USER=${config.DB_USER || 'root'}`); + lines.push(`DB_PASSWORD=${config.DB_PASSWORD || ''}`); + lines.push(`DB_NAME=${config.DB_NAME || 'jnote'}`); + lines.push(''); + + // RUSTFS 配置 + lines.push('# RUSTFS 对象存储配置'); + lines.push(`RUSTFS_ENDPOINT=${config.RUSTFS_ENDPOINT || 'http://43.156.91.115:9001'}`); + lines.push(`RUSTFS_REGION=${config.RUSTFS_REGION || 'us-east-1'}`); + lines.push(`RUSTFS_BUCKET=${config.RUSTFS_BUCKET || 'setting'}`); + lines.push(`RUSTFS_ACCESS_KEY=${config.RUSTFS_ACCESS_KEY || 'rustfsadmin'}`); + lines.push(`RUSTFS_SECRET_KEY=${config.RUSTFS_SECRET_KEY || 'rustfsadmin'}`); + lines.push(''); + + // 服务器配置 + lines.push('# 服务器配置'); + lines.push(`PORT=${config.PORT || 3000}`); + + fs.writeFileSync(ENV_PATH, lines.join('\n'), 'utf-8'); + return true; + } catch (error) { + console.error('写入 .env 失败:', error); + return false; + } +} + +// 获取安全配置(密码隐藏) +function getSafeConfig() { + const config = readEnv(); + + return { + db: { + host: config.DB_HOST || 'localhost', + port: config.DB_PORT || '3306', + user: config.DB_USER || 'root', + password: config.DB_PASSWORD ? '******' : '', + name: config.DB_NAME || 'jnote' + }, + rustfs: { + endpoint: config.RUSTFS_ENDPOINT || 'http://43.156.91.115:9001', + region: config.RUSTFS_REGION || 'us-east-1', + bucket: config.RUSTFS_BUCKET || 'setting', + accessKey: config.RUSTFS_ACCESS_KEY || 'rustfsadmin', + secretKey: config.RUSTFS_SECRET_KEY ? '******' : '' + }, + server: { + port: config.PORT || '3000' + } + }; +} + +module.exports = { + readEnv, + writeEnv, + getSafeConfig, + CONFIG_FIELDS +}; \ No newline at end of file diff --git a/server/src/config/memoryStore.js b/server/src/config/memoryStore.js new file mode 100644 index 0000000..f3eb16d --- /dev/null +++ b/server/src/config/memoryStore.js @@ -0,0 +1,50 @@ +// 内存存储后备方案(数据库未配置时使用) +const memoryStore = { + posts: [ + { id: 1, title: '欢迎来到我的编程学习记录', date: '2026-06-01', excerpt: '这是我的第一篇文章,欢迎大家来访!', content: '这是我的第一篇文章,欢迎大家来访!在这里我会分享一些技术心得和生活感悟。希望大家喜欢这里的内容,有任何问题欢迎留言交流。' }, + { id: 2, title: 'Vue 3 组合式 API 入门', date: '2026-06-02', excerpt: '探索 Vue 3 的组合式 API,感受更好的代码组织方式。', content: 'Vue 3 引入了组合式 API,这是一种全新的代码组织方式。通过 setup 函数和响应式 API,我们可以更灵活地组织组件逻辑,提高代码的可复用性和可维护性。\n\n主要特点:\n1. 更好的逻辑复用\n2. 更灵活的代码组织\n3. 更好的 TypeScript 支持' }, + { id: 3, title: '静态网站生成器选型', date: '2026-06-03', excerpt: '对比常见的静态网站生成器,帮助你选择合适的工具。', content: '选择一个合适的静态网站生成器需要考虑多个因素:\n\n1. Hexo - 简单易用,主题丰富\n2. Jekyll - GitHub Pages 原生支持,社区活跃\n3. Hugo - 构建速度极快\n4. VuePress / VitePress - 基于 Vue,适合技术文档\n\n本博客使用 Vue 3 + Vite 构建,兼具现代特性和开发体验。' }, + { id: 4, title: '优雅地使用 Pinia 管理状态', date: '2026-06-04', excerpt: 'Pinia 是 Vue 3 推荐的状态管理方案,本篇介绍其基本用法。', content: 'Pinia 是 Vue 官方推荐的新一代状态管理库,相比 Vuex 更加轻量和直观。\n\n核心概念:\n- Store - 存储状态的地方\n- Getters - 类似 computed 的状态计算\n- Actions - 处理异步逻辑或修改状态' }, + { id: 5, title: 'CSS Grid 布局实战技巧', date: '2026-06-05', excerpt: '深入探索 CSS Grid,让页面布局变得轻而易举。', content: 'CSS Grid 是现代 CSS 布局的重要组成部分,比 Flexbox 更适合二维布局场景。\n\n基础用法:\n.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }\n\n常用场景:\n1. 相册网格 - 自动填充列数\n2. 圣杯布局 - 经典三栏布局\n3. 响应式卡片 - 自动换行适配' }, + { id: 6, title: '用 Git 工作流提升团队协作效率', date: '2026-06-06', excerpt: 'GitFlow vs trunk-based development,选对工作流事半功倍。', content: '良好的 Git 工作流能让团队协作更加顺畅。常见的工作流模型:\n\n1. GitFlow - 分支模型清晰,适合发布周期稳定的项目\n2. trunk-based development - 主干开发,快速迭代\n3. fork workflow - 开源项目首选,隔离性强\n\n小团队推荐使用简化 GitFlow:main + develop + feature 分支。' }, + { id: 7, title: 'JavaScript 事件循环机制详解', date: '2026-06-07', excerpt: '理解 Event Loop、宏任务与微任务,告别异步编程困惑。', content: '事件循环是 JavaScript 异步编程的核心机制。\n\n执行顺序:\n1. 同步代码优先执行\n2. 微任务(Promise、MutationObserver)\n3. 宏任务(setTimeout、setInterval、setImmediate)\n\n示例:\nconsole.log(\'1\');\nsetTimeout(() => console.log(\'2\'), 0);\nPromise.resolve().then(() => console.log(\'3\'));\nconsole.log(\'4\');\n\n输出顺序:1, 4, 3, 2' }, + { id: 8, title: '我的开发环境配置分享', date: '2026-06-08', excerpt: 'VS Code + Zsh + Tmux,打造高效开发终端。', content: '工欲善其事,必先利其器。分享我的开发环境配置:\n\n编辑器:\n- VS Code + Vim 插件\n- Tokyo Night 主题\n- Fira Code 字体 + 连字\n\n终端:\n- iTerm2 (macOS) / Windows Terminal\n- Oh My Zsh\n- Tmux 会话管理\n\n版本管理:\n- Git + delta 美化 diff\n- lazygit 终端 UI' }, + { id: 9, title: '从零搭建一个 CLI 工具', date: '2026-06-09', excerpt: '使用 Node.js 和 commander.js 快速构建命令行工具。', content: '命令行工具是提升开发效率的利器。使用 Node.js 可以快速构建:\n\n初始化项目:\nnpm init -y\nnpm install commander inquirer\n\n核心代码:\nconst { program } = require(\'commander\');\nprogram.version(\'1.0.0\');\nprogram.option(\'-n, --name \', \'项目名称\');\nprogram.parse(process.argv);\n\n发布到 npm:\nnpm publish --access public' }, + { id: 10, title: '为什么我喜欢深夜编程', date: '2026-06-10', excerpt: '安静、专注、不被打扰,深夜是程序员的黄金时段。', content: '深夜编程的独特魅力:\n\n1. 绝对安静 - 无人打扰,思路连贯\n2. 效率翻倍 - 深度工作状态\n3. 问题解决 - 复杂 bug 往往在这时候被攻破\n\n当然,也要适度。注意休息,保护眼睛,第二天才能持续输出。\n\n推荐配合:黑咖啡 + 轻音乐 + 舒适的降噪耳机。' } + ], + + about: { + id: 1, + title: '关于我', + intro: '你好!我是一名热爱技术开发的开发者。', + blog: '这个博客用于分享我在学习和工作中的一些心得体会。', + tech: 'Vue / Vue 3, JavaScript / TypeScript, Node.js, Vite, Pinia, Vue Router', + features: JSON.stringify([ + '定时任务系统 - 支持 Cron表达式的自动化任务管理', + '自定义背景 - 支持纯色和图片背景,可调节透明度', + '多语言支持 - 中英文切换', + '自定义图标 - 上传本地图片作为网站图标' + ]), + contact: JSON.stringify({ + email: 'example@email.com', + github: 'github.com/yourusername' + }), + filing_number: '桂ICP备2022004108号-1' + }, + + settings: { + id: 1, + bg_type: 'color', + bg_color: '#f5f5f5', + bg_image: '', + bg_opacity: 1.00, + language: 'zh', + favicon: '', + uploaded_images: JSON.stringify([]), + uploaded_icons: JSON.stringify([]) + }, + + cronTasks: [] +}; + +module.exports = memoryStore; \ No newline at end of file diff --git a/server/src/config/rustfs.js b/server/src/config/rustfs.js new file mode 100644 index 0000000..680a9ad --- /dev/null +++ b/server/src/config/rustfs.js @@ -0,0 +1,235 @@ +/** + * RUSTFS 对象存储配置 + * 直接使用 HTTP API 避免 AWS SDK 兼容性问题 + */ +const https = require('https'); +const http = require('http'); +const crypto = require('crypto'); + +const config = { + endpoint: process.env.RUSTFS_ENDPOINT || 'http://43.156.91.115:9001', + bucket: process.env.RUSTFS_BUCKET || 'setting', + accessKey: process.env.RUSTFS_ACCESS_KEY || 'rustfsadmin', + secretKey: process.env.RUSTFS_SECRET_KEY || 'rustfsadmin' +}; + +// 生成 AWS Signature V4 +function createSignature(method, path, headers, query = '') { + const date = new Date().toISOString().replace(/[:\-]|\.\d{3}/g, ''); + const dateShort = date.substring(0, 8); + + const payloadHash = crypto.createHash('sha256').update('').digest('hex'); + const canonicalHeaders = Object.entries(headers) + .map(([k, v]) => `${k.toLowerCase()}:${v}`) + .join('\n'); + const signedHeaders = Object.keys(headers).map(k => k.toLowerCase()).join(';'); + + const canonicalRequest = [ + method, + path, + query, + canonicalHeaders, + '', + signedHeaders, + payloadHash + ].join('\n'); + + const credentialScope = `${dateShort}/us-east-1/s3/aws4_request`; + const stringToSign = [ + 'AWS4-HMAC-SHA256', + date, + credentialScope, + crypto.createHash('sha256').update(canonicalRequest).digest('hex') + ].join('\n'); + + const kDate = crypto.createHmac('sha256', `AWS4${config.secretKey}`).update(dateShort).digest(); + const kRegion = crypto.createHmac('sha256', kDate).update('us-east-1').digest(); + const kService = crypto.createHmac('sha256', kRegion).update('s3').digest(); + const kSigning = crypto.createHmac('sha256', kService).update('aws4_request').digest(); + const signature = crypto.createHmac('sha256', kSigning).update(stringToSign).digest('hex'); + + return { + authorization: `AWS4-HMAC-SHA256 Credential=${config.accessKey}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`, + 'x-amz-date': date, + 'x-amz-content-sha256': payloadHash + }; +} + +function makeRequest(method, path, body = null, contentType = 'application/octet-stream') { + return new Promise((resolve, reject) => { + const url = new URL(config.endpoint); + const isHttps = url.protocol === 'https:'; + const httpModule = isHttps ? https : http; + + const query = ''; + const headers = { + 'host': url.host, + 'content-type': contentType, + 'x-amz-date': new Date().toISOString().replace(/[:\-]|\.\d{3}/g, '').substring(0, 8) + 'T000000Z' + }; + + if (body) { + headers['content-length'] = Buffer.byteLength(body); + } + + // 简化认证:使用 Access Key 作为 Authorization header + headers['Authorization'] = `AWS ${config.accessKey}:${crypto.createHash('sha256').update(config.secretKey).digest('hex')}`; + + const options = { + hostname: url.hostname, + port: url.port || (isHttps ? 443 : 9001), + path: `/${config.bucket}${path}`, + method: method, + headers: headers + }; + + const req = httpModule.request(options, (res) => { + let data = ''; + res.on('data', chunk => data += chunk); + res.on('end', () => { + if (res.statusCode >= 200 && res.statusCode < 300) { + resolve(data); + } else { + reject(new Error(`HTTP ${res.statusCode}: ${data}`)); + } + }); + }); + + req.on('error', reject); + + if (body) { + req.write(body); + } + req.end(); + }); +} + +/** + * 上传文件到 RUSTFS + */ +async function uploadFile(fileData, key, contentType = 'image/jpeg') { + // 解析 endpoint + const endpoint = config.endpoint; + const url = new URL(endpoint); + const isHttps = url.protocol === 'https:'; + const httpModule = isHttps ? https : http; + + const date = new Date().toISOString().replace(/[:\-]|\.\d{3}/g, '').substring(0, 8); + const datetime = date + 'T000000Z'; + + // 创建签名字符串 + const credential = `${config.accessKey}/${date}/us-east-1/s3/aws4_request`; + const signedHeaders = 'content-type;host;x-amz-content-sha256;x-amz-date'; + const contentHash = crypto.createHash('sha256').update(fileData).digest('hex'); + + const canonicalHeaders = [ + `content-type:${contentType}`, + `host:${url.host}`, + `x-amz-content-sha256:${contentHash}`, + `x-amz-date:${datetime}` + ].join('\n'); + + const canonicalRequest = [ + 'PUT', + `/${config.bucket}/${key}`, + '', + canonicalHeaders, + '', + signedHeaders, + contentHash + ].join('\n'); + + const stringToSign = [ + 'AWS4-HMAC-SHA256', + datetime, + `${date}/us-east-1/s3/aws4_request`, + crypto.createHash('sha256').update(canonicalRequest).digest('hex') + ].join('\n'); + + // 计算签名 + const k1 = crypto.createHmac('sha256', 'AWS4' + config.secretKey).update(date).digest(); + const k2 = crypto.createHmac('sha256', k1).update('us-east-1').digest(); + const k3 = crypto.createHmac('sha256', k2).update('s3').digest(); + const k4 = crypto.createHmac('sha256', k3).update('aws4_request').digest(); + const signature = crypto.createHmac('sha256', k4).update(stringToSign).digest('hex'); + + const authorization = `AWS4-HMAC-SHA256 Credential=${credential}, SignedHeaders=${signedHeaders}, Signature=${signature}`; + + return new Promise((resolve, reject) => { + const options = { + hostname: url.hostname, + port: url.port || (isHttps ? 443 : 9001), + path: `/${config.bucket}/${key}`, + method: 'PUT', + headers: { + 'Content-Type': contentType, + 'Host': url.host, + 'X-Amz-Content-Sha256': contentHash, + 'X-Amz-Date': datetime, + 'Authorization': authorization, + 'Content-Length': Buffer.byteLength(fileData) + } + }; + + const req = httpModule.request(options, (res) => { + let data = ''; + res.on('data', chunk => data += chunk); + res.on('end', () => { + if (res.statusCode >= 200 && res.statusCode < 300) { + resolve(`${endpoint}/${config.bucket}/${key}`); + } else { + reject(new Error(`Upload failed: HTTP ${res.statusCode} - ${data}`)); + } + }); + }); + + req.on('error', reject); + req.write(fileData); + req.end(); + }); +} + +/** + * 删除 RUSTFS 中的文件 + */ +async function deleteFile(key) { + const endpoint = config.endpoint; + const url = new URL(endpoint); + const isHttps = url.protocol === 'https:'; + const httpModule = isHttps ? https : http; + + const datetime = new Date().toISOString().replace(/[:\-]|\.\d{3}/g, '').substring(0, 8) + 'T000000Z'; + + return new Promise((resolve, reject) => { + const options = { + hostname: url.hostname, + port: url.port || (isHttps ? 443 : 9001), + path: `/${config.bucket}/${key}`, + method: 'DELETE', + headers: { + 'Host': url.host, + 'X-Amz-Date': datetime, + 'Authorization': `AWS ${config.accessKey}:${crypto.createHash('sha256').update(config.secretKey).digest('hex')}` + } + }; + + const req = httpModule.request(options, (res) => { + if (res.statusCode >= 200 && res.statusCode < 300) { + resolve(); + } else { + let data = ''; + res.on('data', chunk => data += chunk); + res.on('end', () => reject(new Error(`Delete failed: HTTP ${res.statusCode}`))); + } + }); + + req.on('error', reject); + req.end(); + }); +} + +module.exports = { + uploadFile, + deleteFile, + config +}; diff --git a/server/src/config/schema.js b/server/src/config/schema.js new file mode 100644 index 0000000..35ce74b --- /dev/null +++ b/server/src/config/schema.js @@ -0,0 +1,108 @@ +/** + * 数据库表结构定义 + * 包含所有表的 CREATE TABLE 语句 + */ + +const DB_NAME = process.env.DB_NAME || 'jnote'; + +// posts 表 - content 改为 MEDIUMTEXT 支持更大内容 +const CREATE_POSTS_TABLE = ` +CREATE TABLE IF NOT EXISTS posts ( + id INT AUTO_INCREMENT PRIMARY KEY, + title VARCHAR(255) NOT NULL, + date DATE NOT NULL, + excerpt TEXT, + content MEDIUMTEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + INDEX idx_posts_date (date DESC) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci +`; + +// about 表 - features 和 contact 改为 JSON 类型 +const CREATE_ABOUT_TABLE = ` +CREATE TABLE IF NOT EXISTS about ( + id INT PRIMARY KEY DEFAULT 1, + title VARCHAR(255) DEFAULT '关于我', + intro TEXT, + blog TEXT, + tech TEXT, + features JSON, + contact JSON, + filing_number VARCHAR(100), + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci +`; + +// settings 表 - uploaded_images/icons 改为 JSON 类型,bg_image/favicon 改为更节省空间的 TEXT +const CREATE_SETTINGS_TABLE = ` +CREATE TABLE IF NOT EXISTS settings ( + id INT PRIMARY KEY DEFAULT 1, + bg_type VARCHAR(20) DEFAULT 'color', + bg_color VARCHAR(20) DEFAULT '#f5f5f5', + bg_image TEXT, + bg_opacity DECIMAL(3,2) DEFAULT 1.00, + language VARCHAR(10) DEFAULT 'zh', + favicon TEXT, + uploaded_images JSON, + uploaded_icons JSON, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci +`; + +// cron_tasks 表 +const CREATE_CRON_TASKS_TABLE = ` +CREATE TABLE IF NOT EXISTS cron_tasks ( + id VARCHAR(50) PRIMARY KEY, + name VARCHAR(255) NOT NULL, + cron VARCHAR(50) NOT NULL, + url VARCHAR(500) NOT NULL, + method VARCHAR(20) DEFAULT 'GET', + headers TEXT, + body TEXT, + enabled TINYINT(1) DEFAULT 1, + last_run DATETIME, + next_run DATETIME, + run_count INT DEFAULT 0, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci +`; + +// 所有表创建的执行顺序(按依赖关系) +const TABLE_DEFINITIONS = [ + { name: 'posts', sql: CREATE_POSTS_TABLE }, + { name: 'about', sql: CREATE_ABOUT_TABLE }, + { name: 'settings', sql: CREATE_SETTINGS_TABLE }, + { name: 'cron_tasks', sql: CREATE_CRON_TASKS_TABLE } +]; + +// 默认数据 +const DEFAULT_DATA = { + about: { + title: '关于我', + intro: '你好!我是一名热爱技术开发的开发者。', + blog: '这个博客用于分享我在学习和工作中的一些心得体会。', + tech: 'Vue / Vue 3, JavaScript / TypeScript, Node.js, Vite, Pinia, Vue Router', + features: JSON.stringify([ + '定时任务系统 - 支持 Cron表达式的自动化任务管理', + '自定义背景 - 支持纯色和图片背景,可调节透明度', + '多语言支持 - 中英文切换', + '自定义图标 - 上传本地图片作为网站图标' + ]), + contact: JSON.stringify({ email: 'example@email.com', github: 'github.com/yourusername' }), + filing_number: '桂ICP备2022004108号-1' + }, + settings: { + bg_type: 'color', + bg_color: '#f5f5f5', + bg_opacity: 1.00, + language: 'zh' + } +}; + +module.exports = { + DB_NAME, + TABLE_DEFINITIONS, + DEFAULT_DATA +}; \ No newline at end of file diff --git a/server/src/index.js b/server/src/index.js new file mode 100644 index 0000000..b7e74db --- /dev/null +++ b/server/src/index.js @@ -0,0 +1,52 @@ +require('dotenv').config(); + +const express = require('express'); +const cors = require('cors'); +const { initDatabase } = require('./config/database'); +const cronScheduler = require('./config/cronScheduler'); + +const app = express(); +const PORT = process.env.PORT || 3000; + +// 中间件 +app.use(cors()); +app.use(express.json({ limit: '10mb' })); + +// 路由 +const postsRouter = require('./routes/posts'); +const aboutRouter = require('./routes/about'); +const settingsRouter = require('./routes/settings'); +const cronRouter = require('./routes/cron'); +const configRouter = require('./routes/config'); + +app.use('/api/posts', postsRouter); +app.use('/api/about', aboutRouter); +app.use('/api/settings', settingsRouter); +app.use('/api/cron-tasks', cronRouter); +app.use('/api/config', configRouter); + +// 健康检查 +app.get('/api/health', (req, res) => { + res.json({ status: 'ok', timestamp: new Date().toISOString() }); +}); + +// 错误处理 +app.use((err, req, res, next) => { + console.error('Error:', err); + res.status(500).json({ error: '服务器内部错误' }); +}); + +// 启动服务器 +async function start() { + await initDatabase(); + + // 启动定时任务调度器 + cronScheduler.start(); + + app.listen(PORT, () => { + console.log(`🚀 服务器运行在 http://localhost:${PORT}`); + console.log(`📖 API 文档: http://localhost:${PORT}/api/health`); + }); +} + +start(); \ No newline at end of file diff --git a/server/src/routes/about.js b/server/src/routes/about.js new file mode 100644 index 0000000..d9ca9e8 --- /dev/null +++ b/server/src/routes/about.js @@ -0,0 +1,96 @@ +const express = require('express'); +const router = express.Router(); +const { getPool } = require('../config/database'); +const memoryStore = require('../config/memoryStore'); + +// 获取关于内容 - 优先使用预热缓存 +router.get('/', async (req, res) => { + try { + const pool = getPool(); + + if (!pool) { + return res.json(memoryStore.about); + } + + // 优先返回缓存数据 + if (memoryStore.about && memoryStore.about.id === 1) { + return res.json(memoryStore.about); + } + + const [rows] = await pool.execute('SELECT * FROM about WHERE id = 1'); + if (rows.length === 0) { + return res.json(memoryStore.about); + } + + const about = formatAbout(rows[0]); + memoryStore.about = about; + res.json(about); + } catch (error) { + console.error('获取关于内容失败:', error); + res.json(memoryStore.about); + } +}); + +// 格式化 about 数据 - MySQL JSON 类型直接返回对象 +function formatAbout(row) { + if (!row) return memoryStore.about; + const about = { ...row }; + if (about.tech && typeof about.tech === 'string') { + about.techList = about.tech.split(',').map(t => t.trim()); + } + // MySQL JSON 类型直接返回 JS 对象,不需要 JSON.parse + if (about.features && typeof about.features === 'string') { + try { + about.featuresList = JSON.parse(about.features); + } catch { + about.featuresList = Array.isArray(about.features) ? about.features : []; + } + } else if (Array.isArray(about.features)) { + about.featuresList = about.features; + } + if (about.contact && typeof about.contact === 'string') { + try { + about.contactObj = JSON.parse(about.contact); + } catch { + about.contactObj = typeof about.contact === 'object' ? about.contact : {}; + } + } else if (typeof about.contact === 'object') { + about.contactObj = about.contact; + } + return about; +} + +// 更新关于内容 +router.put('/', async (req, res) => { + try { + const { title, intro, blog, tech, features, contact, filing_number } = req.body; + const pool = getPool(); + + if (!pool) { + Object.assign(memoryStore.about, { title, intro, blog, tech, features, contact, filing_number }); + return res.json(memoryStore.about); + } + + await pool.execute( + `UPDATE about SET title = ?, intro = ?, blog = ?, tech = ?, features = ?, contact = ?, filing_number = ? WHERE id = 1`, + [ + title || '关于我', + intro || '', + tech || '', + typeof features === 'object' ? JSON.stringify(features) : features || '[]', + typeof contact === 'object' ? JSON.stringify(contact) : contact || '{}', + filing_number || '' + ] + ); + + const [rows] = await pool.execute('SELECT * FROM about WHERE id = 1'); + const updated = formatAbout(rows[0]); + memoryStore.about = updated; + res.json(updated); + } catch (error) { + console.error('更新关于内容失败:', error); + res.status(500).json({ error: '更新关于内容失败' }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/server/src/routes/config.js b/server/src/routes/config.js new file mode 100644 index 0000000..a011cc9 --- /dev/null +++ b/server/src/routes/config.js @@ -0,0 +1,73 @@ +const express = require('express'); +const router = express.Router(); +const envManager = require('../config/envManager'); + +// 获取当前配置(密码隐藏) +router.get('/', (req, res) => { + try { + const config = envManager.getSafeConfig(); + res.json(config); + } catch (error) { + console.error('获取配置失败:', error); + res.status(500).json({ error: '获取配置失败' }); + } +}); + +// 更新配置 +router.put('/', (req, res) => { + try { + const { db, rustfs, server } = req.body; + + const config = { + // 数据库配置 + DB_HOST: db?.host || 'localhost', + DB_PORT: db?.port || '3306', + DB_USER: db?.user || 'root', + DB_PASSWORD: db?.password || '', + DB_NAME: db?.name || 'jnote', + // RUSTFS 配置 + RUSTFS_ENDPOINT: rustfs?.endpoint || 'http://43.156.91.115:9001', + RUSTFS_REGION: rustfs?.region || 'us-east-1', + RUSTFS_BUCKET: rustfs?.bucket || 'setting', + RUSTFS_ACCESS_KEY: rustfs?.accessKey || 'rustfsadmin', + RUSTFS_SECRET_KEY: rustfs?.secretKey || 'rustfsadmin', + // 服务器配置 + PORT: server?.port || '3000' + }; + + // 如果密码字段为 ******,说明没改,从原文件读取 + if (db?.password === '******') { + const oldConfig = envManager.readEnv(); + config.DB_PASSWORD = oldConfig.DB_PASSWORD || ''; + } + if (rustfs?.secretKey === '******') { + const oldConfig = envManager.readEnv(); + config.RUSTFS_SECRET_KEY = oldConfig.RUSTFS_SECRET_KEY || ''; + } + + const success = envManager.writeEnv(config); + if (!success) { + return res.status(500).json({ error: '保存配置失败' }); + } + + res.json(envManager.getSafeConfig()); + } catch (error) { + console.error('更新配置失败:', error); + res.status(500).json({ error: '更新配置失败' }); + } +}); + +// 重启服务 +router.post('/restart', (req, res) => { + console.log('收到重启信号,准备关闭服务...'); + + // 优雅退出,让 PM2 或其他进程管理器自动重启 + res.json({ message: '服务即将重启', delay: 1000 }); + + // 延迟一点再退出,让响应先发出去 + setTimeout(() => { + process.exit(0); + }, 500); +}); + +module.exports = router; \ No newline at end of file diff --git a/server/src/routes/cron.js b/server/src/routes/cron.js new file mode 100644 index 0000000..5d9bf09 --- /dev/null +++ b/server/src/routes/cron.js @@ -0,0 +1,249 @@ +const express = require('express'); +const router = express.Router(); +const { getPool } = require('../config/database'); +const memoryStore = require('../config/memoryStore'); + +// 获取所有定时任务 +router.get('/', async (req, res) => { + try { + const pool = getPool(); + + if (!pool) { + return res.json(memoryStore.cronTasks); + } + + const [rows] = await pool.execute('SELECT * FROM cron_tasks ORDER BY created_at DESC'); + res.json(rows.map(formatCronTask)); + } catch (error) { + console.error('获取定时任务失败:', error); + res.json(memoryStore.cronTasks); + } +}); + +// 创建定时任务 +router.post('/', async (req, res) => { + try { + const { name, cron, url, method, headers, body, enabled } = req.body; + + if (!name || !cron || !url) { + return res.status(400).json({ error: '任务名称、Cron表达式和URL是必填项' }); + } + + const pool = getPool(); + const id = Date.now().toString(); + const nextRun = calculateNextRun(cron); + + if (!pool) { + const newTask = { + id, + name, + cron, + url, + method: method || 'GET', + headers: headers || '', + body: body || '', + enabled: enabled !== false, + lastRun: null, + nextRun, + runCount: 0 + }; + memoryStore.cronTasks.push(newTask); + return res.status(201).json(newTask); + } + + await pool.execute( + `INSERT INTO cron_tasks (id, name, cron, url, method, headers, body, enabled, next_run, run_count) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 0)`, + [id, name, cron, url, method || 'GET', headers || '', body || '', enabled !== false ? 1 : 0, nextRun] + ); + + const [rows] = await pool.execute('SELECT * FROM cron_tasks WHERE id = ?', [id]); + res.status(201).json(formatCronTask(rows[0])); + } catch (error) { + console.error('创建定时任务失败:', error); + res.status(500).json({ error: '创建定时任务失败' }); + } +}); + +// 更新定时任务 +router.put('/:id', async (req, res) => { + try { + const { name, cron, url, method, headers, body, enabled } = req.body; + const pool = getPool(); + + if (!pool) { + const index = memoryStore.cronTasks.findIndex(t => t.id === req.params.id); + if (index === -1) { + return res.status(404).json({ error: '任务未找到' }); + } + const nextRun = calculateNextRun(cron); + memoryStore.cronTasks[index] = { + ...memoryStore.cronTasks[index], + name, cron, url, method, headers, body, enabled, nextRun + }; + return res.json(memoryStore.cronTasks[index]); + } + + const nextRun = calculateNextRun(cron); + await pool.execute( + `UPDATE cron_tasks SET name = ?, cron = ?, url = ?, method = ?, headers = ?, body = ?, enabled = ?, next_run = ? WHERE id = ?`, + [name, cron, url, method || 'GET', headers || '', body || '', enabled ? 1 : 0, nextRun, req.params.id] + ); + + const [rows] = await pool.execute('SELECT * FROM cron_tasks WHERE id = ?', [req.params.id]); + if (rows.length === 0) { + return res.status(404).json({ error: '任务未找到' }); + } + res.json(formatCronTask(rows[0])); + } catch (error) { + console.error('更新定时任务失败:', error); + res.status(500).json({ error: '更新定时任务失败' }); + } +}); + +// 删除定时任务 +router.delete('/:id', async (req, res) => { + try { + const pool = getPool(); + + if (!pool) { + const index = memoryStore.cronTasks.findIndex(t => t.id === req.params.id); + if (index === -1) { + return res.status(404).json({ error: '任务未找到' }); + } + memoryStore.cronTasks.splice(index, 1); + return res.status(204).send(); + } + + const [result] = await pool.execute('DELETE FROM cron_tasks WHERE id = ?', [req.params.id]); + if (result.affectedRows === 0) { + return res.status(404).json({ error: '任务未找到' }); + } + res.status(204).send(); + } catch (error) { + console.error('删除定时任务失败:', error); + res.status(500).json({ error: '删除定时任务失败' }); + } +}); + +// 立即执行任务 +router.post('/:id/run', async (req, res) => { + try { + const pool = getPool(); + + let task; + if (!pool) { + task = memoryStore.cronTasks.find(t => t.id === req.params.id); + if (!task) { + return res.status(404).json({ error: '任务未找到' }); + } + } else { + const [rows] = await pool.execute('SELECT * FROM cron_tasks WHERE id = ?', [req.params.id]); + if (rows.length === 0) { + return res.status(404).json({ error: '任务未找到' }); + } + task = formatCronTask(rows[0]); + } + + // 执行 HTTP 请求 + const options = { + method: task.method || 'GET', + headers: parseHeaders(task.headers) + }; + + if (task.body && ['POST', 'PUT', 'PATCH'].includes(task.method)) { + options.body = task.body; + } + + const response = await fetch(task.url, options); + const now = new Date(); + const nextRun = calculateNextRun(task.cron); + + if (!pool) { + task.lastRun = now.toLocaleString('zh-CN'); + task.runCount = (task.runCount || 0) + 1; + task.nextRun = nextRun; + return res.json({ + success: response.ok, + status: response.status, + lastRun: task.lastRun, + nextRun: task.nextRun, + runCount: task.runCount + }); + } + + await pool.execute( + 'UPDATE cron_tasks SET last_run = ?, next_run = ?, run_count = run_count + 1 WHERE id = ?', + [now, nextRun, req.params.id] + ); + + res.json({ + success: response.ok, + status: response.status, + lastRun: now.toLocaleString('zh-CN'), + nextRun, + runCount: task.runCount + 1 + }); + } catch (error) { + console.error('执行任务失败:', error); + res.status(500).json({ error: '执行任务失败: ' + error.message }); + } +}); + +function formatCronTask(row) { + if (!row) return null; + + return { + id: row.id, + name: row.name, + cron: row.cron, + url: row.url, + method: row.method, + headers: row.headers, + body: row.body, + enabled: Boolean(row.enabled), + lastRun: row.last_run ? row.last_run.toLocaleString('zh-CN') : null, + nextRun: row.next_run ? row.next_run.toLocaleString('zh-CN') : null, + runCount: row.run_count || 0 + }; +} + +function parseHeaders(headers) { + if (!headers) return {}; + if (typeof headers === 'object') return headers; + try { + return JSON.parse(headers); + } catch { + return {}; + } +} + +function calculateNextRun(cron) { + const parts = cron.trim().split(/\s+/); + if (parts.length < 5) return null; + + const now = new Date(); + const next = new Date(now); + + const minute = parts[0]; + const hour = parts[1]; + + if (minute === '*') { + next.setMinutes(now.getMinutes() + 1); + } else if (minute.includes('/')) { + const step = parseInt(minute.split('/')[1]); + next.setMinutes(Math.ceil(now.getMinutes() / step) * step); + } else { + next.setMinutes(parseInt(minute)); + if (next <= now) next.setHours(next.getHours() + 1); + } + + if (hour !== '*') { + next.setHours(parseInt(hour), 0, 0, 0); + if (next <= now) next.setDate(next.getDate() + 1); + } + + return next; +} + +module.exports = router; \ No newline at end of file diff --git a/server/src/routes/posts.js b/server/src/routes/posts.js new file mode 100644 index 0000000..8b507b5 --- /dev/null +++ b/server/src/routes/posts.js @@ -0,0 +1,188 @@ +const express = require('express'); +const router = express.Router(); +const { getPool } = require('../config/database'); +const memoryStore = require('../config/memoryStore'); + +// 格式化日期为 YYYY-MM-DD HH:mm:ss +function formatDate(date) { + if (!date) return ''; + const d = new Date(date); + if (isNaN(d.getTime())) return date; + const pad = n => n.toString().padStart(2, '0'); + return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`; +} + +// 获取所有文章 - 优先使用预热缓存 +router.get('/', async (req, res) => { + try { + const pool = getPool(); + + if (!pool) { + return res.json(memoryStore.posts); + } + + // 优先返回缓存数据(已预热) + if (memoryStore.posts && memoryStore.posts.length > 0) { + return res.json(memoryStore.posts.map(p => ({ ...p, date: formatDate(p.date) }))); + } + + const [rows] = await pool.execute('SELECT * FROM posts ORDER BY date DESC'); + const formatted = rows.map(r => ({ ...r, date: formatDate(r.date) })); + // 更新缓存 + memoryStore.posts = rows; + res.json(formatted); + } catch (error) { + console.error('获取文章列表失败:', error); + res.json(memoryStore.posts || []); + } +}); + +// 获取单篇文章 +router.get('/:id', async (req, res) => { + try { + const pool = getPool(); + const id = Number(req.params.id); + + if (!pool) { + const post = memoryStore.posts.find(p => p.id === id); + return post ? res.json({ ...post, date: formatDate(post.date) }) : res.status(404).json({ error: '文章未找到' }); + } + + // 先在缓存中查找 + if (memoryStore.posts && memoryStore.posts.length > 0) { + const cached = memoryStore.posts.find(p => p.id === id); + if (cached) { + return res.json({ ...cached, date: formatDate(cached.date) }); + } + } + + const [rows] = await pool.execute('SELECT * FROM posts WHERE id = ?', [id]); + if (rows.length === 0) { + return res.status(404).json({ error: '文章未找到' }); + } + res.json({ ...rows[0], date: formatDate(rows[0].date) }); + } catch (error) { + console.error('获取文章失败:', error); + const post = memoryStore.posts.find(p => p.id === Number(req.params.id)); + post ? res.json({ ...post, date: formatDate(post.date) }) : res.status(404).json({ error: '文章未找到' }); + } +}); + +// 创建文章 +router.post('/', async (req, res) => { + try { + const { title, date, excerpt, content } = req.body; + + if (!title || !date) { + return res.status(400).json({ error: '标题和日期是必填项' }); + } + + const pool = getPool(); + + if (!pool) { + const newPost = { + id: memoryStore.posts.length + 1, + title, + date, + excerpt: excerpt || '', + content: content || '' + }; + memoryStore.posts.unshift(newPost); + return res.status(201).json({ ...newPost, date: formatDate(newPost.date) }); + } + + const [result] = await pool.execute( + 'INSERT INTO posts (title, date, excerpt, content) VALUES (?, ?, ?, ?)', + [title, date, excerpt || '', content || ''] + ); + + const [rows] = await pool.execute('SELECT * FROM posts WHERE id = ?', [result.insertId]); + const newPost = rows[0]; + + // 同步更新缓存 + if (memoryStore.posts) { + memoryStore.posts.unshift(newPost); + } + + res.status(201).json({ ...newPost, date: formatDate(newPost.date) }); + } catch (error) { + console.error('创建文章失败:', error); + res.status(500).json({ error: '创建文章失败' }); + } +}); + +// 更新文章 +router.put('/:id', async (req, res) => { + try { + const { title, date, excerpt, content } = req.body; + const pool = getPool(); + const id = Number(req.params.id); + + if (!pool) { + const index = memoryStore.posts.findIndex(p => p.id === id); + if (index === -1) { + return res.status(404).json({ error: '文章未找到' }); + } + memoryStore.posts[index] = { ...memoryStore.posts[index], title, date, excerpt, content }; + return res.json({ ...memoryStore.posts[index], date: formatDate(memoryStore.posts[index].date) }); + } + + await pool.execute( + 'UPDATE posts SET title = ?, date = ?, excerpt = ?, content = ? WHERE id = ?', + [title, date, excerpt || '', content || '', id] + ); + + const [rows] = await pool.execute('SELECT * FROM posts WHERE id = ?', [id]); + if (rows.length === 0) { + return res.status(404).json({ error: '文章未找到' }); + } + const updated = rows[0]; + + // 同步更新缓存 + if (memoryStore.posts) { + const index = memoryStore.posts.findIndex(p => p.id === id); + if (index !== -1) { + memoryStore.posts[index] = updated; + } + } + + res.json({ ...updated, date: formatDate(updated.date) }); + } catch (error) { + console.error('更新文章失败:', error); + res.status(500).json({ error: '更新文章失败' }); + } +}); + +// 删除文章 +router.delete('/:id', async (req, res) => { + try { + const pool = getPool(); + const id = Number(req.params.id); + + if (!pool) { + const index = memoryStore.posts.findIndex(p => p.id === id); + if (index === -1) { + return res.status(404).json({ error: '文章未找到' }); + } + memoryStore.posts.splice(index, 1); + return res.status(204).send(); + } + + const [result] = await pool.execute('DELETE FROM posts WHERE id = ?', [id]); + if (result.affectedRows === 0) { + return res.status(404).json({ error: '文章未找到' }); + } + + // 同步更新缓存 + if (memoryStore.posts) { + memoryStore.posts = memoryStore.posts.filter(p => p.id !== id); + } + + res.status(204).send(); + } catch (error) { + console.error('删除文章失败:', error); + res.status(500).json({ error: '删除文章失败' }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/server/src/routes/settings.js b/server/src/routes/settings.js new file mode 100644 index 0000000..7907a0b --- /dev/null +++ b/server/src/routes/settings.js @@ -0,0 +1,216 @@ +const express = require('express'); +const router = express.Router(); +const { getPool } = require('../config/database'); +const memoryStore = require('../config/memoryStore'); +const rustfs = require('../config/rustfs'); + +// 生成唯一文件名 +function generateKey(prefix, id) { + const timestamp = Date.now(); + const random = Math.random().toString(36).substring(2, 8); + return `${prefix}/${timestamp}-${random}-${id}`; +} + +// base64 数据解码为 Buffer +function decodeBase64(dataUrl) { + if (!dataUrl || !dataUrl.startsWith('data:')) { + return null; + } + const matches = dataUrl.match(/^data:([^;]+);base64,(.+)$/); + if (!matches) return null; + return { + mimeType: matches[1], + data: Buffer.from(matches[2], 'base64') + }; +} + +// 获取设置 - 优先使用预热缓存 +router.get('/', async (req, res) => { + try { + const pool = getPool(); + + if (!pool) { + return res.json(memoryStore.settings); + } + + // 优先返回缓存数据 + if (memoryStore.settings && memoryStore.settings.bgType) { + return res.json(memoryStore.settings); + } + + const [rows] = await pool.execute('SELECT * FROM settings WHERE id = 1'); + if (rows.length === 0) { + return res.json(memoryStore.settings); + } + + const formatted = formatSettings(rows[0]); + memoryStore.settings = formatted; + res.json(formatted); + } catch (error) { + console.error('获取设置失败:', error.message); + res.json(memoryStore.settings); + } +}); + +// 上传单张图片到 RUSTFS +router.post('/upload-image', async (req, res) => { + try { + const { imageData, type } = req.body; // type: 'background' | 'icon' | 'gallery' + + if (!imageData || !imageData.startsWith('data:')) { + return res.status(400).json({ error: '无效的图片数据' }); + } + + const decoded = decodeBase64(imageData); + if (!decoded) { + return res.status(400).json({ error: '图片解码失败' }); + } + + const id = Date.now().toString(); + const prefix = type || 'images'; + const key = generateKey(prefix, id); + const url = await rustfs.uploadFile(decoded.data, key, decoded.mimeType); + + console.log(`✅ 图片上传成功: ${url}`); + + res.json({ url, id }); + } catch (error) { + console.error('图片上传失败:', error); + res.status(500).json({ error: '图片上传失败' }); + } +}); + +// 批量上传图片(并行上传到 RUSTFS) +router.post('/upload-images', async (req, res) => { + try { + const { images, type } = req.body; // images: [{id, data}] + + if (!Array.isArray(images) || images.length === 0) { + return res.json({ images: [] }); + } + + const prefix = type || 'images'; + + // 并行上传所有图片 + const uploadPromises = images.map(async (img) => { + try { + const decoded = decodeBase64(img.data); + if (!decoded) { + return { id: img.id, url: null, error: '解码失败' }; + } + + const key = generateKey(prefix, img.id); + const url = await rustfs.uploadFile(decoded.data, key, decoded.mimeType); + return { id: img.id, url }; + } catch (err) { + console.error(`图片 ${img.id} 上传失败:`, err); + return { id: img.id, url: null, error: err.message }; + } + }); + + const results = await Promise.all(uploadPromises); + res.json({ images: results }); + } catch (error) { + console.error('批量图片上传失败:', error); + res.status(500).json({ error: '图片上传失败' }); + } +}); + +// 更新设置 +router.put('/', async (req, res) => { + try { + // 兼容 camelCase 和 snake_case + const { + bg_type, bgType, + bg_color, bgColor, + bg_image, bgImage, + bg_opacity, bgOpacity, + language, + favicon, + uploaded_images, uploadedImages, + uploaded_icons, uploadedIcons + } = req.body; + + const pool = getPool(); + + if (!pool) { + Object.assign(memoryStore.settings, { + bg_type: bg_type || bgType, + bg_color: bg_color || bgColor, + bg_image: bg_image || bgImage, + bg_opacity: bg_opacity ?? bgOpacity, + language, + favicon, + uploaded_images: uploaded_images || uploadedImages, + uploaded_icons: uploaded_icons || uploadedIcons + }); + return res.json(memoryStore.settings); + } + + await pool.execute( + `UPDATE settings SET + bg_type = ?, bg_color = ?, bg_image = ?, bg_opacity = ?, + language = ?, favicon = ?, uploaded_images = ?, uploaded_icons = ? + WHERE id = 1`, + [ + bg_type || bgType || 'color', + bg_color || bgColor || '#f5f5f5', + bg_image || bgImage || '', + bg_opacity ?? bgOpacity ?? 1.00, + language || 'zh', + favicon || '', + prepareJSON(uploaded_images || uploadedImages), + prepareJSON(uploaded_icons || uploadedIcons) + ] + ); + + const [rows] = await pool.execute('SELECT * FROM settings WHERE id = 1'); + const formatted = formatSettings(rows[0]); + memoryStore.settings = formatted; + res.json(formatted); + } catch (error) { + console.error('更新设置失败:', error); + res.status(500).json({ error: '更新设置失败' }); + } +}); + +function formatSettings(row) { + if (!row) return memoryStore.settings; + + return { + bgType: row.bg_type, + bgColor: row.bg_color, + bgImage: row.bg_image, + bgOpacity: row.bg_opacity, + language: row.language, + favicon: row.favicon, + // uploadedImages 和 uploadedIcons 现在存储的是 {id, url} 数组 + uploadedImages: parseJSON(row.uploaded_images, []), + uploadedIcons: parseJSON(row.uploaded_icons, []) + }; +} + +function parseJSON(str, defaultValue) { + if (!str) return defaultValue; + if (typeof str === 'object') return str; + try { + return JSON.parse(str); + } catch { + return defaultValue; + } +} + +function prepareJSON(value) { + if (!value) return '[]'; + if (typeof value === 'string') { + try { + JSON.parse(value); + return value; + } catch { + return JSON.stringify(value); + } + } + return JSON.stringify(value); +} + +module.exports = router; diff --git a/server/src/scripts/addIndexes.js b/server/src/scripts/addIndexes.js new file mode 100644 index 0000000..5c1a840 --- /dev/null +++ b/server/src/scripts/addIndexes.js @@ -0,0 +1,49 @@ +/** + * 数据库索引迁移脚本 + * 为已存在的表添加索引,提升查询性能 + * 运行方式: node src/scripts/addIndexes.js + */ +require('dotenv').config(); +const mysql = require('mysql2/promise'); + +const config = { + host: process.env.DB_HOST, + port: process.env.DB_PORT || 3306, + user: process.env.DB_USER || 'root', + password: process.env.DB_PASSWORD || '', + database: process.env.DB_NAME || 'jnote' +}; + +async function migrate() { + let connection; + + try { + console.log('🔌 正在连接数据库...'); + connection = await mysql.createConnection(config); + console.log('✅ 数据库连接成功'); + + // 为 posts 表的 date 字段添加索引 + console.log('📝 正在为 posts.date 添加索引...'); + try { + await connection.query('CREATE INDEX idx_posts_date ON posts (date DESC)'); + console.log('✅ idx_posts_date 索引创建成功'); + } catch (error) { + if (error.code === 'ER_DUP_KEYNAME') { + console.log('ℹ️ idx_posts_date 索引已存在,跳过'); + } else { + throw error; + } + } + + console.log('\n🎉 索引迁移完成!'); + } catch (error) { + console.error('❌ 索引迁移失败:', error.message); + process.exit(1); + } finally { + if (connection) { + await connection.end(); + } + } +} + +migrate(); diff --git a/server/src/scripts/checkDb.js b/server/src/scripts/checkDb.js new file mode 100644 index 0000000..44391d0 --- /dev/null +++ b/server/src/scripts/checkDb.js @@ -0,0 +1,74 @@ +/** + * 数据库诊断脚本 + * 检查数据库中的实际数据 + * 运行方式: node src/scripts/checkDb.js + */ +require('dotenv').config(); +const mysql = require('mysql2/promise'); + +const config = { + host: process.env.DB_HOST, + port: process.env.DB_PORT || 3306, + user: process.env.DB_USER || 'root', + password: process.env.DB_PASSWORD || '', + database: process.env.DB_NAME || 'jnote' +}; + +async function check() { + let connection; + + try { + console.log('🔌 正在连接数据库...\n'); + connection = await mysql.createConnection(config); + console.log('✅ 数据库连接成功\n'); + + // 检查表结构 + console.log('📋 表结构检查:'); + const [tables] = await connection.query('SHOW TABLES'); + console.log('现有表:', tables.map(t => Object.values(t)[0]).join(', ')); + + // 检查 settings 表结构和数据 + console.log('\n📊 settings 表数据:'); + try { + const [settingsRows] = await connection.query('SELECT * FROM settings WHERE id = 1'); + if (settingsRows.length === 0) { + console.log('settings 表为空或无数据'); + } else { + const row = settingsRows[0]; + console.log(' id:', row.id); + console.log(' bg_type:', row.bg_type); + console.log(' bg_color:', row.bg_color); + console.log(' bg_image:', row.bg_image ? `[base64, 长度: ${row.bg_image.length}]` : '(空)'); + console.log(' bg_opacity:', row.bg_opacity); + console.log(' language:', row.language); + console.log(' favicon:', row.favicon ? `[base64, 长度: ${row.favicon.length}]` : '(空)'); + console.log(' uploaded_images:', row.uploaded_images); + console.log(' uploaded_icons:', row.uploaded_icons); + console.log(' uploaded_images 类型:', typeof row.uploaded_images); + console.log(' uploaded_icons 类型:', typeof row.uploaded_icons); + } + } catch (error) { + console.log('settings 表查询失败:', error.message); + } + + // 检查 posts 数量 + console.log('\n📝 posts 数量:'); + try { + const [postCount] = await connection.query('SELECT COUNT(*) as count FROM posts'); + console.log('文章总数:', postCount[0].count); + } catch (error) { + console.log('posts 表查询失败:', error.message); + } + + console.log('\n✅ 诊断完成'); + } catch (error) { + console.error('❌ 诊断失败:', error.message); + process.exit(1); + } finally { + if (connection) { + await connection.end(); + } + } +} + +check(); diff --git a/server/src/scripts/initDb.js b/server/src/scripts/initDb.js new file mode 100644 index 0000000..122b648 --- /dev/null +++ b/server/src/scripts/initDb.js @@ -0,0 +1,165 @@ +/** + * 数据库初始化脚本 + * 运行方式: node src/scripts/initDb.js + */ +require('dotenv').config(); +const mysql = require('mysql2/promise'); + +const config = { + host: process.env.DB_HOST, + port: process.env.DB_PORT || 3306, + user: process.env.DB_USER || 'root', + password: process.env.DB_PASSWORD || '', + charset: 'utf8mb4' +}; + +const DB_NAME = process.env.DB_NAME || 'jnote'; + +async function initDatabase() { + let connection; + + try { + console.log('🔌 正在连接数据库...'); + connection = await mysql.createConnection(config); + console.log('✅ 数据库连接成功'); + + // 创建数据库 + console.log(`📦 正在创建数据库 ${DB_NAME}...`); + await connection.query(`CREATE DATABASE IF NOT EXISTS \`${DB_NAME}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci`); + console.log(`✅ 数据库 ${DB_NAME} 创建成功`); + + // 使用数据库 + await connection.query(`USE \`${DB_NAME}\``); + + // 创建 posts 表 - content 改为 MEDIUMTEXT + console.log('📝 正在创建 posts 表...'); + await connection.query(` + CREATE TABLE IF NOT EXISTS posts ( + id INT AUTO_INCREMENT PRIMARY KEY, + title VARCHAR(255) NOT NULL, + date DATE NOT NULL, + excerpt TEXT, + content MEDIUMTEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + INDEX idx_posts_date (date DESC) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci + `); + console.log('✅ posts 表创建成功'); + + // 创建 about 表 - 使用 JSON 类型 + console.log('📋 正在创建 about 表...'); + await connection.query(` + CREATE TABLE IF NOT EXISTS about ( + id INT PRIMARY KEY DEFAULT 1, + title VARCHAR(255) DEFAULT '关于我', + intro TEXT, + blog TEXT, + tech TEXT, + features JSON, + contact JSON, + filing_number VARCHAR(100), + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci + `); + console.log('✅ about 表创建成功'); + + // 创建 settings 表 - 使用 JSON 类型存储图片列表 + console.log('⚙️ 正在创建 settings 表...'); + await connection.query(` + CREATE TABLE IF NOT EXISTS settings ( + id INT PRIMARY KEY DEFAULT 1, + bg_type VARCHAR(20) DEFAULT 'color', + bg_color VARCHAR(20) DEFAULT '#f5f5f5', + bg_image TEXT, + bg_opacity DECIMAL(3,2) DEFAULT 1.00, + language VARCHAR(10) DEFAULT 'zh', + favicon TEXT, + uploaded_images JSON, + uploaded_icons JSON, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci + `); + console.log('✅ settings 表创建成功'); + + // 创建 cron_tasks 表 + console.log('⏰ 正在创建 cron_tasks 表...'); + await connection.query(` + CREATE TABLE IF NOT EXISTS cron_tasks ( + id VARCHAR(50) PRIMARY KEY, + name VARCHAR(255) NOT NULL, + cron VARCHAR(50) NOT NULL, + url VARCHAR(500) NOT NULL, + method VARCHAR(20) DEFAULT 'GET', + headers TEXT, + body TEXT, + enabled TINYINT(1) DEFAULT 1, + last_run DATETIME, + next_run DATETIME, + run_count INT DEFAULT 0, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci + `); + console.log('✅ cron_tasks 表创建成功'); + + // 初始化默认数据 + console.log('📄 正在初始化默认数据...'); + + // 初始化 about 默认数据 + await connection.query(` + INSERT INTO about (id, title, intro, blog, tech, features, contact, filing_number) + VALUES (1, '关于我', '你好!我是一名热爱技术开发的开发者。', '这个博客用于分享我在学习和工作中的一些心得体会。', + 'Vue / Vue 3, JavaScript / TypeScript, Node.js, Vite, Pinia, Vue Router', + '["定时任务系统 - 支持 Cron表达式的自动化任务管理", "自定义背景 - 支持纯色和图片背景,可调节透明度", "多语言支持 - 中英文切换", "自定义图标 - 上传本地图片作为网站图标"]', + '{"email": "example@email.com", "github": "github.com/yourusername"}', + '桂ICP备2022004108号-1') + ON DUPLICATE KEY UPDATE id=id + `); + console.log('✅ about 默认数据初始化成功'); + + // 初始化 settings 默认数据 + await connection.query(` + INSERT INTO settings (id, bg_type, bg_color, bg_opacity, language) + VALUES (1, 'color', '#f5f5f5', 1.00, 'zh') + ON DUPLICATE KEY UPDATE id=id + `); + console.log('✅ settings 默认数据初始化成功'); + + // 初始化示例文章 + const samplePosts = [ + ['欢迎来到我的编程学习记录', '2026-06-01', '这是我的第一篇文章,欢迎大家来访!', '这是我的第一篇文章,欢迎大家来访!在这里我会分享一些技术心得和生活感悟。希望大家喜欢这里的内容,有任何问题欢迎留言交流。'], + ['Vue 3 组合式 API 入门', '2026-06-02', '探索 Vue 3 的组合式 API,感受更好的代码组织方式。', 'Vue 3 引入了组合式 API,这是一种全新的代码组织方式。通过 setup 函数和响应式 API,我们可以更灵活地组织组件逻辑,提高代码的可复用性和可维护性。\n\n主要特点:\n1. 更好的逻辑复用\n2. 更灵活的代码组织\n3. 更好的 TypeScript 支持'], + ['静态网站生成器选型', '2026-06-03', '对比常见的静态网站生成器,帮助你选择合适的工具。', '选择一个合适的静态网站生成器需要考虑多个因素:\n\n1. Hexo - 简单易用,主题丰富\n2. Jekyll - GitHub Pages 原生支持,社区活跃\n3. Hugo - 构建速度极快\n4. VuePress / VitePress - 基于 Vue,适合技术文档\n\n本博客使用 Vue 3 + Vite 构建,兼具现代特性和开发体验。'], + ['优雅地使用 Pinia 管理状态', '2026-06-04', 'Pinia 是 Vue 3 推荐的状态管理方案,本篇介绍其基本用法。', 'Pinia 是 Vue 官方推荐的新一代状态管理库,相比 Vuex 更加轻量和直观。\n\n核心概念:\n- Store - 存储状态的地方\n- Getters - 类似 computed 的状态计算\n- Actions - 处理异步逻辑或修改状态'], + ['CSS Grid 布局实战技巧', '2026-06-05', '深入探索 CSS Grid,让页面布局变得轻而易举。', 'CSS Grid 是现代 CSS 布局的重要组成部分,比 Flexbox 更适合二维布局场景。\n\n基础用法:\n.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }\n\n常用场景:\n1. 相册网格 - 自动填充列数\n2. 圣杯布局 - 经典三栏布局\n3. 响应式卡片 - 自动换行适配'], + ['用 Git 工作流提升团队协作效率', '2026-06-06', 'GitFlow vs trunk-based development,选对工作流事半功倍。', '良好的 Git 工作流能让团队协作更加顺畅。常见的工作流模型:\n\n1. GitFlow - 分支模型清晰,适合发布周期稳定的项目\n2. trunk-based development - 主干开发,快速迭代\n3. fork workflow - 开源项目首选,隔离性强\n\n小团队推荐使用简化 GitFlow:main + develop + feature 分支。'], + ['JavaScript 事件循环机制详解', '2026-06-07', '理解 Event Loop、宏任务与微任务,告别异步编程困惑。', '事件循环是 JavaScript 异步编程的核心机制。\n\n执行顺序:\n1. 同步代码优先执行\n2. 微任务(Promise、MutationObserver)\n3. 宏任务(setTimeout、setInterval、setImmediate)\n\n示例:\nconsole.log(\'1\');\nsetTimeout(() => console.log(\'2\'), 0);\nPromise.resolve().then(() => console.log(\'3\'));\nconsole.log(\'4\');\n\n输出顺序:1, 4, 3, 2'], + ['我的开发环境配置分享', '2026-06-08', 'VS Code + Zsh + Tmux,打造高效开发终端。', '工欲善其事,必先利其器。分享我的开发环境配置:\n\n编辑器:\n- VS Code + Vim 插件\n- Tokyo Night 主题\n- Fira Code 字体 + 连字\n\n终端:\n- iTerm2 (macOS) / Windows Terminal\n- Oh My Zsh\n- Tmux 会话管理\n\n版本管理:\n- Git + delta 美化 diff\n- lazygit 终端 UI'], + ['从零搭建一个 CLI 工具', '2026-06-09', '使用 Node.js 和 commander.js 快速构建命令行工具。', '命令行工具是提升开发效率的利器。使用 Node.js 可以快速构建:\n\n初始化项目:\nnpm init -y\nnpm install commander inquirer\n\n核心代码:\nconst { program } = require(\'commander\');\nprogram.version(\'1.0.0\');\nprogram.option(\'-n, --name \', \'项目名称\');\nprogram.parse(process.argv);\n\n发布到 npm:\nnpm publish --access public'], + ['为什么我喜欢深夜编程', '2026-06-10', '安静、专注、不被打扰,深夜是程序员的黄金时段。', '深夜编程的独特魅力:\n\n1. 绝对安静 - 无人打扰,思路连贯\n2. 效率翻倍 - 深度工作状态\n3. 问题解决 - 复杂 bug 往往在这时候被攻破\n\n当然,也要适度。注意休息,保护眼睛,第二天才能持续输出。\n\n推荐配合:黑咖啡 + 轻音乐 + 舒适的降噪耳机。'] + ]; + + for (const post of samplePosts) { + await connection.query( + 'INSERT INTO posts (title, date, excerpt, content) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE title=title', + post + ); + } + console.log('✅ 示例文章初始化成功(共10篇)'); + + console.log('\n🎉 数据库初始化完成!'); + console.log(`📖 数据库名: ${DB_NAME}`); + console.log('📋 数据表: posts, about, settings, cron_tasks'); + + } catch (error) { + console.error('❌ 数据库初始化失败:', error.message); + process.exit(1); + } finally { + if (connection) { + await connection.end(); + } + } +} + +initDatabase(); \ No newline at end of file diff --git a/server/src/scripts/migrateColumns.js b/server/src/scripts/migrateColumns.js new file mode 100644 index 0000000..17c5cf6 --- /dev/null +++ b/server/src/scripts/migrateColumns.js @@ -0,0 +1,49 @@ +/** + * 数据库字段扩展脚本 + * 将 TEXT 改为 LONGTEXT 以支持大图片 + */ +require('dotenv').config(); +const mysql = require('mysql2/promise'); + +const config = { + host: process.env.DB_HOST, + port: process.env.DB_PORT || 3306, + user: process.env.DB_USER || 'root', + password: process.env.DB_PASSWORD || '', + database: process.env.DB_NAME || 'jnote' +}; + +async function migrate() { + let connection; + + try { + console.log('🔌 正在连接数据库...'); + connection = await mysql.createConnection(config); + console.log('✅ 数据库连接成功'); + + console.log('📝 正在修改 settings 表字段...'); + + await connection.query('ALTER TABLE settings MODIFY COLUMN bg_image LONGTEXT'); + console.log('✅ bg_image 改为 LONGTEXT'); + + await connection.query('ALTER TABLE settings MODIFY COLUMN favicon LONGTEXT'); + console.log('✅ favicon 改为 LONGTEXT'); + + await connection.query('ALTER TABLE settings MODIFY COLUMN uploaded_images LONGTEXT'); + console.log('✅ uploaded_images 改为 LONGTEXT'); + + await connection.query('ALTER TABLE settings MODIFY COLUMN uploaded_icons LONGTEXT'); + console.log('✅ uploaded_icons 改为 LONGTEXT'); + + console.log('\n🎉 字段扩展完成!'); + } catch (error) { + console.error('❌ 扩展失败:', error.message); + process.exit(1); + } finally { + if (connection) { + await connection.end(); + } + } +} + +migrate(); \ No newline at end of file diff --git a/server/src/scripts/migrateStorage.js b/server/src/scripts/migrateStorage.js new file mode 100644 index 0000000..3f7a763 --- /dev/null +++ b/server/src/scripts/migrateStorage.js @@ -0,0 +1,115 @@ +/** + * 数据存储结构迁移脚本 + * 将 posts.content 升级为 MEDIUMTEXT,about 和 settings 的 JSON 字段类型优化 + * 运行方式: node src/scripts/migrateStorage.js + */ +require('dotenv').config(); +const mysql = require('mysql2/promise'); + +const config = { + host: process.env.DB_HOST, + port: process.env.DB_PORT || 3306, + user: process.env.DB_USER || 'root', + password: process.env.DB_PASSWORD || '', + database: process.env.DB_NAME || 'jnote' +}; + +async function migrate() { + let connection; + + try { + console.log('🔌 正在连接数据库...'); + connection = await mysql.createConnection(config); + console.log('✅ 数据库连接成功'); + + // 1. 将 posts.content 升级为 MEDIUMTEXT + console.log('📝 正在升级 posts.content 为 MEDIUMTEXT...'); + try { + await connection.query('ALTER TABLE posts MODIFY COLUMN content MEDIUMTEXT'); + console.log('✅ posts.content 已升级为 MEDIUMTEXT'); + } catch (error) { + if (error.code === 'ER_BAD_FIELD_ERROR') { + console.log('ℹ️ posts.content 已是 MEDIUMTEXT 或不存在,跳过'); + } else { + throw error; + } + } + + // 2. 将 about.features 改为 JSON 类型 + console.log('📋 正在将 about.features 迁移为 JSON 类型...'); + try { + await connection.query('ALTER TABLE about MODIFY COLUMN features JSON'); + console.log('✅ about.features 已改为 JSON 类型'); + } catch (error) { + if (error.code === 'ER_BAD_FIELD_ERROR') { + console.log('ℹ️ about.features 字段不存在,跳过'); + } else { + console.log('⚠️ about.features 迁移失败:', error.message); + } + } + + // 3. 将 about.contact 改为 JSON 类型 + console.log('📋 正在将 about.contact 迁移为 JSON 类型...'); + try { + await connection.query('ALTER TABLE about MODIFY COLUMN contact JSON'); + console.log('✅ about.contact 已改为 JSON 类型'); + } catch (error) { + if (error.code === 'ER_BAD_FIELD_ERROR') { + console.log('ℹ️ about.contact 字段不存在,跳过'); + } else { + console.log('⚠️ about.contact 迁移失败:', error.message); + } + } + + // 4. 将 settings.uploaded_images 改为 JSON 类型 + console.log('⚙️ 正在将 settings.uploaded_images 迁移为 JSON 类型...'); + try { + await connection.query('ALTER TABLE settings MODIFY COLUMN uploaded_images JSON'); + console.log('✅ settings.uploaded_images 已改为 JSON 类型'); + } catch (error) { + if (error.code === 'ER_BAD_FIELD_ERROR') { + console.log('ℹ️ settings.uploaded_images 字段不存在,跳过'); + } else { + console.log('⚠️ settings.uploaded_images 迁移失败:', error.message); + } + } + + // 5. 将 settings.uploaded_icons 改为 JSON 类型 + console.log('⚙️ 正在将 settings.uploaded_icons 迁移为 JSON 类型...'); + try { + await connection.query('ALTER TABLE settings MODIFY COLUMN uploaded_icons JSON'); + console.log('✅ settings.uploaded_icons 已改为 JSON 类型'); + } catch (error) { + if (error.code === 'ER_BAD_FIELD_ERROR') { + console.log('ℹ️ settings.uploaded_icons 字段不存在,跳过'); + } else { + console.log('⚠️ settings.uploaded_icons 迁移失败:', error.message); + } + } + + // 6. 添加 posts.date 索引 + console.log('📊 正在添加 posts.date 索引...'); + try { + await connection.query('CREATE INDEX idx_posts_date ON posts (date DESC)'); + console.log('✅ idx_posts_date 索引创建成功'); + } catch (error) { + if (error.code === 'ER_DUP_KEYNAME') { + console.log('ℹ️ idx_posts_date 索引已存在,跳过'); + } else { + throw error; + } + } + + console.log('\n🎉 存储结构迁移完成!'); + console.log('\n建议:考虑将图片等大文件存储到文件服务器,而非数据库。'); + } catch (error) { + console.error('❌ 迁移失败:', error.message); + process.exit(1); + } finally { + if (connection) { + await connection.end(); + } + } +} + +migrate(); diff --git a/server/start.js b/server/start.js new file mode 100644 index 0000000..d012558 --- /dev/null +++ b/server/start.js @@ -0,0 +1,134 @@ +/** + * JNote 后端启动脚本 + * 跨平台兼容 Windows 和 Linux + */ + +const { spawn, execSync } = require('child_process'); +const fs = require('fs'); +const path = require('path'); +const os = require('os'); + +const scriptDir = __dirname; +process.chdir(scriptDir); + +const APP_NAME = 'jnote-api'; +const isWindows = os.platform() === 'win32'; + +function log(msg) { + console.log(`[Start] ${msg}`); +} + +function loadEnv() { + const envFile = path.join(scriptDir, '.env'); + if (!fs.existsSync(envFile)) { + log('⚠️ 未找到 .env 文件'); + return; + } + + const content = fs.readFileSync(envFile, 'utf8'); + content.split('\n').forEach(line => { + line = line.trim(); + if (!line || line.startsWith('#')) return; + const idx = line.indexOf('='); + if (idx > 0) { + const key = line.substring(0, idx).trim(); + let value = line.substring(idx + 1).trim(); + if ((value.startsWith('"') && value.endsWith('"')) || + (value.startsWith("'") && value.endsWith("'"))) { + value = value.slice(1, -1); + } + process.env[key] = value; + } + }); +} + +function getExePath() { + const possibleNames = isWindows + ? ['jnote-api.exe', 'jnote-api'] + : ['jnote-api', 'jnote-api.exe']; + + for (const name of possibleNames) { + const p = path.join(scriptDir, name); + if (fs.existsSync(p)) return p; + } + return null; +} + +function startWithPM2(exePath) { + log('🚀 使用 PM2 启动...'); + + try { + execSync('pm2 --version', { stdio: 'ignore' }); + } catch { + log('📦 安装 PM2...'); + execSync('npm install -g pm2', { cwd: scriptDir, stdio: 'inherit' }); + } + + try { + execSync(`pm2 stop ${APP_NAME}`, { stdio: 'ignore' }); + execSync(`pm2 delete ${APP_NAME}`, { stdio: 'ignore' }); + } catch {} + + spawn('pm2', ['start', exePath, '--name', APP_NAME], { + cwd: scriptDir, + stdio: 'inherit', + shell: true + }); + + setTimeout(() => { + try { execSync('pm2 save', { stdio: 'ignore' }); } catch {} + }, 2000); + + log('✅ 服务已启动'); + log(' 状态: pm2 status'); + log(' 日志: pm2 logs jnote-api'); +} + +function startDirect(exePath) { + log('🚀 直接启动服务...'); + log(` 端口: ${process.env.PORT || 3000}`); + log(''); + + if (!isWindows) { + fs.chmodSync(exePath, 0o755); + } + + spawn(exePath, [], { + cwd: scriptDir, + stdio: 'inherit', + env: process.env + }); +} + +function main() { + console.log('========================================='); + console.log(' JNote 后端启动脚本'); + console.log(` 平台: ${isWindows ? 'Windows' : 'Linux'}`); + console.log('========================================='); + + loadEnv(); + + const exe = getExePath(); + if (!exe) { + console.error('❌ 错误: 未找到 jnote-api 可执行文件'); + console.error(` 请确保可执行文件与本脚本在同一目录下: ${scriptDir}`); + console.error(''); + console.error(' Linux 应有: jnote-api'); + console.error(' Windows 应有: jnote-api.exe'); + console.error(''); + console.error(' 如果还没有打包,请先运行: node build.js'); + process.exit(1); + } + + log(`✓ 找到: ${path.basename(exe)}`); + + // 优先使用 PM2 + try { + execSync('pm2 --version', { stdio: 'ignore' }); + startWithPM2(exe); + } catch { + startDirect(exe); + } +} + +main(); \ No newline at end of file diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..96dc38d --- /dev/null +++ b/src/App.vue @@ -0,0 +1,85 @@ + + + + + \ No newline at end of file diff --git a/src/assets/base.css b/src/assets/base.css new file mode 100644 index 0000000..a51d575 --- /dev/null +++ b/src/assets/base.css @@ -0,0 +1,80 @@ +/* 颜色调色板 */ +:root { + --vt-c-white: #ffffff; + --vt-c-white-soft: #f8f8f8; + --vt-c-white-mute: #f2f2f2; + + --vt-c-black: #181818; + --vt-c-black-soft: #222222; + --vt-c-black-mute: #282828; + + --vt-c-indigo: #2c3e50; + + --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); + --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); + --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); + --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); + + --vt-c-text-light-1: var(--vt-c-indigo); + --vt-c-text-light-2: rgba(60, 60, 60, 0.66); + --vt-c-text-dark-1: var(--vt-c-white); + --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); +} + +/* 语义化颜色变量 */ +:root { + --color-background: var(--vt-c-white); + --color-background-soft: var(--vt-c-white-soft); + --color-background-mute: var(--vt-c-white-mute); + + --color-border: var(--vt-c-divider-light-2); + --color-border-hover: var(--vt-c-divider-light-1); + + --color-heading: var(--vt-c-text-light-1); + --color-text: var(--vt-c-text-light-1); + + --color-primary: #42b883; +} + +@media (prefers-color-scheme: dark) { + :root { + --color-background: var(--vt-c-black); + --color-background-soft: var(--vt-c-black-soft); + --color-background-mute: var(--vt-c-black-mute); + + --color-border: var(--vt-c-divider-dark-2); + --color-border-hover: var(--vt-c-divider-dark-1); + + --color-heading: var(--vt-c-text-dark-1); + --color-text: var(--vt-c-text-dark-2); + + --color-primary: #42b883; + } +} + +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + position: relative; + font-weight: normal; +} + +body { + min-height: 100vh; + color: var(--color-text); + background: var(--color-background); + transition: color 0.5s, background-color 0.5s; + line-height: 1.6; + font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, + Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; + font-size: 15px; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +#app { + min-height: 100vh; +} \ No newline at end of file diff --git a/src/assets/logo.svg b/src/assets/logo.svg new file mode 100644 index 0000000..bc826fe --- /dev/null +++ b/src/assets/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/PostList.vue b/src/components/PostList.vue new file mode 100644 index 0000000..e7240ef --- /dev/null +++ b/src/components/PostList.vue @@ -0,0 +1,74 @@ + + + + + \ No newline at end of file diff --git a/src/components/SiteHeader.vue b/src/components/SiteHeader.vue new file mode 100644 index 0000000..8b4104b --- /dev/null +++ b/src/components/SiteHeader.vue @@ -0,0 +1,62 @@ + + + + + \ No newline at end of file diff --git a/src/composables/useI18n.js b/src/composables/useI18n.js new file mode 100644 index 0000000..db8b0db --- /dev/null +++ b/src/composables/useI18n.js @@ -0,0 +1,15 @@ +import { computed } from 'vue' +import { useSettingsStore } from '@/stores/settings' +import { t as translate } from '@/i18n' + +export function useI18n() { + const settings = useSettingsStore() + + const locale = computed(() => settings.language) + + function t(key) { + return translate(key, locale.value) + } + + return { t, locale } +} \ No newline at end of file diff --git a/src/i18n/index.js b/src/i18n/index.js new file mode 100644 index 0000000..a92ca96 --- /dev/null +++ b/src/i18n/index.js @@ -0,0 +1,269 @@ +export const messages = { + zh: { + nav: { + articles: '文章', + about: '关于', + cron: '定时任务', + settings: '设置' + }, + home: { + title: '我的编程学习记录', + empty: '暂无文章', + loading: '加载中...', + newPost: '新建文章' + }, + about: { + title: '关于我', + intro: '你好!我是一名热爱技术开发的开发者。', + blog: '这个博客用于分享我在学习和工作中的一些心得体会。', + tech: '技术栈', + features: '功能特点', + feature1: '定时任务系统 - 支持 Cron表达式的自动化任务管理', + feature2: '自定义背景 - 支持纯色和图片背景,可调节透明度', + feature3: '多语言支持 - 中英文切换', + feature4: '自定义图标 - 上传本地图片作为网站图标', + contact: '联系方式', + contactDesc: '如果你有任何问题或建议,欢迎通过以下方式联系我:', + filingNumber: '桂ICP备2022004108号-1' + }, + settings: { + title: '设置', + language: '语言设置', + interfaceLang: '界面语言', + background: '背景设置', + bgType: '背景类型', + solid: '纯色', + image: '图片', + bgColor: '背景颜色', + bgImage: '背景图片', + opacity: '背景透明度', + preview: '预览', + uploadImage: '上传本地图片', + uploading: '上传中...', + localImage: '本地图片', + clear: '清除', + imageUrlPlaceholder: '或输入图片URL', + saved: '已保存', + siteIcon: '网站图标', + uploadIcon: '上传图标', + defaultIcon: '恢复默认', + myIcons: '我的图标库', + myImages: '我的图片库' + }, + serverConfig: { + title: '服务端配置', + database: '数据库配置', + rustfs: 'RUSTFS 对象存储', + server: '服务器配置', + dbHost: '主机', + dbPort: '端口', + dbUser: '用户名', + dbPassword: '密码', + dbName: '数据库名', + rustfsEndpoint: '端点地址', + rustfsRegion: '区域', + rustfsBucket: '存储桶', + rustfsAccessKey: '访问密钥', + rustfsSecretKey: '密钥', + serverPort: '端口', + passwordPlaceholder: '留空则不修改', + save: '保存配置', + saving: '保存中...', + saved: '配置已保存', + saveFailed: '保存失败', + restart: '重启服务', + restarting: '重启中...', + restartFailed: '重启失败', + confirmRestart: '确定要重启后端服务吗?', + loading: '加载中...' + }, + cron: { + title: '定时任务处理系统', + newTask: '新建任务', + editTask: '编辑任务', + usage: '使用说明', + cronFormat: 'Cron表达式格式:分 时 日 月 周,例如*/5 * * * * 表示每5分钟执行', + supportedSymbols: '支持的符号:*任意值,*/n每n个时间单位,,列表,-范围', + headersFormat: '请求头格式:JSON对象,例如 {"Content-Type": "application/json"}', + empty: '暂无定时任务,点击"新建任务"添加第一个任务', + disabled: '已禁用', + running: '执行中', + success: '成功', + error: '失败', + nextRun: '下次执行', + lastRun: '上次执行', + runCount: '累计执行', + executing: '执行中...', + runNow: '立即执行', + disable: '禁用', + enable: '启用', + edit: '编辑', + delete: '删除', + taskName: '任务名称', + taskNamePlaceholder: '例如:每隔5分钟同步数据', + cronExpression: 'Cron表达式', + cronHint: '分 时 日 月 周', + requestMethod: '请求方法', + requestURL: '请求URL', + requestHeaders: '请求头', + requestBody: '请求体', + enableTask: '启用任务', + cancel: '取消', + save: '保存' + }, + postEditor: { + newTitle: '新建文章', + editTitle: '编辑文章', + title: '标题', + date: '日期', + excerpt: '摘要', + excerptPlaceholder: '文章摘要(可选)', + content: '正文', + contentPlaceholder: '文章正文内容...', + save: '保存', + saving: '保存中...', + cancel: '取消', + titleRequired: '标题和日期是必填项', + saveFailed: '保存失败', + loadFailed: '加载文章失败' + } + }, + en: { + nav: { + articles: 'Articles', + about: 'About', + cron: 'Cron Jobs', + settings: 'Settings' + }, + home: { + title: 'My Programming Learning Blog', + empty: 'No articles yet', + loading: 'Loading...', + newPost: 'New Post' + }, + about: { + title: 'About Me', + intro: 'Hello! I am a developer passionate about technology.', + blog: 'This blog is for sharing my insights and experiences in learning and work.', + tech: 'Tech Stack', + features: 'Features', + feature1: 'Cron Job System - Automated task management with Cron expressions', + feature2: 'Custom Background - Solid color and image backgrounds with adjustable opacity', + feature3: 'Multi-language Support - Chinese and English switching', + feature4: 'Custom Icon - Upload local images as website icon', + contact: 'Contact', + contactDesc: 'If you have any questions or suggestions, feel free to contact me:', + filingNumber: '桂ICP备2022004108号-1' + }, + settings: { + title: 'Settings', + language: 'Language Settings', + interfaceLang: 'Interface Language', + background: 'Background Settings', + bgType: 'Background Type', + solid: 'Solid Color', + image: 'Image', + bgColor: 'Background Color', + bgImage: 'Background Image', + opacity: 'Background Opacity', + preview: 'Preview', + uploadImage: 'Upload Local Image', + uploading: 'Uploading...', + localImage: 'Local Image', + clear: 'Clear', + imageUrlPlaceholder: 'or enter image URL', + saved: 'Saved', + siteIcon: 'Site Icon', + uploadIcon: 'Upload Icon', + defaultIcon: 'Reset Default', + myIcons: 'My Icons', + myImages: 'My Images' + }, + serverConfig: { + title: 'Server Config', + database: 'Database', + rustfs: 'RUSTFS Object Storage', + server: 'Server', + dbHost: 'Host', + dbPort: 'Port', + dbUser: 'User', + dbPassword: 'Password', + dbName: 'Database', + rustfsEndpoint: 'Endpoint', + rustfsRegion: 'Region', + rustfsBucket: 'Bucket', + rustfsAccessKey: 'Access Key', + rustfsSecretKey: 'Secret Key', + serverPort: 'Port', + passwordPlaceholder: 'Leave empty to keep unchanged', + save: 'Save Config', + saving: 'Saving...', + saved: 'Config saved', + saveFailed: 'Save failed', + restart: 'Restart Server', + restarting: 'Restarting...', + restartFailed: 'Restart failed', + confirmRestart: 'Are you sure you want to restart the server?', + loading: 'Loading...' + }, + cron: { + title: 'Cron Job System', + newTask: 'New Task', + editTask: 'Edit Task', + usage: 'Usage Instructions', + cronFormat: 'Cron format: min hour day month week, e.g. */5 * * * * means every 5 minutes', + supportedSymbols: 'Supported symbols: * any value, */n every n units, , list, - range', + headersFormat: 'Headers format: JSON object, e.g. {"Content-Type": "application/json"}', + empty: 'No cron tasks yet. Click "New Task" to add your first task.', + disabled: 'Disabled', + running: 'Running', + success: 'Success', + error: 'Failed', + nextRun: 'Next Run', + lastRun: 'Last Run', + runCount: 'Run Count', + executing: 'Executing...', + runNow: 'Run Now', + disable: 'Disable', + enable: 'Enable', + edit: 'Edit', + delete: 'Delete', + taskName: 'Task Name', + taskNamePlaceholder: 'e.g., Sync data every 5 minutes', + cronExpression: 'Cron Expression', + cronHint: 'min hour day month week', + requestMethod: 'Request Method', + requestURL: 'Request URL', + requestHeaders: 'Request Headers', + requestBody: 'Request Body', + enableTask: 'Enable Task', + cancel: 'Cancel', + save: 'Save' + }, + postEditor: { + newTitle: 'New Post', + editTitle: 'Edit Post', + title: 'Title', + date: 'Date', + excerpt: 'Excerpt', + excerptPlaceholder: 'Post excerpt (optional)', + content: 'Content', + contentPlaceholder: 'Post content...', + save: 'Save', + saving: 'Saving...', + cancel: 'Cancel', + titleRequired: 'Title and date are required', + saveFailed: 'Save failed', + loadFailed: 'Failed to load post' + } + } +} + +export function t(key, locale = 'zh') { + const keys = key.split('.') + let value = messages[locale] + for (const k of keys) { + value = value?.[k] + } + return value || key +} \ No newline at end of file diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..fda1e6e --- /dev/null +++ b/src/main.js @@ -0,0 +1,12 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/src/router/index.js b/src/router/index.js new file mode 100644 index 0000000..281d099 --- /dev/null +++ b/src/router/index.js @@ -0,0 +1,51 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '@/views/HomeView.vue' +import PostDetail from '@/views/PostDetail.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/post/:id', + name: 'post', + component: PostDetail + }, + { + path: '/about', + name: 'about', + component: () => import('@/views/AboutView.vue') + }, + { + path: '/cron', + name: 'cron', + component: () => import('@/views/CronView.vue') + }, + { + path: '/settings', + name: 'settings', + component: () => import('@/views/SettingsView.vue') + }, + { + path: '/server-config', + name: 'server-config', + component: () => import('@/views/ServerConfigView.vue') + }, + { + path: '/post/new', + name: 'post-new', + component: () => import('@/views/PostEditorView.vue') + }, + { + path: '/post/edit/:id', + name: 'post-edit', + component: () => import('@/views/PostEditorView.vue') + } + ] +}) + +export default router \ No newline at end of file diff --git a/src/services/api.js b/src/services/api.js new file mode 100644 index 0000000..9a2dd3f --- /dev/null +++ b/src/services/api.js @@ -0,0 +1,69 @@ +// API 服务层 +// 开发环境通过 vite.config.js 代理到后端 +// 生产环境可配置 VITE_API_URL 环境变量 +const API_BASE = import.meta.env.VITE_API_URL || '/api'; + +async function request(endpoint, options = {}) { + const url = `${API_BASE}${endpoint}`; + + const config = { + headers: { + 'Content-Type': 'application/json', + ...options.headers + }, + ...options + }; + + try { + const response = await fetch(url, config); + const data = await response.json(); + + if (!response.ok) { + throw new Error(data.error || '请求失败'); + } + + return data; + } catch (error) { + console.error(`API Error [${endpoint}]:`, error); + throw error; + } +} + +export const api = { + // 文章 + getPosts: () => request('/posts'), + getPost: (id) => request(`/posts/${id}`), + createPost: (data) => request('/posts', { method: 'POST', body: JSON.stringify(data) }), + updatePost: (id, data) => request(`/posts/${id}`, { method: 'PUT', body: JSON.stringify(data) }), + deletePost: (id) => request(`/posts/${id}`, { method: 'DELETE' }), + + // 关于 + getAbout: () => request('/about'), + updateAbout: (data) => request('/about', { method: 'PUT', body: JSON.stringify(data) }), + + // 设置 + getSettings: () => request('/settings'), + updateSettings: (data) => request('/settings', { method: 'PUT', body: JSON.stringify(data) }), + + // 图片上传到 RUSTFS + uploadImage: (imageData, type) => request('/settings/upload-image', { + method: 'POST', + body: JSON.stringify({ imageData, type }) + }), + uploadImages: (images, type) => request('/settings/upload-images', { + method: 'POST', + body: JSON.stringify({ images, type }) + }), + + // 定时任务 + getCronTasks: () => request('/cron-tasks'), + createCronTask: (data) => request('/cron-tasks', { method: 'POST', body: JSON.stringify(data) }), + updateCronTask: (id, data) => request(`/cron-tasks/${id}`, { method: 'PUT', body: JSON.stringify(data) }), + deleteCronTask: (id) => request(`/cron-tasks/${id}`, { method: 'DELETE' }), + runCronTask: (id) => request(`/cron-tasks/${id}/run`, { method: 'POST' }), + + // 健康检查 + health: () => request('/health') +}; + +export default api; \ No newline at end of file diff --git a/src/stores/about.js b/src/stores/about.js new file mode 100644 index 0000000..f8d27bb --- /dev/null +++ b/src/stores/about.js @@ -0,0 +1,61 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { api } from '@/services/api' + +export const useAboutStore = defineStore('about', () => { + const title = ref('') + const intro = ref('') + const blog = ref('') + const tech = ref('') + const features = ref([]) + const contact = ref({}) + const filingNumber = ref('') + const loading = ref(false) + + async function loadAbout() { + loading.value = true + try { + const data = await api.getAbout() + title.value = data.title || '' + intro.value = data.intro || '' + blog.value = data.blog || '' + tech.value = data.tech || '' + features.value = data.featuresList || [] + contact.value = data.contactObj || {} + filingNumber.value = data.filing_number || '' + } catch (error) { + console.error('加载关于内容失败:', error) + } finally { + loading.value = false + } + } + + async function saveAbout(data) { + try { + await api.updateAbout(data) + title.value = data.title || title.value + intro.value = data.intro ?? intro.value + blog.value = data.blog ?? blog.value + tech.value = data.tech ?? tech.value + features.value = data.features ?? features.value + contact.value = data.contact ?? contact.value + filingNumber.value = data.filing_number ?? filingNumber.value + } catch (error) { + console.error('保存关于内容失败:', error) + throw error + } + } + + return { + title, + intro, + blog, + tech, + features, + contact, + filingNumber, + loading, + loadAbout, + saveAbout + } +}) \ No newline at end of file diff --git a/src/stores/cron.js b/src/stores/cron.js new file mode 100644 index 0000000..e4f6373 --- /dev/null +++ b/src/stores/cron.js @@ -0,0 +1,189 @@ +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' +import { api } from '@/services/api' + +export const useCronStore = defineStore('cron', () => { + const tasks = ref([]) + const loading = ref(false) + const error = ref(null) + + const runningTasks = computed(() => { + return tasks.value.filter(t => taskStatus.value[t.id] === 'running') + }) + + const taskStatus = ref({}) + + async function loadTasks() { + loading.value = true + error.value = null + try { + tasks.value = await api.getCronTasks() + } catch (err) { + error.value = err.message + console.error('加载定时任务失败:', err) + // 降级到 localStorage + const saved = localStorage.getItem('cron-tasks') + if (saved) { + try { + tasks.value = JSON.parse(saved) + } catch { + tasks.value = [] + } + } + } finally { + loading.value = false + } + } + + async function saveTasks() { + try { + // 同步到服务器 + for (const task of tasks.value) { + await api.updateCronTask(task.id, { + name: task.name, + cron: task.cron, + url: task.url, + method: task.method, + headers: task.headers, + body: task.body, + enabled: task.enabled + }) + } + } catch (err) { + console.warn('同步到服务器失败,保留在本地:', err.message) + // 备用 localStorage + try { + localStorage.setItem('cron-tasks', JSON.stringify(tasks.value)) + } catch (e) { + console.warn('localStorage 保存失败:', e) + } + } + } + + async function createTask(data) { + try { + const newTask = await api.createCronTask(data) + tasks.value.unshift(newTask) + return newTask + } catch (err) { + // 后备方案:本地创建 + const localTask = { + ...data, + id: Date.now().toString(), + lastRun: null, + nextRun: calculateNextRun(data.cron), + runCount: 0 + } + tasks.value.unshift(localTask) + localStorage.setItem('cron-tasks', JSON.stringify(tasks.value)) + return localTask + } + } + + async function updateTask(id, data) { + try { + const updated = await api.updateCronTask(id, data) + const index = tasks.value.findIndex(t => t.id === id) + if (index !== -1) { + tasks.value[index] = updated + } + return updated + } catch (err) { + const index = tasks.value.findIndex(t => t.id === id) + if (index !== -1) { + tasks.value[index] = { ...tasks.value[index], ...data } + } + localStorage.setItem('cron-tasks', JSON.stringify(tasks.value)) + return tasks.value[index] + } + } + + async function deleteTask(id) { + try { + await api.deleteCronTask(id) + tasks.value = tasks.value.filter(t => t.id !== id) + } catch (err) { + tasks.value = tasks.value.filter(t => t.id !== id) + localStorage.setItem('cron-tasks', JSON.stringify(tasks.value)) + } + } + + async function toggleTask(id) { + const task = tasks.value.find(t => t.id === id) + if (task) { + task.enabled = !task.enabled + await updateTask(id, { enabled: task.enabled }) + } + } + + async function executeTask(id) { + if (taskStatus.value[id] === 'running') return + + taskStatus.value[id] = 'running' + + try { + const result = await api.runCronTask(id) + const task = tasks.value.find(t => t.id === id) + if (task) { + task.lastRun = result.lastRun + task.nextRun = result.nextRun + task.runCount = result.runCount + } + taskStatus.value[id] = result.success ? 'success' : 'error' + + setTimeout(() => { + taskStatus.value[id] = null + }, 3000) + } catch (error) { + taskStatus.value[id] = 'error' + console.error('执行任务失败:', error) + + setTimeout(() => { + taskStatus.value[id] = null + }, 3000) + } + } + + function calculateNextRun(cron) { + const parts = cron.trim().split(/\s+/) + if (parts.length < 5) return null + + const now = new Date() + const next = new Date(now) + + const minute = parts[0] + const hour = parts[1] + + if (minute === '*') { + next.setMinutes(now.getMinutes() + 1) + } else if (minute.includes('/')) { + const step = parseInt(minute.split('/')[1]) + next.setMinutes(Math.ceil(now.getMinutes() / step) * step) + } else { + next.setMinutes(parseInt(minute)) + if (next <= now) next.setHours(next.getHours() + 1) + } + + if (hour !== '*') { + next.setHours(parseInt(hour), 0, 0, 0) + if (next <= now) next.setDate(next.getDate() + 1) + } + + return next + } + + return { + tasks, + loading, + error, + taskStatus, + runningTasks, + loadTasks, + createTask, + updateTask, + deleteTask, + toggleTask, + executeTask, + calculateNextRun + } +}) \ No newline at end of file diff --git a/src/stores/posts.js b/src/stores/posts.js new file mode 100644 index 0000000..d3d033e --- /dev/null +++ b/src/stores/posts.js @@ -0,0 +1,66 @@ +import { defineStore } from 'pinia' +import { api } from '@/services/api' + +export const usePostsStore = defineStore('posts', { + state: () => ({ + posts: [], + loading: false, + error: null + }), + + getters: { + getPostById: (state) => (id) => { + return state.posts.find(post => post.id === Number(id)) + } + }, + + actions: { + async fetchPosts() { + this.loading = true + this.error = null + try { + this.posts = await api.getPosts() + } catch (error) { + this.error = error.message + console.error('获取文章失败:', error) + } finally { + this.loading = false + } + }, + + async createPost(data) { + try { + const newPost = await api.createPost(data) + this.posts.unshift(newPost) + return newPost + } catch (error) { + this.error = error.message + throw error + } + }, + + async updatePost(id, data) { + try { + const updated = await api.updatePost(id, data) + const index = this.posts.findIndex(p => p.id === Number(id)) + if (index !== -1) { + this.posts[index] = updated + } + return updated + } catch (error) { + this.error = error.message + throw error + } + }, + + async deletePost(id) { + try { + await api.deletePost(id) + this.posts = this.posts.filter(p => p.id !== Number(id)) + } catch (error) { + this.error = error.message + throw error + } + } + } +}) \ No newline at end of file diff --git a/src/stores/settings.js b/src/stores/settings.js new file mode 100644 index 0000000..2b92159 --- /dev/null +++ b/src/stores/settings.js @@ -0,0 +1,263 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { api } from '@/services/api' + +export const useSettingsStore = defineStore('settings', () => { + const bgType = ref('color') + const bgColor = ref('#f5f5f5') + const bgImage = ref('') + const bgOpacity = ref(1) + const language = ref('zh') + const favicon = ref('') + // 现在存储 {id, url} 而不是 {id, data: base64} + const uploadedImages = ref([]) + const uploadedIcons = ref([]) + const loading = ref(false) + let initialized = false + + async function loadSettings() { + loading.value = true + try { + const data = await api.getSettings() + bgType.value = data.bgType || 'color' + bgColor.value = data.bgColor || '#f5f5f5' + bgImage.value = data.bgImage || '' + bgOpacity.value = data.bgOpacity ?? 1 + language.value = data.language || 'zh' + favicon.value = data.favicon || '' + uploadedImages.value = data.uploadedImages || [] + uploadedIcons.value = data.uploadedIcons || [] + applyFavicon(favicon.value) + initialized = true + } catch (error) { + console.error('加载设置失败:', error) + initialized = true + // 降级到 localStorage + const saved = localStorage.getItem('site-settings') + if (saved) { + try { + const settings = JSON.parse(saved) + bgType.value = settings.bgType || 'color' + bgColor.value = settings.bgColor || '#f5f5f5' + bgImage.value = settings.bgImage || '' + bgOpacity.value = settings.bgOpacity || 1 + language.value = settings.language || 'zh' + favicon.value = settings.favicon || '' + uploadedImages.value = settings.uploadedImages || [] + uploadedIcons.value = settings.uploadedIcons || [] + } catch { + // ignore + } + } + } finally { + loading.value = false + } + } + + async function saveSettings() { + if (!initialized) { + console.warn('saveSettings 跳过:还未初始化') + return + } + try { + await api.updateSettings({ + bgType: bgType.value, + bgColor: bgColor.value, + bgImage: bgImage.value, + bgOpacity: bgOpacity.value, + language: language.value, + favicon: favicon.value, + uploadedImages: uploadedImages.value, + uploadedIcons: uploadedIcons.value + }) + } catch (error) { + console.warn('保存到服务器失败:', error.message) + } + } + + // 上传图片到 RUSTFS,返回 {id, url} + async function uploadImageToRustfs(imageData, type = 'background') { + try { + const result = await api.uploadImage(imageData, type) + return { id: result.id, url: result.url } + } catch (error) { + console.error('图片上传失败:', error) + throw error + } + } + + // 批量上传图片到 RUSTFS + async function uploadImagesToRustfs(imageDataList, type = 'background') { + try { + const images = imageDataList.map((data, index) => ({ + id: `${Date.now()}-${index}`, + data + })) + const result = await api.uploadImages(images, type) + return result.images + } catch (error) { + console.error('批量图片上传失败:', error) + throw error + } + } + + // 添加单张图片(上传到 RUSTFS) + async function addUploadedImage(imageData) { + const result = await uploadImageToRustfs(imageData, 'background') + uploadedImages.value.push(result) + await saveSettings() + return result.id + } + + // 批量添加图片(不上传到服务器) + function addUploadedImagesBatchLocal(imageDataList) { + const baseId = Date.now() + const tempImages = imageDataList.map((imageData, index) => ({ + id: `${baseId}-${index}`, + data: imageData + })) + return tempImages + } + + // 批量上传图片 + async function addUploadedImagesBatch(imageDataList) { + const uploaded = await uploadImagesToRustfs(imageDataList, 'background') + for (const img of uploaded) { + if (img.url) { + uploadedImages.value.push({ id: img.id, url: img.url }) + } + } + await saveSettings() + } + + // 设置背景图片(使用 URL) + async function setBgImage(value) { + bgImage.value = value + await saveSettings() + } + + // 设置背景图片(上传 base64 后设置) + async function setBgImageFromData(imageData) { + const result = await uploadImageToRustfs(imageData, 'background') + bgImage.value = result.url + await saveSettings() + } + + function setBgType(value) { + bgType.value = value + saveSettings() + } + + function setBgColor(value) { + bgColor.value = value + saveSettings() + } + + function setBgOpacity(value) { + bgOpacity.value = value + saveSettings() + } + + function setLanguage(value) { + language.value = value + saveSettings() + } + + // 设置图标(上传到 RUSTFS) + async function setFaviconFromData(imageData) { + const result = await uploadImageToRustfs(imageData, 'icon') + favicon.value = result.url + applyFavicon(result.url) + await saveSettings() + } + + // 设置图标(使用已有 URL) + async function setFavicon(value) { + favicon.value = value + applyFavicon(value) + await saveSettings() + } + + // 添加图标到图标库(上传到 RUSTFS) + async function addUploadedIcon(imageData) { + const result = await uploadImageToRustfs(imageData, 'icon') + uploadedIcons.value.push(result) + await saveSettings() + return result.id + } + + // 批量添加图标 + async function addUploadedIconsBatch(imageDataList) { + const uploaded = await uploadImagesToRustfs(imageDataList, 'icon') + for (const icon of uploaded) { + if (icon.url) { + uploadedIcons.value.push({ id: icon.id, url: icon.url }) + } + } + await saveSettings() + } + + function removeUploadedImage(id) { + uploadedImages.value = uploadedImages.value.filter(img => img.id !== id) + // bgImage 现在是 URL,检查是否是被删除图片的 URL + const img = uploadedImages.value.find(img => img.url === bgImage.value) + if (!img && bgImage.value) { + // 当前背景图片被删除了,重置为默认 + bgImage.value = '' + } + saveSettings() + } + + function removeUploadedIcon(id) { + uploadedIcons.value = uploadedIcons.value.filter(icon => icon.id !== id) + // favicon 现在是 URL,检查是否是被删除图标的 URL + const icon = uploadedIcons.value.find(icon => icon.url === favicon.value) + if (!icon && favicon.value) { + favicon.value = '' + applyFavicon('') + } + saveSettings() + } + + function applyFavicon(value) { + const link = document.querySelector("link[rel='icon']") + if (link) { + if (value) { + link.href = value + } else { + link.href = '/favicon.ico' + } + } + } + + return { + bgType, + bgColor, + bgImage, + bgOpacity, + language, + favicon, + uploadedImages, + uploadedIcons, + loading, + initialized, + loadSettings, + saveSettings, + setBgImage, + setBgImageFromData, + setBgType, + setBgColor, + setBgOpacity, + setLanguage, + setFavicon, + setFaviconFromData, + addUploadedImage, + addUploadedImagesBatch, + addUploadedImagesBatchLocal, + removeUploadedImage, + addUploadedIcon, + addUploadedIconsBatch, + removeUploadedIcon, + applyFavicon + } +}) diff --git a/src/views/AboutView.vue b/src/views/AboutView.vue new file mode 100644 index 0000000..a7b5e61 --- /dev/null +++ b/src/views/AboutView.vue @@ -0,0 +1,93 @@ + + + + + \ No newline at end of file diff --git a/src/views/CronView.vue b/src/views/CronView.vue new file mode 100644 index 0000000..dd18fa2 --- /dev/null +++ b/src/views/CronView.vue @@ -0,0 +1,591 @@ + + + + + \ No newline at end of file diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue new file mode 100644 index 0000000..65bf9a1 --- /dev/null +++ b/src/views/HomeView.vue @@ -0,0 +1,79 @@ + + + + + \ No newline at end of file diff --git a/src/views/PostDetail.vue b/src/views/PostDetail.vue new file mode 100644 index 0000000..2dc3edb --- /dev/null +++ b/src/views/PostDetail.vue @@ -0,0 +1,240 @@ + + + + + + + \ No newline at end of file diff --git a/src/views/PostEditorView.vue b/src/views/PostEditorView.vue new file mode 100644 index 0000000..edf6803 --- /dev/null +++ b/src/views/PostEditorView.vue @@ -0,0 +1,215 @@ + + + + \ No newline at end of file diff --git a/src/views/ServerConfigView.vue b/src/views/ServerConfigView.vue new file mode 100644 index 0000000..2b1b8dd --- /dev/null +++ b/src/views/ServerConfigView.vue @@ -0,0 +1,275 @@ + + + + + \ No newline at end of file diff --git a/src/views/SettingsView.vue b/src/views/SettingsView.vue new file mode 100644 index 0000000..6be756c --- /dev/null +++ b/src/views/SettingsView.vue @@ -0,0 +1,771 @@ + + + + + \ No newline at end of file diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..4831a9b --- /dev/null +++ b/vite.config.js @@ -0,0 +1,36 @@ +import { fileURLToPath } from 'url' +import { defineConfig, loadEnv } from 'vite' +import vue from '@vitejs/plugin-vue' + +// Vite 配置 +export default defineConfig(({ mode }) => { + // 加载环境变量 + const env = loadEnv(mode, process.cwd(), '') + + return { + plugins: [vue()], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + }, + server: { + port: 5173, + proxy: { + '/api': { + // 本地开发模式:VITE_SERVER_URL 为空或本地地址时使用代理 + target: env.VITE_SERVER_URL || `http://localhost:${env.VITE_API_PORT || '3000'}`, + changeOrigin: true, + // 仅远程部署时改变 origin + configure: (proxy) => { + if (env.VITE_SERVER_URL && !env.VITE_SERVER_URL.includes('localhost')) { + proxy.on('proxyReq', (proxyReq) => { + proxyReq.setHeader('origin', env.VITE_SERVER_URL) + }) + } + } + } + } + } + } +}) \ No newline at end of file