From 14b61b23a222e72598b661e5341dde70b245a92c Mon Sep 17 00:00:00 2001 From: Awuqing <3184394176@qq.com> Date: Sun, 9 Aug 2026 19:42:02 +0800 Subject: [PATCH 1/2] =?UTF-8?q?chore(repo):=20=E5=AE=8C=E5=96=84=E4=BB=93?= =?UTF-8?q?=E5=BA=93=E7=BB=B4=E6=8A=A4=E4=B8=8E=E8=87=AA=E5=8A=A8=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 25 ++++++ .gitattributes | 15 ++++ .github/ISSUE_TEMPLATE/bug_report.md | 43 ++++++---- .github/ISSUE_TEMPLATE/config.yml | 6 +- .github/ISSUE_TEMPLATE/feature_request.md | 31 +++++-- .github/PULL_REQUEST_TEMPLATE.md | 57 ++++++++---- .github/SECURITY.md | 50 ++++++----- .github/dependabot.yml | 86 +++++++++++++++++++ .github/workflows/ci.yml | 36 ++++++-- .github/workflows/docs.yml | 31 +++++-- .github/workflows/release.yml | 75 ++++++++++++++-- .gitignore | 36 +++++++- .node-version | 1 + CONTRIBUTING.md | 27 +++--- Dockerfile | 2 +- Makefile | 29 ++++++- README.md | 2 + README.zh-CN.md | 2 + docs-site/docs/development/setup.md | 2 +- .../docs/getting-started/installation.md | 2 +- .../current/development/setup.md | 2 +- .../current/getting-started/installation.md | 2 +- docs-site/package-lock.json | 2 +- docs-site/package.json | 2 +- web/package-lock.json | 19 ++-- web/package.json | 8 +- web/tsconfig.json | 3 +- web/tsconfig.node.json | 2 +- web/tsconfig.node.tsbuildinfo | 1 - web/tsconfig.tsbuildinfo | 1 - web/vite.config.d.ts | 2 - web/vite.config.js | 32 ------- 32 files changed, 478 insertions(+), 156 deletions(-) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/dependabot.yml create mode 100644 .node-version delete mode 100644 web/tsconfig.node.tsbuildinfo delete mode 100644 web/tsconfig.tsbuildinfo delete mode 100644 web/vite.config.d.ts delete mode 100644 web/vite.config.js diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..16a4e00 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,25 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{go,mod,sum}] +indent_style = tab +indent_size = 4 + +[Makefile] +indent_style = tab + +[*.{js,jsx,ts,tsx,json,yml,yaml,css,scss,html,md,mdx}] +indent_style = space +indent_size = 2 + +[*.sh] +indent_style = space +indent_size = 4 + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..f11075d --- /dev/null +++ b/.gitattributes @@ -0,0 +1,15 @@ +* text=auto eol=lf + +*.bat text eol=crlf +*.cmd text eol=crlf + +*.gif binary +*.ico binary +*.jpg binary +*.jpeg binary +*.png binary +*.webp binary +*.woff binary +*.woff2 binary +*.gz binary +*.zip binary diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 34bd5d3..21ece1e 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,14 +1,14 @@ --- -name: "\U0001F41B Bug 报告" -about: "报告一个 Bug,帮助我们改进 BackupX" +name: "Bug 报告" +about: "提交可复现的缺陷报告" title: "[Bug] " labels: ["bug"] assignees: [] --- -## 描述 +## 问题描述 - + ## 复现步骤 @@ -18,26 +18,39 @@ assignees: [] ## 期望行为 - + ## 实际行为 - + ## 环境信息 -- **OS**: -- **Go 版本**: -- **Node.js 版本**: -- **浏览器**: -- **BackupX 版本**: +- BackupX 版本或提交: +- 部署方式(Docker、裸机、集群): +- 操作系统与架构: +- 数据库或备份类型: +- 浏览器版本(仅界面问题): +- 是否使用代理、私有 CA 或堡垒机: -## 相关日志 +## 最小配置 + + + +```yaml ``` - + +## 相关日志 + + + +```text + ``` -## 截图 +## 补充信息 + + - +请勿提交数据库文件、完整配置、备份数据、API Key、Agent Token、安装命令或未脱敏日志。安全漏洞请使用私密漏洞报告入口。 diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index f848beb..7e9eca9 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,5 @@ blank_issues_enabled: false contact_links: - - name: 💬 讨论区 / Discussions - url: https://github.com/Awuqing/GoogleDriverBackupEveryDay/discussions - about: 提问、讨论功能想法或分享使用经验 + - name: 安全漏洞 / Security vulnerability + url: https://github.com/Awuqing/BackupX/security/advisories/new + about: 请通过私密渠道报告安全问题,不要创建公开 Issue。 diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index b329fc7..dc14587 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,23 +1,36 @@ --- -name: "\U0001F680 功能请求" -about: "建议一个新功能或改进" +name: "功能请求" +about: "建议一个可落地的新功能或改进" title: "[Feature] " labels: ["enhancement"] assignees: [] --- -## 需求描述 +## 使用场景 - + -## 使用场景 +## 期望结果 + + + +## 建议方案 + + + +## 替代方案 + + + +## 兼容性与风险 - + -## 建议的解决方案 +## 验收标准 - +- [ ] +- [ ] ## 补充信息 - + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index df7d5e1..31625c7 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,29 +1,48 @@ -## Pull Request +## 变更说明 / Summary -### 变更类型 / Type of Change + -- [ ] 🐛 Bug 修复 (非破坏性变更) -- [ ] ✨ 新功能 (非破坏性变更) -- [ ] 💥 破坏性变更 (修复或功能导致现有功能变更) -- [ ] 📝 文档更新 -- [ ] ♻️ 代码重构 (不影响功能) -- [ ] ⚡ 性能优化 +## 变更类型 / Type of Change -### 描述 / Description +- [ ] 缺陷修复 +- [ ] 新功能 +- [ ] 破坏性变更 +- [ ] 性能优化 +- [ ] 重构或工程化 +- [ ] 文档更新 - +## 相关 Issue / Related Issue -### 相关 Issue / Related Issue + - +## 验证 / Validation -### 测试 / Testing + -- [ ] 后端测试通过 (`go test ./...`) -- [ ] 前端测试通过 (`npm run test`) -- [ ] 前端构建成功 (`npm run build`) -- [ ] 已在本地环境手动测试 +- [ ] 后端格式、静态检查与测试通过 +- [ ] 前端测试与生产构建通过 +- [ ] 文档类型检查与中英文生产构建通过 +- [ ] 配置、迁移或部署兼容性已验证 +- [ ] 已完成与变更范围相符的手动验证 -### 截图 / Screenshots +验证命令与结果: - +```text + +``` + +## 风险与回滚 / Risk and Rollback + + + +## 界面变更 / UI Changes + + + +## 提交前检查 / Checklist + +- [ ] 提交信息符合 Conventional Commits +- [ ] 未提交密钥、Token、真实配置、数据库或日志 +- [ ] 新行为已补充测试和中英文文档 +- [ ] 前端未使用 Emoji、渐变、阴影、独立字体或超过 4px 的圆角 +- [ ] 没有夹带与本 PR 无关的格式化或重构 diff --git a/.github/SECURITY.md b/.github/SECURITY.md index 27ede9b..1375c26 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -1,34 +1,40 @@ -# 安全漏洞披露政策 / Security Policy +# 安全策略 / Security Policy -## 支持的版本 / Supported Versions +## 支持范围 / Supported Versions -| Version | Supported | -|---------|--------------------| -| latest | ✅ | -| < latest | ❌ | +安全修复面向最新稳定版本和 `main` 分支。旧版本不会单独维护安全补丁;升级前请先阅读对应 Release Notes 和升级恢复文档。 -## 报告安全漏洞 / Reporting a Vulnerability +Security fixes target the latest stable release and the `main` branch. Older versions do not receive separate security patches. Review the release notes and upgrade documentation before updating. -如果您发现了安全漏洞,**请不要通过公开 Issue 报告**。 +| Version | Status | +|---------|--------| +| Latest stable release | Supported | +| `main` | Development support | +| Older releases | Unsupported | -请发送邮件至项目维护者,包含以下信息: +## 报告漏洞 / Reporting a Vulnerability -1. 漏洞描述 -2. 复现步骤 -3. 受影响的版本 -4. 可能的影响范围 +请勿通过公开 Issue、Discussion 或 Pull Request 披露安全漏洞。使用 GitHub 的[私密漏洞报告入口](https://github.com/Awuqing/BackupX/security/advisories/new)提交报告。 -我们会在 48 小时内确认收到并开始处理。 +Do not disclose vulnerabilities in a public Issue, Discussion, or Pull Request. Submit the report through GitHub's [private vulnerability reporting form](https://github.com/Awuqing/BackupX/security/advisories/new). ---- +报告应包含: -If you discover a security vulnerability, **please do NOT open a public issue**. +1. 受影响版本或提交; +2. 漏洞描述、攻击前提和影响范围; +3. 最小复现步骤或验证代码; +4. 已知缓解措施; +5. 希望使用的署名信息。 -Instead, email the project maintainer with the following details: +不要上传真实密钥、Token、备份数据、数据库或包含客户信息的日志。必要时请先脱敏,并使用最小化测试数据。 -1. Description of the vulnerability -2. Steps to reproduce -3. Affected versions -4. Potential impact +Do not upload real credentials, tokens, backup data, databases, or logs containing customer information. Redact sensitive values and use minimal test data. -We will acknowledge receipt within 48 hours and begin working on a fix. +## 处理流程 / Response Process + +- 维护者会尽快确认报告并进行初步分级; +- 修复期间请保持细节私密,避免影响仍未升级的部署; +- 修复发布后会在安全公告或 Release Notes 中说明受影响范围、缓解措施和升级版本; +- 披露时间由报告者与维护者协调确定。 + +The maintainer will acknowledge and triage the report as soon as practical. Details should remain private until a fix and coordinated disclosure are ready. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..ad7f801 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,86 @@ +version: 2 + +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + day: monday + time: "03:00" + timezone: Asia/Shanghai + open-pull-requests-limit: 5 + commit-message: + prefix: chore(deps) + groups: + github-actions: + patterns: + - "*" + + - package-ecosystem: gomod + directory: /server + schedule: + interval: weekly + day: monday + time: "03:10" + timezone: Asia/Shanghai + open-pull-requests-limit: 5 + commit-message: + prefix: chore(deps) + groups: + go-minor-and-patch: + patterns: + - "*" + update-types: + - minor + - patch + + - package-ecosystem: npm + directory: /web + schedule: + interval: weekly + day: monday + time: "03:20" + timezone: Asia/Shanghai + open-pull-requests-limit: 5 + commit-message: + prefix: chore(deps) + groups: + web-minor-and-patch: + patterns: + - "*" + update-types: + - minor + - patch + + - package-ecosystem: npm + directory: /docs-site + schedule: + interval: weekly + day: monday + time: "03:30" + timezone: Asia/Shanghai + open-pull-requests-limit: 5 + commit-message: + prefix: chore(deps) + groups: + docs-minor-and-patch: + patterns: + - "*" + update-types: + - minor + - patch + + - package-ecosystem: docker + directory: / + schedule: + interval: weekly + day: monday + time: "03:40" + timezone: Asia/Shanghai + open-pull-requests-limit: 5 + commit-message: + prefix: chore(deps) + groups: + container-images: + patterns: + - "*" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3924233..f1341b1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,18 +2,24 @@ name: CI on: push: - branches: [main, master] + branches: [main] pull_request: - branches: [main, master] + branches: [main] + workflow_dispatch: # 最小权限:构建/测试仅需读取仓库内容,显式声明以收敛默认的可写令牌。 permissions: contents: read +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: backend: name: Go Build & Test runs-on: ubuntu-latest + timeout-minutes: 20 steps: - uses: actions/checkout@v4 @@ -23,6 +29,23 @@ jobs: go-version: '1.25' cache-dependency-path: server/go.sum + - name: Verify modules + working-directory: server + run: go mod verify + + - name: Check formatting + working-directory: server + run: | + unformatted="$(gofmt -l .)" + if [ -n "$unformatted" ]; then + printf '%s\n' "$unformatted" + exit 1 + fi + + - name: Vet + working-directory: server + run: go vet ./... + - name: Build working-directory: server run: go build ./... @@ -34,13 +57,14 @@ jobs: frontend: name: React Build & Test runs-on: ubuntu-latest + timeout-minutes: 20 steps: - uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' cache: 'npm' cache-dependency-path: web/package-lock.json @@ -48,14 +72,10 @@ jobs: working-directory: web run: npm ci - - name: Type Check - working-directory: web - run: npx tsc --noEmit -p tsconfig.json - - name: Test working-directory: web run: npm run test - - name: Build + - name: Type Check & Build working-directory: web run: npm run build diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 16233a1..bb23ef7 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,9 +1,16 @@ name: Deploy Docs # 触发条件: -# - 推送 main 时,如果 docs-site/ 或站点相关 README 有变化 +# - PR 修改 docs-site/ 时执行类型检查和构建 +# - 推送 main 时构建并部署 GitHub Pages # - 手动触发(在 Actions 页面) on: + pull_request: + branches: + - main + paths: + - 'docs-site/**' + - '.github/workflows/docs.yml' push: branches: - main @@ -12,20 +19,20 @@ on: - '.github/workflows/docs.yml' workflow_dispatch: -# 允许写入 Pages,用于发布到 github.com/Awuqing/BackupX 的 Pages 站点 +# 默认只读;Pages 写权限仅授予部署任务。 permissions: contents: read - pages: write - id-token: write -# 同时只保留一个部署任务 +# 同一分支只保留最新一次构建,避免旧提交覆盖新结果。 concurrency: - group: pages-${{ github.ref }} + group: docs-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: build: + name: Build Docs runs-on: ubuntu-latest + timeout-minutes: 20 defaults: run: working-directory: docs-site @@ -36,24 +43,34 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' cache: 'npm' cache-dependency-path: docs-site/package-lock.json - name: Install dependencies run: npm ci + - name: Type check + run: npm run typecheck + - name: Build site run: npm run build - name: Upload artifact + if: github.event_name != 'pull_request' uses: actions/upload-pages-artifact@v3 with: path: docs-site/build deploy: + name: Deploy Docs + if: github.event_name != 'pull_request' needs: build runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + pages: write + id-token: write environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 342203a..8f00fc5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,25 +27,85 @@ on: type: string permissions: - contents: write - packages: write + contents: read # 统一版本号:tag 推送取 ref_name,手动触发取 inputs.version env: VERSION: ${{ github.event.inputs.version || github.ref_name }} +concurrency: + group: release-${{ github.ref }}-${{ github.event.inputs.version || 'tag' }} + cancel-in-progress: false + jobs: + # ─── Job 0: 校验版本与测试 ─── + verify: + name: Validate Release + runs-on: ubuntu-latest + timeout-minutes: 25 + steps: + - uses: actions/checkout@v4 + + - name: Validate release input + shell: bash + env: + RELEASE_VERSION: ${{ env.VERSION }} + RELEASE_EVENT: ${{ github.event_name }} + RELEASE_REF: ${{ github.ref }} + run: | + if [[ ! "$RELEASE_VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z][0-9A-Za-z.-]*)?$ ]]; then + echo "Version must be a SemVer tag such as v1.2.3 or v1.2.3-rc.1" + exit 1 + fi + if [[ "$RELEASE_EVENT" == "workflow_dispatch" && "$RELEASE_REF" != "refs/heads/main" ]]; then + echo "Manual releases must run from the main branch" + exit 1 + fi + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.25' + cache-dependency-path: server/go.sum + + - name: Verify backend + working-directory: server + run: | + go mod verify + unformatted="$(gofmt -l .)" + if [ -n "$unformatted" ]; then + printf '%s\n' "$unformatted" + exit 1 + fi + go vet ./... + go test ./... + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '24' + cache: 'npm' + cache-dependency-path: web/package-lock.json + + - name: Verify frontend + working-directory: web + run: | + npm ci + npm run test + # ─── Job 1: 构建前端 ─── build-web: name: Build Frontend + needs: verify runs-on: ubuntu-latest + timeout-minutes: 20 steps: - uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' cache: 'npm' cache-dependency-path: web/package-lock.json @@ -67,6 +127,9 @@ jobs: name: Build ${{ matrix.goarch }} needs: build-web runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + contents: write strategy: matrix: include: @@ -98,13 +161,13 @@ jobs: run: | go build \ -trimpath \ - -ldflags "-s -w -X main.version=${{ env.VERSION }}" \ + -ldflags "-s -w -X main.version=${VERSION}" \ -o ../backupx \ ./cmd/backupx - name: Package release run: | - ARCHIVE_NAME="backupx-${{ env.VERSION }}-${{ matrix.goos }}-${{ matrix.goarch }}" + ARCHIVE_NAME="backupx-${VERSION}-${{ matrix.goos }}-${{ matrix.goarch }}" mkdir -p "${ARCHIVE_NAME}" cp backupx "${ARCHIVE_NAME}/" cp -r web/dist "${ARCHIVE_NAME}/web" @@ -130,6 +193,7 @@ jobs: backupx-${{ env.VERSION }}-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz.sha256 backupx-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz backupx-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz.sha256 + fail_on_unmatched_files: true generate_release_notes: true # ─── Job 3: Docker 多架构 → Docker Hub ─── @@ -137,6 +201,7 @@ jobs: name: Build & Push Docker needs: build-web runs-on: ubuntu-latest + timeout-minutes: 45 steps: - uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index bfeb8e3..96dce16 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,38 @@ +# Dependencies web/node_modules/ +docs-site/node_modules/ + +# Build and test artifacts web/dist/ +docs-site/build/ +docs-site/.docusaurus/ server/bin/ -.claude/ \ No newline at end of file +coverage/ +*.out +*.tsbuildinfo +web/vite.config.js +web/vite.config.d.ts + +# Runtime data and local configuration +data/ +tmp/ +temp/ +*.db +*.db-shm +*.db-wal +*.log +.env +.env.* +!.env*.example + +# Editors, operating systems, and local tools +.idea/ +.vscode/ +.DS_Store +Thumbs.db +desktop.ini +*.swp +*.swo +*~ +.claude/ +.codex/ diff --git a/.node-version b/.node-version new file mode 100644 index 0000000..a45fd52 --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +24 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 80b4bc2..5443a40 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,8 +8,8 @@ Thanks for your interest in contributing to BackupX! This guide covers how to se ### 依赖 / Prerequisites - **Go** 1.25+(见 `server/go.mod`) -- **Node.js** 20+(CI 与 Docker 使用 Node 20) -- **npm** 9+ +- **Node.js** 24 LTS(见 `.node-version`,CI 与 Docker 使用同一主版本) +- **npm** 11+ ### 快速开始 / Quick Start @@ -17,6 +17,8 @@ Thanks for your interest in contributing to BackupX! This guide covers how to se ```bash git clone https://github.com/Awuqing/BackupX.git && cd BackupX +npm --prefix web ci +npm --prefix docs-site ci # 终端 1 —— 后端(默认 http://localhost:8340) make dev-server @@ -31,6 +33,7 @@ make dev-web make build # 同时构建后端与前端 make build-server # 仅后端 → server/bin/backupx make build-web # 仅前端 → web/dist +make build-docs # 仅文档站 → docs-site/build make docker # 构建 Docker 镜像 make docker-cn # 国内镜像源加速构建 ``` @@ -39,15 +42,17 @@ make docker-cn # 国内镜像源加速构建 ## 测试 / Testing -提交前请确保测试通过: +提交前应执行与 CI 一致的完整验证: ```bash -make test # 后端 + 前端全部测试 +make verify # 格式、依赖、静态检查、测试与三端构建 +make test # 仅后端 + 前端测试 make test-server # 仅后端:cd server && go test ./... make test-web # 仅前端:cd web && npm run test(vitest) +make check-docs # 文档类型检查 + 中英文站点构建 ``` -新增功能或修复缺陷时,请尽量补充对应测试。 +新增功能或修复缺陷时,请补充对应测试。文档变更也必须通过严格断链检查,不能只依赖合并后的 Pages 部署结果。 ## 提交信息规范 / Commit Messages @@ -82,7 +87,7 @@ docs: 补充 CONTRIBUTING 指南 1. **Fork** 仓库并从最新的 `main` 切出特性分支; 2. **开发**功能或修复,必要时补充测试; -3. **自测**:确保 `make test` 通过; +3. **自测**:确保 `make verify` 通过; 4. **提交**:使用上述 Conventional Commits(中文); 5. **推送**并对着 `main` 发起 PR。 @@ -91,15 +96,17 @@ docs: 补充 CONTRIBUTING 指南 - 清晰说明本 PR 做了什么; - 对新功能/修复,补充动机与背景; - 关联相关 Issue(如 `Closes #62`); -- 纯文档 PR 可不附测试。 +- 纯文档 PR 至少应附上 `make check-docs` 的结果。 > 请保持分支基于较新的 `main`:基线过旧的分支容易产生大范围冲突,难以评审与合入。 ## 编码规范 / Coding Conventions -- **Go**:所有错误必须处理(禁止 `_ = err`),日志使用项目已有库(`zap`),禁止 `fmt.Println`;提交前执行 `gofmt`。 -- **前端**:遵循项目 ESLint/Prettier/tsconfig 配置,不擅自引入新的 CSS 框架或 UI 库。 -- **包管理**:`web/` 使用 npm,请提交对应的 `package-lock.json`。 +- **Go**:遵循现有 handler → service → repository 分层;避免把连续业务流程拆成大量无复用价值的独立函数。所有错误必须处理,日志使用 `zap`,禁止 `fmt.Println`,提交前执行 `gofmt` 与 `go vet`。 +- **前端组件**:复用并组合现有组件,不在页面内复制同类交互逻辑,不擅自改变共享组件的基础样式,不引入新的 CSS 框架或 UI 库。 +- **前端视觉**:不使用 Emoji、渐变和 `box-shadow`;图标统一使用项目 SVG 图标组件;圆角为 0–4px;不引入独立字体,不用加粗字体制造层级,减少 Card,不使用数据左侧装饰竖线。 +- **包管理**:`web/` 与 `docs-site/` 均使用 npm;依赖变更必须同步提交对应的 `package-lock.json`。 +- **文档**:英文源文件与 `zh-CN` 翻译应同步维护;新增页面必须加入侧边栏并通过两种语言的生产构建。 ## License diff --git a/Dockerfile b/Dockerfile index 88299cb..73febfb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,7 @@ ARG USE_CHINA_MIRROR=false # ---- Stage 1: Build frontend ---- -FROM node:20-alpine AS web-builder +FROM node:24-alpine AS web-builder ARG USE_CHINA_MIRROR # 国内镜像:npm 使用淘宝源 diff --git a/Makefile b/Makefile index da55d5c..a5cefa8 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ -.PHONY: build dev test clean docker docker-cn +.PHONY: build build-server build-web build-docs dev-server dev-web \ + test test-server test-web check-docs format-check vet-server \ + verify verify-server verify-web verify-docs clean docker docker-cn # 自动获取版本号(从 git tag 或 commit hash) VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo dev) @@ -12,6 +14,9 @@ build-server: build-web: cd web && npm run build +build-docs: + cd docs-site && npm run build + # ── 开发模式(分别在两个终端运行)── dev-server: cd server && go run ./cmd/backupx @@ -28,6 +33,28 @@ test-server: test-web: cd web && npm run test +check-docs: + cd docs-site && npm run typecheck && npm run build + +format-check: + @unformatted="$$(gofmt -l server)"; \ + if [ -n "$$unformatted" ]; then \ + printf '%s\n' "$$unformatted"; \ + exit 1; \ + fi + +vet-server: + cd server && go mod verify && go vet ./... + +# ── 提交前完整验证 ── +verify: verify-server verify-web verify-docs + +verify-server: format-check vet-server test-server build-server + +verify-web: test-web build-web + +verify-docs: check-docs + # ── Docker 构建 ── docker: docker build --build-arg VERSION=$(VERSION) -t backupx:$(VERSION) -t backupx:latest . diff --git a/README.md b/README.md index 5fd3c63..b6e23b6 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@

Stars Release + CI + Docs Go React SQLite diff --git a/README.zh-CN.md b/README.zh-CN.md index 4ed8bcf..f7e368f 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -10,6 +10,8 @@

Stars Release + CI + Docs Go React SQLite diff --git a/docs-site/docs/development/setup.md b/docs-site/docs/development/setup.md index f6354b0..5531c0b 100644 --- a/docs-site/docs/development/setup.md +++ b/docs-site/docs/development/setup.md @@ -6,7 +6,7 @@ description: Get a BackupX dev environment running — backend, frontend, tests. # Development Setup -**Requirements:** Go ≥ 1.25, Node.js ≥ 20, npm. +**Requirements:** Go ≥ 1.25, Node.js 24 LTS, npm 11 or later. ## Clone & install diff --git a/docs-site/docs/getting-started/installation.md b/docs-site/docs/getting-started/installation.md index 8c34ff1..7c698c4 100644 --- a/docs-site/docs/getting-started/installation.md +++ b/docs-site/docs/getting-started/installation.md @@ -51,7 +51,7 @@ The installer: ## From source -Requires Go ≥ 1.25 and Node.js ≥ 20. +Requires Go ≥ 1.25, Node.js 24 LTS, and npm 11 or later. ```bash git clone https://github.com/Awuqing/BackupX.git && cd BackupX diff --git a/docs-site/i18n/zh-CN/docusaurus-plugin-content-docs/current/development/setup.md b/docs-site/i18n/zh-CN/docusaurus-plugin-content-docs/current/development/setup.md index 27ccc0d..769e5ac 100644 --- a/docs-site/i18n/zh-CN/docusaurus-plugin-content-docs/current/development/setup.md +++ b/docs-site/i18n/zh-CN/docusaurus-plugin-content-docs/current/development/setup.md @@ -6,7 +6,7 @@ description: 搭建 BackupX 本地开发环境 — 后端、前端、测试。 # 开发环境 -**环境要求:** Go ≥ 1.25,Node.js ≥ 20,npm。 +**环境要求:** Go ≥ 1.25、Node.js 24 LTS、npm 11 或更高版本。 ## 克隆与依赖 diff --git a/docs-site/i18n/zh-CN/docusaurus-plugin-content-docs/current/getting-started/installation.md b/docs-site/i18n/zh-CN/docusaurus-plugin-content-docs/current/getting-started/installation.md index ac7532a..71f6d57 100644 --- a/docs-site/i18n/zh-CN/docusaurus-plugin-content-docs/current/getting-started/installation.md +++ b/docs-site/i18n/zh-CN/docusaurus-plugin-content-docs/current/getting-started/installation.md @@ -51,7 +51,7 @@ sudo ./install.sh # 创建系统用户、安装到 /opt/backupx、配置 ## 从源码构建 -依赖:Go ≥ 1.25,Node.js ≥ 20。 +依赖:Go ≥ 1.25、Node.js 24 LTS、npm 11 或更高版本。 ```bash git clone https://github.com/Awuqing/BackupX.git && cd BackupX diff --git a/docs-site/package-lock.json b/docs-site/package-lock.json index ca8ea04..04e91b4 100644 --- a/docs-site/package-lock.json +++ b/docs-site/package-lock.json @@ -25,7 +25,7 @@ "typescript": "~6.0.2" }, "engines": { - "node": ">=20.0" + "node": ">=24.0" } }, "node_modules/@11ty/gray-matter": { diff --git a/docs-site/package.json b/docs-site/package.json index 13d50d6..a4cafc0 100644 --- a/docs-site/package.json +++ b/docs-site/package.json @@ -44,6 +44,6 @@ ] }, "engines": { - "node": ">=20.0" + "node": ">=24.0" } } diff --git a/web/package-lock.json b/web/package-lock.json index 06c1c20..fe4a986 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -23,7 +23,7 @@ "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.2.0", "@testing-library/user-event": "^14.6.1", - "@types/node": "^22.13.10", + "@types/node": "^24.13.3", "@types/react": "^18.3.20", "@types/react-dom": "^18.3.6", "@vitejs/plugin-react": "^4.3.4", @@ -31,6 +31,9 @@ "typescript": "^5.7.3", "vite": "^6.4.3", "vitest": "^3.2.7" + }, + "engines": { + "node": ">=24.0" } }, "node_modules/@adobe/css-tools": { @@ -1529,13 +1532,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.19.15", - "resolved": "https://registry.npmmirror.com/@types/node/-/node-22.19.15.tgz", - "integrity": "sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==", + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz", + "integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~7.18.0" } }, "node_modules/@types/prop-types": { @@ -3468,9 +3471,9 @@ } }, "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", "dev": true, "license": "MIT" }, diff --git a/web/package.json b/web/package.json index 40b14ac..0a5d107 100644 --- a/web/package.json +++ b/web/package.json @@ -3,9 +3,13 @@ "private": true, "version": "0.1.0", "type": "module", + "engines": { + "node": ">=24.0" + }, "scripts": { "dev": "vite", - "build": "tsc --noEmit -p tsconfig.json && vite build", + "typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig.node.json", + "build": "npm run typecheck && vite build", "preview": "vite preview", "test": "vitest run" }, @@ -25,7 +29,7 @@ "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.2.0", "@testing-library/user-event": "^14.6.1", - "@types/node": "^22.13.10", + "@types/node": "^24.13.3", "@types/react": "^18.3.20", "@types/react-dom": "^18.3.6", "@vitejs/plugin-react": "^4.3.4", diff --git a/web/tsconfig.json b/web/tsconfig.json index 05eda53..1e44244 100644 --- a/web/tsconfig.json +++ b/web/tsconfig.json @@ -29,6 +29,5 @@ "src/pages/login/page.tsx", "src/pages/system-info/page.tsx", "src/stores/auth.test.ts" - ], - "references": [{ "path": "./tsconfig.node.json" }] + ] } diff --git a/web/tsconfig.node.json b/web/tsconfig.node.json index c0a187b..f31fd36 100644 --- a/web/tsconfig.node.json +++ b/web/tsconfig.node.json @@ -1,11 +1,11 @@ { "compilerOptions": { - "composite": true, "target": "ES2020", "lib": ["ES2020", "DOM"], "module": "ESNext", "moduleResolution": "Bundler", "allowSyntheticDefaultImports": true, + "noEmit": true, "types": ["node"] }, "include": ["vite.config.ts"] diff --git a/web/tsconfig.node.tsbuildinfo b/web/tsconfig.node.tsbuildinfo deleted file mode 100644 index 52dc24c..0000000 --- a/web/tsconfig.node.tsbuildinfo +++ /dev/null @@ -1 +0,0 @@ -{"fileNames":["./node_modules/typescript/lib/lib.es5.d.ts","./node_modules/typescript/lib/lib.es2015.d.ts","./node_modules/typescript/lib/lib.es2016.d.ts","./node_modules/typescript/lib/lib.es2017.d.ts","./node_modules/typescript/lib/lib.es2018.d.ts","./node_modules/typescript/lib/lib.es2019.d.ts","./node_modules/typescript/lib/lib.es2020.d.ts","./node_modules/typescript/lib/lib.dom.d.ts","./node_modules/typescript/lib/lib.es2015.core.d.ts","./node_modules/typescript/lib/lib.es2015.collection.d.ts","./node_modules/typescript/lib/lib.es2015.generator.d.ts","./node_modules/typescript/lib/lib.es2015.iterable.d.ts","./node_modules/typescript/lib/lib.es2015.promise.d.ts","./node_modules/typescript/lib/lib.es2015.proxy.d.ts","./node_modules/typescript/lib/lib.es2015.reflect.d.ts","./node_modules/typescript/lib/lib.es2015.symbol.d.ts","./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","./node_modules/typescript/lib/lib.es2016.array.include.d.ts","./node_modules/typescript/lib/lib.es2016.intl.d.ts","./node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","./node_modules/typescript/lib/lib.es2017.date.d.ts","./node_modules/typescript/lib/lib.es2017.object.d.ts","./node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2017.string.d.ts","./node_modules/typescript/lib/lib.es2017.intl.d.ts","./node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","./node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","./node_modules/typescript/lib/lib.es2018.intl.d.ts","./node_modules/typescript/lib/lib.es2018.promise.d.ts","./node_modules/typescript/lib/lib.es2018.regexp.d.ts","./node_modules/typescript/lib/lib.es2019.array.d.ts","./node_modules/typescript/lib/lib.es2019.object.d.ts","./node_modules/typescript/lib/lib.es2019.string.d.ts","./node_modules/typescript/lib/lib.es2019.symbol.d.ts","./node_modules/typescript/lib/lib.es2019.intl.d.ts","./node_modules/typescript/lib/lib.es2020.bigint.d.ts","./node_modules/typescript/lib/lib.es2020.date.d.ts","./node_modules/typescript/lib/lib.es2020.promise.d.ts","./node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2020.string.d.ts","./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","./node_modules/typescript/lib/lib.es2020.intl.d.ts","./node_modules/typescript/lib/lib.es2020.number.d.ts","./node_modules/typescript/lib/lib.decorators.d.ts","./node_modules/typescript/lib/lib.decorators.legacy.d.ts","./node_modules/@vitest/spy/dist/index.d.ts","./node_modules/@vitest/pretty-format/dist/index.d.ts","./node_modules/@vitest/utils/dist/types.d.ts","./node_modules/@vitest/utils/dist/helpers.d.ts","./node_modules/tinyrainbow/dist/index-8b61d5bc.d.ts","./node_modules/tinyrainbow/dist/node.d.ts","./node_modules/@vitest/utils/dist/index.d.ts","./node_modules/@vitest/utils/dist/types.d-bcelap-c.d.ts","./node_modules/@vitest/utils/dist/diff.d.ts","./node_modules/@vitest/expect/dist/index.d.ts","./node_modules/@types/node/compatibility/disposable.d.ts","./node_modules/@types/node/compatibility/indexable.d.ts","./node_modules/@types/node/compatibility/iterators.d.ts","./node_modules/@types/node/compatibility/index.d.ts","./node_modules/@types/node/globals.typedarray.d.ts","./node_modules/@types/node/buffer.buffer.d.ts","./node_modules/@types/node/globals.d.ts","./node_modules/@types/node/web-globals/abortcontroller.d.ts","./node_modules/@types/node/web-globals/domexception.d.ts","./node_modules/@types/node/web-globals/events.d.ts","./node_modules/undici-types/header.d.ts","./node_modules/undici-types/readable.d.ts","./node_modules/undici-types/file.d.ts","./node_modules/undici-types/fetch.d.ts","./node_modules/undici-types/formdata.d.ts","./node_modules/undici-types/connector.d.ts","./node_modules/undici-types/client.d.ts","./node_modules/undici-types/errors.d.ts","./node_modules/undici-types/dispatcher.d.ts","./node_modules/undici-types/global-dispatcher.d.ts","./node_modules/undici-types/global-origin.d.ts","./node_modules/undici-types/pool-stats.d.ts","./node_modules/undici-types/pool.d.ts","./node_modules/undici-types/handlers.d.ts","./node_modules/undici-types/balanced-pool.d.ts","./node_modules/undici-types/agent.d.ts","./node_modules/undici-types/mock-interceptor.d.ts","./node_modules/undici-types/mock-agent.d.ts","./node_modules/undici-types/mock-client.d.ts","./node_modules/undici-types/mock-pool.d.ts","./node_modules/undici-types/mock-errors.d.ts","./node_modules/undici-types/proxy-agent.d.ts","./node_modules/undici-types/env-http-proxy-agent.d.ts","./node_modules/undici-types/retry-handler.d.ts","./node_modules/undici-types/retry-agent.d.ts","./node_modules/undici-types/api.d.ts","./node_modules/undici-types/interceptors.d.ts","./node_modules/undici-types/util.d.ts","./node_modules/undici-types/cookies.d.ts","./node_modules/undici-types/patch.d.ts","./node_modules/undici-types/websocket.d.ts","./node_modules/undici-types/eventsource.d.ts","./node_modules/undici-types/filereader.d.ts","./node_modules/undici-types/diagnostics-channel.d.ts","./node_modules/undici-types/content-type.d.ts","./node_modules/undici-types/cache.d.ts","./node_modules/undici-types/index.d.ts","./node_modules/@types/node/web-globals/fetch.d.ts","./node_modules/@types/node/web-globals/navigator.d.ts","./node_modules/@types/node/web-globals/storage.d.ts","./node_modules/@types/node/assert.d.ts","./node_modules/@types/node/assert/strict.d.ts","./node_modules/@types/node/async_hooks.d.ts","./node_modules/@types/node/buffer.d.ts","./node_modules/@types/node/child_process.d.ts","./node_modules/@types/node/cluster.d.ts","./node_modules/@types/node/console.d.ts","./node_modules/@types/node/constants.d.ts","./node_modules/@types/node/crypto.d.ts","./node_modules/@types/node/dgram.d.ts","./node_modules/@types/node/diagnostics_channel.d.ts","./node_modules/@types/node/dns.d.ts","./node_modules/@types/node/dns/promises.d.ts","./node_modules/@types/node/domain.d.ts","./node_modules/@types/node/events.d.ts","./node_modules/@types/node/fs.d.ts","./node_modules/@types/node/fs/promises.d.ts","./node_modules/@types/node/http.d.ts","./node_modules/@types/node/http2.d.ts","./node_modules/@types/node/https.d.ts","./node_modules/@types/node/inspector.d.ts","./node_modules/@types/node/inspector.generated.d.ts","./node_modules/@types/node/module.d.ts","./node_modules/@types/node/net.d.ts","./node_modules/@types/node/os.d.ts","./node_modules/@types/node/path.d.ts","./node_modules/@types/node/perf_hooks.d.ts","./node_modules/@types/node/process.d.ts","./node_modules/@types/node/punycode.d.ts","./node_modules/@types/node/querystring.d.ts","./node_modules/@types/node/readline.d.ts","./node_modules/@types/node/readline/promises.d.ts","./node_modules/@types/node/repl.d.ts","./node_modules/@types/node/sea.d.ts","./node_modules/@types/node/sqlite.d.ts","./node_modules/@types/node/stream.d.ts","./node_modules/@types/node/stream/promises.d.ts","./node_modules/@types/node/stream/consumers.d.ts","./node_modules/@types/node/stream/web.d.ts","./node_modules/@types/node/string_decoder.d.ts","./node_modules/@types/node/test.d.ts","./node_modules/@types/node/timers.d.ts","./node_modules/@types/node/timers/promises.d.ts","./node_modules/@types/node/tls.d.ts","./node_modules/@types/node/trace_events.d.ts","./node_modules/@types/node/tty.d.ts","./node_modules/@types/node/url.d.ts","./node_modules/@types/node/util.d.ts","./node_modules/@types/node/v8.d.ts","./node_modules/@types/node/vm.d.ts","./node_modules/@types/node/wasi.d.ts","./node_modules/@types/node/worker_threads.d.ts","./node_modules/@types/node/zlib.d.ts","./node_modules/@types/node/index.d.ts","./node_modules/@types/estree/index.d.ts","./node_modules/rollup/dist/rollup.d.ts","./node_modules/rollup/dist/parseast.d.ts","./node_modules/vite/types/hmrpayload.d.ts","./node_modules/vite/types/customevent.d.ts","./node_modules/vite/types/hot.d.ts","./node_modules/vite/dist/node/modulerunnertransport.d-dj_me5sf.d.ts","./node_modules/vite/dist/node/module-runner.d.ts","./node_modules/esbuild/lib/main.d.ts","./node_modules/source-map-js/source-map.d.ts","./node_modules/postcss/lib/previous-map.d.ts","./node_modules/postcss/lib/input.d.ts","./node_modules/postcss/lib/css-syntax-error.d.ts","./node_modules/postcss/lib/declaration.d.ts","./node_modules/postcss/lib/root.d.ts","./node_modules/postcss/lib/warning.d.ts","./node_modules/postcss/lib/lazy-result.d.ts","./node_modules/postcss/lib/no-work-result.d.ts","./node_modules/postcss/lib/processor.d.ts","./node_modules/postcss/lib/result.d.ts","./node_modules/postcss/lib/document.d.ts","./node_modules/postcss/lib/rule.d.ts","./node_modules/postcss/lib/node.d.ts","./node_modules/postcss/lib/comment.d.ts","./node_modules/postcss/lib/container.d.ts","./node_modules/postcss/lib/at-rule.d.ts","./node_modules/postcss/lib/list.d.ts","./node_modules/postcss/lib/postcss.d.ts","./node_modules/postcss/lib/postcss.d.mts","./node_modules/vite/types/internal/lightningcssoptions.d.ts","./node_modules/vite/types/internal/csspreprocessoroptions.d.ts","./node_modules/vite/types/importglob.d.ts","./node_modules/vite/types/metadata.d.ts","./node_modules/vite/dist/node/index.d.ts","./node_modules/@vitest/runner/dist/tasks.d-cksck4of.d.ts","./node_modules/@vitest/runner/dist/types.d.ts","./node_modules/@vitest/utils/dist/error.d.ts","./node_modules/@vitest/runner/dist/index.d.ts","./node_modules/vitest/optional-types.d.ts","./node_modules/vitest/dist/chunks/environment.d.cl3nlxbe.d.ts","./node_modules/@vitest/mocker/dist/registry.d-d765pazg.d.ts","./node_modules/@vitest/mocker/dist/types.d-d_arzrdy.d.ts","./node_modules/@vitest/mocker/dist/index.d.ts","./node_modules/@vitest/utils/dist/source-map.d.ts","./node_modules/vite-node/dist/trace-mapping.d-dlvdeqop.d.ts","./node_modules/vite-node/dist/index.d-dgmxd2u7.d.ts","./node_modules/vite-node/dist/index.d.ts","./node_modules/@vitest/snapshot/dist/environment.d-dhdq1csl.d.ts","./node_modules/@vitest/snapshot/dist/rawsnapshot.d-lfsmjfud.d.ts","./node_modules/@vitest/snapshot/dist/index.d.ts","./node_modules/@vitest/snapshot/dist/environment.d.ts","./node_modules/vitest/dist/chunks/config.d.d2roskhv.d.ts","./node_modules/vitest/dist/chunks/worker.d.1gmbbd7g.d.ts","./node_modules/@types/deep-eql/index.d.ts","./node_modules/assertion-error/index.d.ts","./node_modules/@types/chai/index.d.ts","./node_modules/@vitest/runner/dist/utils.d.ts","./node_modules/tinybench/dist/index.d.ts","./node_modules/vitest/dist/chunks/benchmark.d.bwvbvtda.d.ts","./node_modules/vite-node/dist/client.d.ts","./node_modules/vitest/dist/chunks/coverage.d.s9rmnxie.d.ts","./node_modules/@vitest/snapshot/dist/manager.d.ts","./node_modules/vitest/dist/chunks/reporters.d.bflkqcl6.d.ts","./node_modules/vitest/dist/chunks/vite.d.cmlllifp.d.ts","./node_modules/vitest/dist/config.d.ts","./node_modules/vitest/config.d.ts","./node_modules/@babel/types/lib/index.d.ts","./node_modules/@types/babel__generator/index.d.ts","./node_modules/@babel/parser/typings/babel-parser.d.ts","./node_modules/@types/babel__template/index.d.ts","./node_modules/@types/babel__traverse/index.d.ts","./node_modules/@types/babel__core/index.d.ts","./node_modules/@vitejs/plugin-react/dist/index.d.ts","./vite.config.ts"],"fileIdsList":[[62,110,127,128,227],[62,110,127,128],[62,110,127,128,227,228,229,230,231],[62,110,127,128,227,229],[62,110,127,128,214,215],[62,107,108,110,127,128],[62,109,110,127,128],[110,127,128],[62,110,115,127,128,145],[62,110,111,116,121,127,128,130,142,153],[62,110,111,112,121,127,128,130],[57,58,59,62,110,127,128],[62,110,113,127,128,154],[62,110,114,115,122,127,128,131],[62,110,115,127,128,142,150],[62,110,116,118,121,127,128,130],[62,109,110,117,127,128],[62,110,118,119,127,128],[62,110,120,121,127,128],[62,109,110,121,127,128],[62,110,121,122,123,127,128,142,153],[62,110,121,122,123,127,128,137,142,145],[62,103,110,118,121,124,127,128,130,142,153],[62,110,121,122,124,125,127,128,130,142,150,153],[62,110,124,126,127,128,142,150,153],[60,61,62,63,64,65,66,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159],[62,110,121,127,128],[62,110,127,128,129,153],[62,110,118,121,127,128,130,142],[62,110,127,128,131],[62,110,127,128,132],[62,109,110,127,128,133],[62,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159],[62,110,127,128,135],[62,110,127,128,136],[62,110,121,127,128,137,138],[62,110,127,128,137,139,154,156],[62,110,122,127,128],[62,110,121,127,128,142,143,145],[62,110,127,128,144,145],[62,110,127,128,142,143],[62,110,127,128,145],[62,110,127,128,146],[62,107,110,127,128,142,147,153],[62,110,121,127,128,148,149],[62,110,127,128,148,149],[62,110,115,127,128,130,142,150],[62,110,127,128,151],[62,110,127,128,130,152],[62,110,124,127,128,136,153],[62,110,115,127,128,154],[62,110,127,128,142,155],[62,110,127,128,129,156],[62,110,127,128,157],[62,103,110,127,128],[62,103,110,121,123,127,128,133,142,145,153,155,156,158],[62,110,127,128,142,159],[62,110,127,128,194,224,232],[47,52,53,55,62,110,127,128],[62,110,127,128,201,202],[53,55,62,110,127,128,195,196,197],[53,62,110,127,128],[53,55,62,110,127,128,195],[53,62,110,127,128,195],[62,110,127,128,208],[48,62,110,127,128,208,209],[48,62,110,127,128,208],[48,54,62,110,127,128],[49,62,110,127,128],[48,49,50,52,62,110,127,128],[48,62,110,127,128],[62,110,127,128,185],[62,110,127,128,183,185],[62,110,127,128,174,182,183,184,186,188],[62,110,127,128,172],[62,110,127,128,175,180,185,188],[62,110,127,128,171,188],[62,110,127,128,175,176,179,180,181,188],[62,110,127,128,175,176,177,179,180,188],[62,110,127,128,172,173,174,175,176,180,181,182,184,185,186,188],[62,110,127,128,188],[62,110,127,128,170,172,173,174,175,176,177,179,180,181,182,183,184,185,186,187],[62,110,127,128,170,188],[62,110,127,128,175,177,178,180,181,188],[62,110,127,128,179,188],[62,110,127,128,180,181,185,188],[62,110,127,128,173,183],[62,110,127,128,162,193,194],[62,110,127,128,161,162],[51,62,110,127,128],[62,75,79,110,127,128,153],[62,75,110,127,128,142,153],[62,70,110,127,128],[62,72,75,110,127,128,150,153],[62,110,127,128,130,150],[62,110,127,128,160],[62,70,110,127,128,160],[62,72,75,110,127,128,130,153],[62,67,68,71,74,110,121,127,128,142,153],[62,75,82,110,127,128],[62,67,73,110,127,128],[62,75,96,97,110,127,128],[62,71,75,110,127,128,145,153,160],[62,96,110,127,128,160],[62,69,70,110,127,128,160],[62,75,110,127,128],[62,69,70,71,72,73,74,75,76,77,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,97,98,99,100,101,102,110,127,128],[62,75,90,110,127,128],[62,75,82,83,110,127,128],[62,73,75,83,84,110,127,128],[62,74,110,127,128],[62,67,70,75,110,127,128],[62,75,79,83,84,110,127,128],[62,79,110,127,128],[62,73,75,78,110,127,128,153],[62,67,72,75,82,110,127,128],[62,110,127,128,142],[62,70,75,96,110,127,128,158,160],[62,110,127,128,205,206],[62,110,127,128,205],[62,110,121,122,124,125,126,127,128,130,142,150,153,159,160,162,163,164,165,167,168,169,189,190,191,192,193,194],[62,110,127,128,164,165,166,167],[62,110,127,128,164],[62,110,127,128,165],[62,110,127,128,162,194],[56,62,110,127,128,225],[62,110,127,128,198,217,218],[48,55,62,110,127,128,198,210,211],[62,110,127,128,220],[62,110,127,128,199],[48,53,55,62,110,113,122,127,128,142,194,198,200,203,204,207,210,212,213,216,219,221,222,224],[62,110,127,128,194,223,224],[62,110,127,128,198,200,207,210,212],[48,53,55,62,110,113,122,127,128,142,194,198,199,200,203,204,207,210,211,212,213,216,217,218,219,220,221,222,223,224],[62,110,127,128,226,233]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"080941d9f9ff9307f7e27a83bcd888b7c8270716c39af943532438932ec1d0b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"04471dc55f802c29791cc75edda8c4dd2a121f71c2401059da61eff83099e8ab","impliedFormat":99},{"version":"5c54a34e3d91727f7ae840bfe4d5d1c9a2f93c54cb7b6063d06ee4a6c3322656","impliedFormat":99},{"version":"db4da53b03596668cf6cc9484834e5de3833b9e7e64620cf08399fe069cd398d","impliedFormat":99},{"version":"ac7c28f153820c10850457994db1462d8c8e462f253b828ad942a979f726f2f9","impliedFormat":99},{"version":"f9b028d3c3891dd817e24d53102132b8f696269309605e6ed4f0db2c113bbd82","impliedFormat":99},{"version":"fb7c8d90e52e2884509166f96f3d591020c7b7977ab473b746954b0c8d100960","impliedFormat":99},{"version":"0bff51d6ed0c9093f6955b9d8258ce152ddb273359d50a897d8baabcb34de2c4","impliedFormat":99},{"version":"ef13c73d6157a32933c612d476c1524dd674cf5b9a88571d7d6a0d147544d529","impliedFormat":99},{"version":"13918e2b81c4288695f9b1f3dcc2468caf0f848d5c1f3dc00071c619d34ff63a","impliedFormat":99},{"version":"120a80aa556732f684db3ed61aeff1d6671e1655bd6cba0aa88b22b88ac9a6b1","affectsGlobalScope":true,"impliedFormat":99},{"version":"6c7176368037af28cb72f2392010fa1cef295d6d6744bca8cfb54985f3a18c3e","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"437e20f2ba32abaeb7985e0afe0002de1917bc74e949ba585e49feba65da6ca1","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"98cffbf06d6bab333473c70a893770dbe990783904002c4f1a960447b4b53dca","affectsGlobalScope":true,"impliedFormat":1},{"version":"3af97acf03cc97de58a3a4bc91f8f616408099bc4233f6d0852e72a8ffb91ac9","affectsGlobalScope":true,"impliedFormat":1},{"version":"808069bba06b6768b62fd22429b53362e7af342da4a236ed2d2e1c89fcca3b4a","affectsGlobalScope":true,"impliedFormat":1},{"version":"1db0b7dca579049ca4193d034d835f6bfe73096c73663e5ef9a0b5779939f3d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"f26b11d8d8e4b8028f1c7d618b22274c892e4b0ef5b3678a8ccbad85419aef43","affectsGlobalScope":true,"impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"7f182617db458e98fc18dfb272d40aa2fff3a353c44a89b2c0ccb3937709bfb5","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"e61be3f894b41b7baa1fbd6a66893f2579bfad01d208b4ff61daef21493ef0a8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"b52476feb4a0cbcb25e5931b930fc73cb6643fb1a5060bf8a3dda0eeae5b4b68","affectsGlobalScope":true,"impliedFormat":1},{"version":"f9501cc13ce624c72b61f12b3963e84fad210fbdf0ffbc4590e08460a3f04eba","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"0fa06ada475b910e2106c98c68b10483dc8811d0c14a8a8dd36efb2672485b29","impliedFormat":1},{"version":"33e5e9aba62c3193d10d1d33ae1fa75c46a1171cf76fef750777377d53b0303f","impliedFormat":1},{"version":"2b06b93fd01bcd49d1a6bd1f9b65ddcae6480b9a86e9061634d6f8e354c1468f","impliedFormat":1},{"version":"6a0cd27e5dc2cfbe039e731cf879d12b0e2dded06d1b1dedad07f7712de0d7f4","affectsGlobalScope":true,"impliedFormat":1},{"version":"13f5c844119c43e51ce777c509267f14d6aaf31eafb2c2b002ca35584cd13b29","impliedFormat":1},{"version":"e60477649d6ad21542bd2dc7e3d9ff6853d0797ba9f689ba2f6653818999c264","impliedFormat":1},{"version":"c2510f124c0293ab80b1777c44d80f812b75612f297b9857406468c0f4dafe29","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"4c829ab315f57c5442c6667b53769975acbf92003a66aef19bce151987675bd1","affectsGlobalScope":true,"impliedFormat":1},{"version":"b2ade7657e2db96d18315694789eff2ddd3d8aea7215b181f8a0b303277cc579","impliedFormat":1},{"version":"9855e02d837744303391e5623a531734443a5f8e6e8755e018c41d63ad797db2","impliedFormat":1},{"version":"4d631b81fa2f07a0e63a9a143d6a82c25c5f051298651a9b69176ba28930756d","impliedFormat":1},{"version":"836a356aae992ff3c28a0212e3eabcb76dd4b0cc06bcb9607aeef560661b860d","impliedFormat":1},{"version":"1e0d1f8b0adfa0b0330e028c7941b5a98c08b600efe7f14d2d2a00854fb2f393","impliedFormat":1},{"version":"41670ee38943d9cbb4924e436f56fc19ee94232bc96108562de1a734af20dc2c","affectsGlobalScope":true,"impliedFormat":1},{"version":"c906fb15bd2aabc9ed1e3f44eb6a8661199d6c320b3aa196b826121552cb3695","impliedFormat":1},{"version":"22295e8103f1d6d8ea4b5d6211e43421fe4564e34d0dd8e09e520e452d89e659","impliedFormat":1},{"version":"58647d85d0f722a1ce9de50955df60a7489f0593bf1a7015521efe901c06d770","impliedFormat":1},{"version":"6b4e081d55ac24fc8a4631d5dd77fe249fa25900abd7d046abb87d90e3b45645","impliedFormat":1},{"version":"a10f0e1854f3316d7ee437b79649e5a6ae3ae14ffe6322b02d4987071a95362e","impliedFormat":1},{"version":"e208f73ef6a980104304b0d2ca5f6bf1b85de6009d2c7e404028b875020fa8f2","impliedFormat":1},{"version":"d163b6bc2372b4f07260747cbc6c0a6405ab3fbcea3852305e98ac43ca59f5bc","impliedFormat":1},{"version":"e6fa9ad47c5f71ff733744a029d1dc472c618de53804eae08ffc243b936f87ff","affectsGlobalScope":true,"impliedFormat":1},{"version":"83e63d6ccf8ec004a3bb6d58b9bb0104f60e002754b1e968024b320730cc5311","impliedFormat":1},{"version":"24826ed94a78d5c64bd857570fdbd96229ad41b5cb654c08d75a9845e3ab7dde","impliedFormat":1},{"version":"8b479a130ccb62e98f11f136d3ac80f2984fdc07616516d29881f3061f2dd472","impliedFormat":1},{"version":"928af3d90454bf656a52a48679f199f64c1435247d6189d1caf4c68f2eaf921f","affectsGlobalScope":true,"impliedFormat":1},{"version":"bceb58df66ab8fb00170df20cd813978c5ab84be1d285710c4eb005d8e9d8efb","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f16a7e4deafa527ed9995a772bb380eb7d3c2c0fd4ae178c5263ed18394db2c","impliedFormat":1},{"version":"933921f0bb0ec12ef45d1062a1fc0f27635318f4d294e4d99de9a5493e618ca2","impliedFormat":1},{"version":"71a0f3ad612c123b57239a7749770017ecfe6b66411488000aba83e4546fde25","impliedFormat":1},{"version":"77fbe5eecb6fac4b6242bbf6eebfc43e98ce5ccba8fa44e0ef6a95c945ff4d98","impliedFormat":1},{"version":"4f9d8ca0c417b67b69eeb54c7ca1bedd7b56034bb9bfd27c5d4f3bc4692daca7","impliedFormat":1},{"version":"814118df420c4e38fe5ae1b9a3bafb6e9c2aa40838e528cde908381867be6466","impliedFormat":1},{"version":"a3fc63c0d7b031693f665f5494412ba4b551fe644ededccc0ab5922401079c95","impliedFormat":1},{"version":"f27524f4bef4b6519c604bdb23bf4465bddcccbf3f003abb901acbd0d7404d99","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"45650f47bfb376c8a8ed39d4bcda5902ab899a3150029684ee4c10676d9fbaee","impliedFormat":1},{"version":"6b039f55681caaf111d5eb84d292b9bee9e0131d0db1ad0871eef0964f533c73","affectsGlobalScope":true,"impliedFormat":1},{"version":"18fd40412d102c5564136f29735e5d1c3b455b8a37f920da79561f1fde068208","impliedFormat":1},{"version":"c8d3e5a18ba35629954e48c4cc8f11dc88224650067a172685c736b27a34a4dc","impliedFormat":1},{"version":"f0be1b8078cd549d91f37c30c222c2a187ac1cf981d994fb476a1adc61387b14","affectsGlobalScope":true,"impliedFormat":1},{"version":"0aaed1d72199b01234152f7a60046bc947f1f37d78d182e9ae09c4289e06a592","impliedFormat":1},{"version":"2b55d426ff2b9087485e52ac4bc7cfafe1dc420fc76dad926cd46526567c501a","impliedFormat":1},{"version":"66ba1b2c3e3a3644a1011cd530fb444a96b1b2dfe2f5e837a002d41a1a799e60","impliedFormat":1},{"version":"7e514f5b852fdbc166b539fdd1f4e9114f29911592a5eb10a94bb3a13ccac3c4","impliedFormat":1},{"version":"5b7aa3c4c1a5d81b411e8cb302b45507fea9358d3569196b27eb1a27ae3a90ef","affectsGlobalScope":true,"impliedFormat":1},{"version":"5987a903da92c7462e0b35704ce7da94d7fdc4b89a984871c0e2b87a8aae9e69","affectsGlobalScope":true,"impliedFormat":1},{"version":"ea08a0345023ade2b47fbff5a76d0d0ed8bff10bc9d22b83f40858a8e941501c","impliedFormat":1},{"version":"47613031a5a31510831304405af561b0ffaedb734437c595256bb61a90f9311b","impliedFormat":1},{"version":"ae062ce7d9510060c5d7e7952ae379224fb3f8f2dd74e88959878af2057c143b","impliedFormat":1},{"version":"8a1a0d0a4a06a8d278947fcb66bf684f117bf147f89b06e50662d79a53be3e9f","affectsGlobalScope":true,"impliedFormat":1},{"version":"358765d5ea8afd285d4fd1532e78b88273f18cb3f87403a9b16fef61ac9fdcfe","impliedFormat":1},{"version":"9f55299850d4f0921e79b6bf344b47c420ce0f507b9dcf593e532b09ea7eeea1","impliedFormat":1},{"version":"151ff381ef9ff8da2da9b9663ebf657eac35c4c9a19183420c05728f31a6761d","impliedFormat":1},{"version":"ee70b8037ecdf0de6c04f35277f253663a536d7e38f1539d270e4e916d225a3f","affectsGlobalScope":true,"impliedFormat":1},{"version":"a660aa95476042d3fdcc1343cf6bb8fdf24772d31712b1db321c5a4dcc325434","impliedFormat":1},{"version":"a7ca8df4f2931bef2aa4118078584d84a0b16539598eaadf7dce9104dfaa381c","impliedFormat":1},{"version":"11443a1dcfaaa404c68d53368b5b818712b95dd19f188cab1669c39bee8b84b3","impliedFormat":1},{"version":"36977c14a7f7bfc8c0426ae4343875689949fb699f3f84ecbe5b300ebf9a2c55","impliedFormat":1},{"version":"035d0934d304483f07148427a5bd5b98ac265dae914a6b49749fe23fbd893ec7","impliedFormat":99},{"version":"e2ed5b81cbed3a511b21a18ab2539e79ac1f4bc1d1d28f8d35d8104caa3b429f","impliedFormat":99},{"version":"161c8e0690c46021506e32fda85956d785b70f309ae97011fd27374c065cac9b","affectsGlobalScope":true,"impliedFormat":1},{"version":"402e5c534fb2b85fa771170595db3ac0dd532112c8fa44fc23f233bc6967488b","impliedFormat":1},{"version":"7965dc3c7648e2a7a586d11781cabb43d4859920716bc2fdc523da912b06570d","impliedFormat":1},{"version":"90c2bd9a3e72fe08b8fa5982e78cb8dc855a1157b26e11e37a793283c52bf64b","impliedFormat":1},{"version":"a8122fe390a2a987079e06c573b1471296114677923c1c094c24a53ddd7344a2","impliedFormat":1},{"version":"70c2cb19c0c42061a39351156653aa0cf5ba1ecdc8a07424dd38e3a1f1e3c7f4","impliedFormat":1},{"version":"a8fb10fd8c7bc7d9b8f546d4d186d1027f8a9002a639bec689b5000dab68e35c","impliedFormat":1},{"version":"c9b467ea59b86bd27714a879b9ad43c16f186012a26d0f7110b1322025ceaa83","impliedFormat":1},{"version":"57ea19c2e6ba094d8087c721bac30ff1c681081dbd8b167ac068590ef633e7a5","impliedFormat":1},{"version":"cba81ec9ae7bc31a4dc56f33c054131e037649d6b9a2cfa245124c67e23e4721","impliedFormat":1},{"version":"ad193f61ba708e01218496f093c23626aa3808c296844a99189be7108a9c8343","impliedFormat":1},{"version":"a0544b3c8b70b2f319a99ea380b55ab5394ede9188cdee452a5d0ce264f258b2","impliedFormat":1},{"version":"8c654c17c334c7c168c1c36e5336896dc2c892de940886c1639bebd9fc7b9be4","impliedFormat":1},{"version":"6a4da742485d5c2eb6bcb322ae96993999ffecbd5660b0219a5f5678d8225bb0","impliedFormat":1},{"version":"c65ca21d7002bdb431f9ab3c7a6e765a489aa5196e7e0ef00aed55b1294df599","impliedFormat":1},{"version":"c8fc655c2c4bafc155ceee01c84ab3d6c03192ced5d3f2de82e20f3d1bd7f9fa","impliedFormat":1},{"version":"be5a7ff3b47f7e553565e9483bdcadb0ca2040ac9e5ec7b81c7e115a81059882","impliedFormat":1},{"version":"1a93f36ecdb60a95e3a3621b561763e2952da81962fae217ab5441ac1d77ffc5","impliedFormat":1},{"version":"2a771d907aebf9391ac1f50e4ad37952943515eeea0dcc7e78aa08f508294668","impliedFormat":1},{"version":"0146fd6262c3fd3da51cb0254bb6b9a4e42931eb2f56329edd4c199cb9aaf804","impliedFormat":1},{"version":"183f480885db5caa5a8acb833c2be04f98056bdcc5fb29e969ff86e07efe57ab","impliedFormat":99},{"version":"4ec16d7a4e366c06a4573d299e15fe6207fc080f41beac5da06f4af33ea9761e","impliedFormat":1},{"version":"7870becb94cbc11d2d01b77c4422589adcba4d8e59f726246d40cd0d129784d8","affectsGlobalScope":true,"impliedFormat":1},{"version":"7f698624bbbb060ece7c0e51b7236520ebada74b747d7523c7df376453ed6fea","impliedFormat":1},{"version":"f70b8328a15ca1d10b1436b691e134a49bc30dcf3183a69bfaa7ba77e1b78ecd","impliedFormat":1},{"version":"683b035f752e318d02e303894e767a1ac16ac4493baa2b593195d7976e6b7310","impliedFormat":99},{"version":"45cec9a1ba6549060552eead8959d47226048e0b71c7d0702ae58b7e16a28912","impliedFormat":99},{"version":"6907b09850f86610e7a528348c15484c1e1c09a18a9c1e98861399dfe4b18b46","impliedFormat":99},{"version":"12deea8eaa7a4fc1a2908e67da99831e5c5a6b46ad4f4f948fd4759314ea2b80","impliedFormat":99},{"version":"f0a8b376568a18f9a4976ecb0855187672b16b96c4df1c183a7e52dc1b5d98e8","impliedFormat":99},{"version":"8124828a11be7db984fcdab052fd4ff756b18edcfa8d71118b55388176210923","impliedFormat":99},{"version":"092944a8c05f9b96579161e88c6f211d5304a76bd2c47f8d4c30053269146bc8","impliedFormat":99},{"version":"b34b5f6b506abb206b1ea73c6a332b9ee9c8c98be0f6d17cdbda9430ecc1efab","impliedFormat":99},{"version":"75d4c746c3d16af0df61e7b0afe9606475a23335d9f34fcc525d388c21e9058b","impliedFormat":99},{"version":"fa959bf357232201c32566f45d97e70538c75a093c940af594865d12f31d4912","impliedFormat":99},{"version":"d2c52abd76259fc39a30dfae70a2e5ce77fd23144457a7ff1b64b03de6e3aec7","impliedFormat":99},{"version":"e6233e1c976265e85aa8ad76c3881febe6264cb06ae3136f0257e1eab4a6cc5a","impliedFormat":99},{"version":"f73e2335e568014e279927321770da6fe26facd4ac96cdc22a56687f1ecbb58e","impliedFormat":99},{"version":"317878f156f976d487e21fd1d58ad0461ee0a09185d5b0a43eedf2a56eb7e4ea","impliedFormat":99},{"version":"324ac98294dab54fbd580c7d0e707d94506d7b2c3d5efe981a8495f02cf9ad96","impliedFormat":99},{"version":"9ec72eb493ff209b470467e24264116b6a8616484bca438091433a545dfba17e","impliedFormat":99},{"version":"d6ee22aba183d5fc0c7b8617f77ee82ecadc2c14359cc51271c135e23f6ed51f","impliedFormat":99},{"version":"49747416f08b3ba50500a215e7a55d75268b84e31e896a40313c8053e8dec908","impliedFormat":99},{"version":"81e634f1c5e1ca309e7e3dc69e2732eea932ef07b8b34517d452e5a3e9a36fa3","impliedFormat":99},{"version":"34f39f75f2b5aa9c84a9f8157abbf8322e6831430e402badeaf58dd284f9b9a6","impliedFormat":99},{"version":"427fe2004642504828c1476d0af4270e6ad4db6de78c0b5da3e4c5ca95052a99","impliedFormat":1},{"version":"2eeffcee5c1661ddca53353929558037b8cf305ffb86a803512982f99bcab50d","impliedFormat":99},{"version":"9afb4cb864d297e4092a79ee2871b5d3143ea14153f62ef0bb04ede25f432030","affectsGlobalScope":true,"impliedFormat":99},{"version":"891694d3694abd66f0b8872997b85fd8e52bc51632ce0f8128c96962b443189f","impliedFormat":99},{"version":"69bf2422313487956e4dacf049f30cb91b34968912058d244cb19e4baa24da97","impliedFormat":99},{"version":"971a2c327ff166c770c5fb35699575ba2d13bba1f6d2757309c9be4b30036c8e","impliedFormat":99},{"version":"4f45e8effab83434a78d17123b01124259fbd1e335732135c213955d85222234","impliedFormat":99},{"version":"7bd51996fb7717941cbe094b05adc0d80b9503b350a77b789bbb0fc786f28053","impliedFormat":99},{"version":"b62006bbc815fe8190c7aee262aad6bff993e3f9ade70d7057dfceab6de79d2f","impliedFormat":99},{"version":"13497c0d73306e27f70634c424cd2f3b472187164f36140b504b3756b0ff476d","impliedFormat":99},{"version":"a23a08b626aa4d4a1924957bd8c4d38a7ffc032e21407bbd2c97413e1d8c3dbd","impliedFormat":99},{"version":"c320fe76361c53cad266b46986aac4e68d644acda1629f64be29c95534463d28","impliedFormat":99},{"version":"7bbff6783e96c691a41a7cf12dd5486b8166a01b0c57d071dbcfca55c9525ec4","impliedFormat":99},{"version":"556ccd493ec36c7d7cb130d51be66e147b91cc1415be383d71da0f1e49f742a9","impliedFormat":1},{"version":"b6d03c9cfe2cf0ba4c673c209fcd7c46c815b2619fd2aad59fc4229aaef2ed43","impliedFormat":1},{"version":"95aba78013d782537cc5e23868e736bec5d377b918990e28ed56110e3ae8b958","impliedFormat":1},{"version":"670a76db379b27c8ff42f1ba927828a22862e2ab0b0908e38b671f0e912cc5ed","impliedFormat":1},{"version":"13b77ab19ef7aadd86a1e54f2f08ea23a6d74e102909e3c00d31f231ed040f62","impliedFormat":1},{"version":"069bebfee29864e3955378107e243508b163e77ab10de6a5ee03ae06939f0bb9","impliedFormat":1},{"version":"26e0ffceb2198feb1ef460d5d14111c69ad07d44c5a67fd4bfeb74c969aa9afb","impliedFormat":99},{"version":"161b7ff2c0b478686a09ee22372e2b3b9b3d08a25204e271a4581562a6764bac","signature":"4b96dd19fd2949d28ce80e913412b0026dc421e5bf6c31d87c7b5eb11b5753b4"}],"root":[234],"options":{"allowSyntheticDefaultImports":true,"composite":true,"module":99,"target":7},"referencedMap":[[229,1],[227,2],[232,3],[228,1],[230,4],[231,1],[216,5],[214,2],[161,2],[107,6],[108,6],[109,7],[62,8],[110,9],[111,10],[112,11],[57,2],[60,12],[58,2],[59,2],[113,13],[114,14],[115,15],[116,16],[117,17],[118,18],[119,18],[120,19],[121,20],[122,21],[123,22],[63,2],[61,2],[124,23],[125,24],[126,25],[160,26],[127,27],[128,2],[129,28],[130,29],[131,30],[132,31],[133,32],[134,33],[135,34],[136,35],[137,36],[138,36],[139,37],[140,2],[141,38],[142,39],[144,40],[143,41],[145,42],[146,43],[147,44],[148,45],[149,46],[150,47],[151,48],[152,49],[153,50],[154,51],[155,52],[156,53],[157,54],[64,2],[65,2],[66,2],[104,55],[105,2],[106,2],[158,56],[159,57],[233,58],[56,59],[203,60],[201,2],[202,2],[48,2],[198,61],[195,62],[196,63],[217,64],[208,2],[211,65],[210,66],[222,66],[209,67],[47,2],[55,68],[197,68],[50,69],[53,70],[204,69],[54,71],[49,2],[215,2],[169,2],[186,72],[184,73],[185,74],[173,75],[174,73],[181,76],[172,77],[177,78],[187,2],[178,79],[183,80],[189,81],[188,82],[171,83],[179,84],[180,85],[175,86],[182,72],[176,87],[163,88],[162,89],[170,2],[218,2],[51,2],[52,90],[45,2],[46,2],[8,2],[10,2],[9,2],[2,2],[11,2],[12,2],[13,2],[14,2],[15,2],[16,2],[17,2],[18,2],[3,2],[19,2],[20,2],[4,2],[21,2],[25,2],[22,2],[23,2],[24,2],[26,2],[27,2],[28,2],[5,2],[29,2],[30,2],[31,2],[32,2],[6,2],[36,2],[33,2],[34,2],[35,2],[37,2],[7,2],[38,2],[43,2],[44,2],[39,2],[40,2],[41,2],[42,2],[1,2],[82,91],[92,92],[81,91],[102,93],[73,94],[72,95],[101,96],[95,97],[100,98],[75,99],[89,100],[74,101],[98,102],[70,103],[69,96],[99,104],[71,105],[76,106],[77,2],[80,106],[67,2],[103,107],[93,108],[84,109],[85,110],[87,111],[83,112],[86,113],[96,96],[78,114],[79,115],[88,116],[68,117],[91,108],[90,106],[94,2],[97,118],[220,119],[206,120],[207,119],[205,2],[194,121],[168,122],[167,123],[165,123],[164,2],[166,124],[192,2],[191,2],[190,2],[193,125],[226,126],[219,127],[212,128],[221,129],[200,130],[223,131],[224,132],[213,133],[225,134],[199,2],[234,135]],"semanticDiagnosticsPerFile":[[8,[{"start":930,"length":9,"messageText":"Definitions of the following identifiers conflict with those in another file: ImportExportKind, TableKind, ExportValue, Exports, ImportValue, Imports, ModuleImports, ValueType, name, AlgorithmIdentifier, AllowSharedBufferSource, BigInteger, BlobPart, BodyInit, BufferSource, CSSKeywordish, CSSNumberish, CSSPerspectiveValue, CSSUnparsedSegment, CanvasImageSource, CookieList, DOMHighResTimeStamp, EpochTimeStamp, EventListenerOrEventListenerObject, FileSystemWriteChunkType, Float32List, FormDataEntryValue, GLbitfield, GLboolean, GLclampf, GLenum, GLfloat, GLint, GLint64, GLintptr, GLsizei, GLsizeiptr, GLuint, GLuint64, HashAlgorithmIdentifier, HeadersInit, IDBValidKey, ImageBitmapSource, ImageBufferSource, ImageDataArray, Int32List, MessageEventSource, NamedCurve, OffscreenRenderingContext, OnErrorEventHandler, PerformanceEntryList, ReadableStreamController, ReadableStreamReadResult, ReadableStreamReader, ReportList, RequestInfo, TexImageSource, TimerHandler, Transferable, Uint32List, XMLHttpRequestBodyInit, AlphaOption, AudioSampleFormat, AvcBitstreamFormat, BinaryType, BitrateMode, CSSMathOperator, CSSNumericBaseType, CanvasDirection, CanvasFillRule, CanvasFontKerning, CanvasFontStretch, CanvasFontVariantCaps, CanvasLineCap, CanvasLineJoin, CanvasTextAlign, CanvasTextBaseline, CanvasTextRendering, ClientTypes, CodecState, ColorGamut, ColorSpaceConversion, CompressionFormat, CookieSameSite, DocumentVisibilityState, EncodedAudioChunkType, EncodedVideoChunkType, EndingType, FileSystemHandleKind, FontDisplay, FontFaceLoadStatus, FontFaceSetLoadStatus, GlobalCompositeOperation, HardwareAcceleration, HdrMetadataType, IDBCursorDirection, IDBRequestReadyState, IDBTransactionDurability, IDBTransactionMode, ImageOrientation, ImageSmoothingQuality, KeyFormat, KeyType, KeyUsage, LatencyMode, LockMode, MediaDecodingType, MediaEncodingType, MediaKeysRequirement, NotificationDirection, NotificationPermission, OffscreenRenderingContextId, OpusBitstreamFormat, PermissionName, PermissionState, PredefinedColorSpace, PremultiplyAlpha, PushEncryptionKeyName, RTCDataChannelState, RTCEncodedVideoFrameType, ReadableStreamReaderMode, ReadableStreamType, ReferrerPolicy, RequestCache, RequestCredentials, RequestDestination, RequestMode, RequestPriority, RequestRedirect, ResizeQuality, ResponseType, SecurityPolicyViolationEventDisposition, ServiceWorkerState, ServiceWorkerUpdateViaCache, TransferFunction, VideoColorPrimaries, VideoEncoderBitrateMode, VideoMatrixCoefficients, VideoPixelFormat, VideoTransferCharacteristics, WebGLPowerPreference, WebTransportCongestionControl, WebTransportErrorSource, WorkerType, WriteCommandType, XMLHttpRequestResponseType","category":1,"code":6200,"relatedInformation":[{"file":false,"start":930,"length":9,"messageText":"Conflicts are in this file.","category":3,"code":6201}]},{"start":194996,"length":33,"messageText":"Duplicate index signature for type 'number'.","category":1,"code":2374},{"start":283291,"length":39,"messageText":"Duplicate index signature for type 'number'.","category":1,"code":2374},{"start":287103,"length":36,"messageText":"Duplicate index signature for type 'number'.","category":1,"code":2374},{"start":378009,"length":24,"messageText":"Duplicate index signature for type 'number'.","category":1,"code":2374},{"start":487425,"length":22,"messageText":"Duplicate index signature for type 'number'.","category":1,"code":2374},{"start":851009,"length":28,"messageText":"Duplicate index signature for type 'number'.","category":1,"code":2374}]]],"latestChangedDtsFile":"./vite.config.d.ts","version":"5.9.3"} \ No newline at end of file diff --git a/web/tsconfig.tsbuildinfo b/web/tsconfig.tsbuildinfo deleted file mode 100644 index 31c3ec1..0000000 --- a/web/tsconfig.tsbuildinfo +++ /dev/null @@ -1 +0,0 @@ -{"root":["./src/rootapp.tsx","./src/main.tsx","./src/components/authbootstrap.tsx","./src/components/fullpageloading.tsx","./src/layouts/applayout.tsx","./src/pages/dashboard/dashboardpage.tsx","./src/pages/login/loginpage.tsx","./src/pages/system-info/systeminfopage.tsx","./src/router/protectedroute.tsx","./src/router/index.tsx","./src/services/auth.ts","./src/services/http.ts","./src/services/system.ts","./src/stores/auth.ts","./src/test/setup.ts","./src/types/api.ts","./src/types/auth.ts","./src/types/system.ts"],"version":"5.9.3"} \ No newline at end of file diff --git a/web/vite.config.d.ts b/web/vite.config.d.ts deleted file mode 100644 index 340562a..0000000 --- a/web/vite.config.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -declare const _default: import("vite").UserConfig; -export default _default; diff --git a/web/vite.config.js b/web/vite.config.js deleted file mode 100644 index c48ce53..0000000 --- a/web/vite.config.js +++ /dev/null @@ -1,32 +0,0 @@ -import { defineConfig } from 'vitest/config'; -import react from '@vitejs/plugin-react'; -export default defineConfig({ - plugins: [react()], - server: { - port: 5173, - proxy: { - '/api': { - target: 'http://127.0.0.1:8340', - changeOrigin: true, - }, - }, - }, - build: { - rollupOptions: { - output: { - manualChunks: { - 'vendor-react': ['react', 'react-dom', 'react-router-dom'], - 'vendor-arco': ['@arco-design/web-react'], - 'vendor-echarts': ['echarts', 'echarts-for-react'], - }, - }, - }, - }, - test: { - environment: 'jsdom', - setupFiles: './src/test/setup.ts', - globals: true, - include: ['src/**/*.test.ts', 'src/**/*.test.tsx'], - exclude: ['src/components/auth-guard.test.tsx', 'src/stores/auth.test.ts'], - }, -}); From 4cbd4c302afc9fc29f3d4eb45873186babb2a417 Mon Sep 17 00:00:00 2001 From: Awuqing <3184394176@qq.com> Date: Sun, 9 Aug 2026 19:42:15 +0800 Subject: [PATCH 2/2] =?UTF-8?q?style(go):=20=E7=BB=9F=E4=B8=80=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E4=BB=A3=E7=A0=81=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/cmd/backupx/backint.go | 1 - server/internal/backint/agent.go | 1 - server/internal/backint/protocol.go | 8 +- .../internal/backup/file_runner_diff_test.go | 2 +- server/internal/backup/mysql_runner.go | 1 - server/internal/backup/verify_test.go | 4 +- server/internal/backup/window.go | 9 +- server/internal/model/notification.go | 22 +-- server/internal/model/replication_record.go | 26 +-- server/internal/model/task_template.go | 8 +- server/internal/service/dashboard_service.go | 40 ++--- server/internal/service/system_service.go | 11 +- .../internal/service/task_export_service.go | 170 +++++++++--------- server/internal/storage/rclone/factory.go | 26 +-- 14 files changed, 166 insertions(+), 163 deletions(-) diff --git a/server/cmd/backupx/backint.go b/server/cmd/backupx/backint.go index 12bc268..2ab5ef2 100644 --- a/server/cmd/backupx/backint.go +++ b/server/cmd/backupx/backint.go @@ -95,4 +95,3 @@ func redirectStderr(path string) (func(), error) { _ = f.Close() }, nil } - diff --git a/server/internal/backint/agent.go b/server/internal/backint/agent.go index 56f2382..d41de13 100644 --- a/server/internal/backint/agent.go +++ b/server/internal/backint/agent.go @@ -357,4 +357,3 @@ func buildStorageRegistry() *storage.Registry { storageRclone.RegisterAllBackends(registry) return registry } - diff --git a/server/internal/backint/protocol.go b/server/internal/backint/protocol.go index b790f0f..1c8fa25 100644 --- a/server/internal/backint/protocol.go +++ b/server/internal/backint/protocol.go @@ -21,10 +21,10 @@ import ( type Function string const ( - FunctionBackup Function = "backup" - FunctionRestore Function = "restore" - FunctionInquire Function = "inquire" - FunctionDelete Function = "delete" + FunctionBackup Function = "backup" + FunctionRestore Function = "restore" + FunctionInquire Function = "inquire" + FunctionDelete Function = "delete" ) // BackupRequest 是 BACKUP 操作的单条请求。 diff --git a/server/internal/backup/file_runner_diff_test.go b/server/internal/backup/file_runner_diff_test.go index ffb43d5..0eb74db 100644 --- a/server/internal/backup/file_runner_diff_test.go +++ b/server/internal/backup/file_runner_diff_test.go @@ -160,7 +160,7 @@ func TestFileRunnerSelectiveRestore(t *testing.T) { } diffAssertContent(t, filepath.Join(restoreSrc, "a.txt"), "alpha") diffAssertContent(t, filepath.Join(restoreSrc, "sub", "c.txt"), "charlie") // 选中目录 → 子项一并恢复 - diffAssertAbsent(t, filepath.Join(restoreSrc, "b.txt")) // 未选中 → 不恢复 + diffAssertAbsent(t, filepath.Join(restoreSrc, "b.txt")) // 未选中 → 不恢复 } // TestFileRunnerDifferentialWithoutBaseIsFull 验证无基线时差异请求回退为全量(产出清单、含全部文件)。 diff --git a/server/internal/backup/mysql_runner.go b/server/internal/backup/mysql_runner.go index 2497db4..7350697 100644 --- a/server/internal/backup/mysql_runner.go +++ b/server/internal/backup/mysql_runner.go @@ -160,4 +160,3 @@ func formatFileSize(size int64) string { return fmt.Sprintf("%d B", size) } } - diff --git a/server/internal/backup/verify_test.go b/server/internal/backup/verify_test.go index c808e4d..573871f 100644 --- a/server/internal/backup/verify_test.go +++ b/server/internal/backup/verify_test.go @@ -32,8 +32,8 @@ func writeTestTar(t *testing.T, entries map[string][]byte) string { func TestVerifyTarArchive_Valid(t *testing.T) { path := writeTestTar(t, map[string][]byte{ - "readme.md": []byte("hello"), - "data.bin": []byte("world!!!"), + "readme.md": []byte("hello"), + "data.bin": []byte("world!!!"), }) report, err := VerifyTarArchive(path, "") if err != nil { diff --git a/server/internal/backup/window.go b/server/internal/backup/window.go index c0011a7..4e5c390 100644 --- a/server/internal/backup/window.go +++ b/server/internal/backup/window.go @@ -24,10 +24,11 @@ type MaintenanceWindow struct { // 简化语法:多个窗口以 ';' 分隔,每个窗口按 "[days=xxx;]time=HH:MM-HH:MM" 格式。 // Days 缺省 = 全周;若不合法,跳过该段而非抛错(让调用方尽力工作)。 // 示例: -// "time=01:00-05:00" 每天 1 点到 5 点 -// "days=sat,sun;time=00:00-23:59" 仅周末全天 -// "time=22:00-06:00" 每天跨夜 -// "days=mon,tue,wed,thu,fri;time=22:00-06:00" 工作日跨夜 +// +// "time=01:00-05:00" 每天 1 点到 5 点 +// "days=sat,sun;time=00:00-23:59" 仅周末全天 +// "time=22:00-06:00" 每天跨夜 +// "days=mon,tue,wed,thu,fri;time=22:00-06:00" 工作日跨夜 func ParseMaintenanceWindows(value string) []MaintenanceWindow { v := strings.TrimSpace(value) if v == "" { diff --git a/server/internal/model/notification.go b/server/internal/model/notification.go index c590509..be8a042 100644 --- a/server/internal/model/notification.go +++ b/server/internal/model/notification.go @@ -6,12 +6,12 @@ import "time" // 任一 Notification 可订阅多个事件,EventTypes 字段存 CSV。 // 空 EventTypes + OnSuccess/OnFailure=true 时沿用旧语义(仅备份成功/失败)。 const ( - NotificationEventBackupSuccess = "backup_success" - NotificationEventBackupFailed = "backup_failed" + NotificationEventBackupSuccess = "backup_success" + NotificationEventBackupFailed = "backup_failed" NotificationEventRestoreSuccess = "restore_success" NotificationEventRestoreFailed = "restore_failed" - NotificationEventVerifyFailed = "verify_failed" - NotificationEventSLAViolation = "sla_violation" + NotificationEventVerifyFailed = "verify_failed" + NotificationEventSLAViolation = "sla_violation" // NotificationEventStorageUnhealthy 存储目标连接失败(后台健康扫描触发)。 NotificationEventStorageUnhealthy = "storage_unhealthy" // NotificationEventReplicationFailed 备份复制失败。 @@ -23,13 +23,13 @@ const ( ) type Notification struct { - ID uint `gorm:"primaryKey" json:"id"` - Type string `gorm:"size:20;index;not null" json:"type"` - Name string `gorm:"size:100;uniqueIndex;not null" json:"name"` - ConfigCiphertext string `gorm:"column:config_ciphertext;type:text;not null" json:"-"` - Enabled bool `gorm:"not null;default:true" json:"enabled"` - OnSuccess bool `gorm:"column:on_success;not null;default:false" json:"onSuccess"` - OnFailure bool `gorm:"column:on_failure;not null;default:true" json:"onFailure"` + ID uint `gorm:"primaryKey" json:"id"` + Type string `gorm:"size:20;index;not null" json:"type"` + Name string `gorm:"size:100;uniqueIndex;not null" json:"name"` + ConfigCiphertext string `gorm:"column:config_ciphertext;type:text;not null" json:"-"` + Enabled bool `gorm:"not null;default:true" json:"enabled"` + OnSuccess bool `gorm:"column:on_success;not null;default:false" json:"onSuccess"` + OnFailure bool `gorm:"column:on_failure;not null;default:true" json:"onFailure"` // EventTypes 逗号分隔,订阅的事件类型。 // 空 = 仅监听备份成功/失败(兼容旧配置);非空则严格按订阅触发。 EventTypes string `gorm:"column:event_types;size:500" json:"eventTypes"` diff --git a/server/internal/model/replication_record.go b/server/internal/model/replication_record.go index 19de40a..58692e2 100644 --- a/server/internal/model/replication_record.go +++ b/server/internal/model/replication_record.go @@ -24,19 +24,19 @@ type ReplicationRecord struct { SourceTargetID uint `gorm:"column:source_target_id;index;not null" json:"sourceTargetId"` SourceTarget StorageTarget `gorm:"foreignKey:SourceTargetID;references:ID" json:"sourceTarget,omitempty"` // DestTargetID 目标存储(复制过去) - DestTargetID uint `gorm:"column:dest_target_id;index;not null" json:"destTargetId"` - DestTarget StorageTarget `gorm:"foreignKey:DestTargetID;references:ID" json:"destTarget,omitempty"` - Status string `gorm:"size:20;index;not null" json:"status"` - StoragePath string `gorm:"column:storage_path;size:500" json:"storagePath"` - FileSize int64 `gorm:"column:file_size;not null;default:0" json:"fileSize"` - Checksum string `gorm:"column:checksum;size:64" json:"checksum"` - ErrorMessage string `gorm:"column:error_message;size:2000" json:"errorMessage"` - DurationSeconds int `gorm:"column:duration_seconds;not null;default:0" json:"durationSeconds"` - TriggeredBy string `gorm:"column:triggered_by;size:100" json:"triggeredBy"` - StartedAt time.Time `gorm:"column:started_at;index;not null" json:"startedAt"` - CompletedAt *time.Time `gorm:"column:completed_at;index" json:"completedAt,omitempty"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + DestTargetID uint `gorm:"column:dest_target_id;index;not null" json:"destTargetId"` + DestTarget StorageTarget `gorm:"foreignKey:DestTargetID;references:ID" json:"destTarget,omitempty"` + Status string `gorm:"size:20;index;not null" json:"status"` + StoragePath string `gorm:"column:storage_path;size:500" json:"storagePath"` + FileSize int64 `gorm:"column:file_size;not null;default:0" json:"fileSize"` + Checksum string `gorm:"column:checksum;size:64" json:"checksum"` + ErrorMessage string `gorm:"column:error_message;size:2000" json:"errorMessage"` + DurationSeconds int `gorm:"column:duration_seconds;not null;default:0" json:"durationSeconds"` + TriggeredBy string `gorm:"column:triggered_by;size:100" json:"triggeredBy"` + StartedAt time.Time `gorm:"column:started_at;index;not null" json:"startedAt"` + CompletedAt *time.Time `gorm:"column:completed_at;index" json:"completedAt,omitempty"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } func (ReplicationRecord) TableName() string { diff --git a/server/internal/model/task_template.go b/server/internal/model/task_template.go index 9d27976..14be6ac 100644 --- a/server/internal/model/task_template.go +++ b/server/internal/model/task_template.go @@ -11,10 +11,10 @@ import "time" // - name // - sourcePath / sourcePaths 中的 {{.Host}} / {{.Env}} 等占位符 type TaskTemplate struct { - ID uint `gorm:"primaryKey" json:"id"` - Name string `gorm:"size:128;uniqueIndex;not null" json:"name"` - Description string `gorm:"size:500" json:"description"` - TaskType string `gorm:"column:task_type;size:20;not null" json:"taskType"` + ID uint `gorm:"primaryKey" json:"id"` + Name string `gorm:"size:128;uniqueIndex;not null" json:"name"` + Description string `gorm:"size:500" json:"description"` + TaskType string `gorm:"column:task_type;size:20;not null" json:"taskType"` // Payload JSON,存完整 BackupTaskUpsertInput 的序列化 Payload string `gorm:"type:text;not null" json:"payload"` CreatedBy string `gorm:"column:created_by;size:128" json:"createdBy"` diff --git a/server/internal/service/dashboard_service.go b/server/internal/service/dashboard_service.go index 2508882..00f6bd1 100644 --- a/server/internal/service/dashboard_service.go +++ b/server/internal/service/dashboard_service.go @@ -126,14 +126,14 @@ func (s *DashboardService) Timeline(ctx context.Context, days int) ([]repository // 判定规则:任务设置了 SLAHoursRPO > 0,且距最近一次 success 备份的时间 > SLAHoursRPO。 // 从未成功过的任务(LastSuccessAt = nil)若启用也视为违约(from createdAt 起算)。 type SLAViolation struct { - TaskID uint `json:"taskId"` - TaskName string `json:"taskName"` - NodeID uint `json:"nodeId"` - NodeName string `json:"nodeName,omitempty"` - SLAHoursRPO int `json:"slaHoursRpo"` - LastSuccessAt *time.Time `json:"lastSuccessAt,omitempty"` - HoursSinceLastSuccess float64 `json:"hoursSinceLastSuccess"` - NeverSucceeded bool `json:"neverSucceeded"` + TaskID uint `json:"taskId"` + TaskName string `json:"taskName"` + NodeID uint `json:"nodeId"` + NodeName string `json:"nodeName,omitempty"` + SLAHoursRPO int `json:"slaHoursRpo"` + LastSuccessAt *time.Time `json:"lastSuccessAt,omitempty"` + HoursSinceLastSuccess float64 `json:"hoursSinceLastSuccess"` + NeverSucceeded bool `json:"neverSucceeded"` } // SLAComplianceReport Dashboard 的 SLA 合规概览。 @@ -204,15 +204,15 @@ func roundHours(value float64) float64 { // ClusterNodeSummary 集群节点简报(Dashboard 用)。 type ClusterNodeSummary struct { - ID uint `json:"id"` - Name string `json:"name"` - Hostname string `json:"hostname"` - Status string `json:"status"` - IsLocal bool `json:"isLocal"` - AgentVersion string `json:"agentVersion"` - VersionStatus string `json:"versionStatus"` // current | outdated | unknown - LastSeen time.Time `json:"lastSeen"` - TaskCount int64 `json:"taskCount"` + ID uint `json:"id"` + Name string `json:"name"` + Hostname string `json:"hostname"` + Status string `json:"status"` + IsLocal bool `json:"isLocal"` + AgentVersion string `json:"agentVersion"` + VersionStatus string `json:"versionStatus"` // current | outdated | unknown + LastSeen time.Time `json:"lastSeen"` + TaskCount int64 `json:"taskCount"` } // ClusterOverview Dashboard 集群概览卡片。 @@ -312,9 +312,9 @@ func (s *DashboardService) Breakdown(ctx context.Context, days int) (*BreakdownS } } result := &BreakdownStats{ - ByType: makeBreakdown(typeCounts, typeLabel), - ByNode: makeBreakdownByUint(nodeCounts, nodeNames, "节点 #"), - ByStatus: []BreakdownItem{}, + ByType: makeBreakdown(typeCounts, typeLabel), + ByNode: makeBreakdownByUint(nodeCounts, nodeNames, "节点 #"), + ByStatus: []BreakdownItem{}, ByStorage: []BreakdownItem{}, } // 按状态(最近 days 天记录) diff --git a/server/internal/service/system_service.go b/server/internal/service/system_service.go index 3880f55..891ff26 100644 --- a/server/internal/service/system_service.go +++ b/server/internal/service/system_service.go @@ -74,11 +74,11 @@ func (s *SystemService) CheckUpdate(ctx context.Context) (*UpdateCheckResult, er } var release struct { - TagName string `json:"tag_name"` - HTMLURL string `json:"html_url"` - Body string `json:"body"` - Published string `json:"published_at"` - Assets []struct { + TagName string `json:"tag_name"` + HTMLURL string `json:"html_url"` + Body string `json:"body"` + Published string `json:"published_at"` + Assets []struct { Name string `json:"name"` BrowserDownloadURL string `json:"browser_download_url"` } `json:"assets"` @@ -132,4 +132,3 @@ func (s *SystemService) GetInfo(_ context.Context) *SystemInfo { } return info } - diff --git a/server/internal/service/task_export_service.go b/server/internal/service/task_export_service.go index f690458..1e54ccb 100644 --- a/server/internal/service/task_export_service.go +++ b/server/internal/service/task_export_service.go @@ -14,9 +14,9 @@ import ( // TaskExportService 管理备份任务的 JSON 导入 / 导出。 // 用途: -// 1. 集群迁移(旧 Master → 新 Master 的任务配置搬迁) -// 2. 灾备恢复(任务配置本地文件化,Master 宕机后重建) -// 3. 配置审计(版本化 Git 管理 JSON 快照) +// 1. 集群迁移(旧 Master → 新 Master 的任务配置搬迁) +// 2. 灾备恢复(任务配置本地文件化,Master 宕机后重建) +// 3. 配置审计(版本化 Git 管理 JSON 快照) // // 出于安全考虑,导出/导入不包含任何敏感字段: // - 数据库密码(DBPasswordCiphertext):跳过,导入后需人工填补 @@ -40,35 +40,35 @@ func NewTaskExportService( // ExportedTask 导出格式:按名称引用存储/节点,不含敏感数据。 type ExportedTask struct { - Name string `json:"name"` - Type string `json:"type"` - Enabled bool `json:"enabled"` - CronExpr string `json:"cronExpr,omitempty"` - SourcePath string `json:"sourcePath,omitempty"` - SourcePaths []string `json:"sourcePaths,omitempty"` - ExcludePatterns []string `json:"excludePatterns,omitempty"` - DBHost string `json:"dbHost,omitempty"` - DBPort int `json:"dbPort,omitempty"` - DBUser string `json:"dbUser,omitempty"` - DBName string `json:"dbName,omitempty"` - DBPath string `json:"dbPath,omitempty"` - ExtraConfig map[string]any `json:"extraConfig,omitempty"` + Name string `json:"name"` + Type string `json:"type"` + Enabled bool `json:"enabled"` + CronExpr string `json:"cronExpr,omitempty"` + SourcePath string `json:"sourcePath,omitempty"` + SourcePaths []string `json:"sourcePaths,omitempty"` + ExcludePatterns []string `json:"excludePatterns,omitempty"` + DBHost string `json:"dbHost,omitempty"` + DBPort int `json:"dbPort,omitempty"` + DBUser string `json:"dbUser,omitempty"` + DBName string `json:"dbName,omitempty"` + DBPath string `json:"dbPath,omitempty"` + ExtraConfig map[string]any `json:"extraConfig,omitempty"` // 按名称引用:导入时按名称查找对应 ID - StorageTargetNames []string `json:"storageTargetNames"` - ReplicationTargetNames []string `json:"replicationTargetNames,omitempty"` - NodeName string `json:"nodeName,omitempty"` - DependsOnTaskNames []string `json:"dependsOnTaskNames,omitempty"` - Tags string `json:"tags,omitempty"` - Compression string `json:"compression,omitempty"` - Encrypt bool `json:"encrypt,omitempty"` - RetentionDays int `json:"retentionDays,omitempty"` - MaxBackups int `json:"maxBackups,omitempty"` - VerifyEnabled bool `json:"verifyEnabled,omitempty"` - VerifyCronExpr string `json:"verifyCronExpr,omitempty"` - VerifyMode string `json:"verifyMode,omitempty"` - SLAHoursRPO int `json:"slaHoursRpo,omitempty"` - AlertOnConsecutiveFails int `json:"alertOnConsecutiveFails,omitempty"` - MaintenanceWindows string `json:"maintenanceWindows,omitempty"` + StorageTargetNames []string `json:"storageTargetNames"` + ReplicationTargetNames []string `json:"replicationTargetNames,omitempty"` + NodeName string `json:"nodeName,omitempty"` + DependsOnTaskNames []string `json:"dependsOnTaskNames,omitempty"` + Tags string `json:"tags,omitempty"` + Compression string `json:"compression,omitempty"` + Encrypt bool `json:"encrypt,omitempty"` + RetentionDays int `json:"retentionDays,omitempty"` + MaxBackups int `json:"maxBackups,omitempty"` + VerifyEnabled bool `json:"verifyEnabled,omitempty"` + VerifyCronExpr string `json:"verifyCronExpr,omitempty"` + VerifyMode string `json:"verifyMode,omitempty"` + SLAHoursRPO int `json:"slaHoursRpo,omitempty"` + AlertOnConsecutiveFails int `json:"alertOnConsecutiveFails,omitempty"` + MaintenanceWindows string `json:"maintenanceWindows,omitempty"` } // ExportPayload 导出整体结构,带元信息。 @@ -233,67 +233,67 @@ func (s *TaskExportService) toExported(item *model.BackupTask, targetNames, node nodeName = nodeNames[item.NodeID] } return ExportedTask{ - Name: item.Name, - Type: item.Type, - Enabled: item.Enabled, - CronExpr: item.CronExpr, - SourcePath: item.SourcePath, - SourcePaths: sourcePaths, - ExcludePatterns: excludes, - DBHost: item.DBHost, - DBPort: item.DBPort, - DBUser: item.DBUser, - DBName: item.DBName, - DBPath: item.DBPath, - ExtraConfig: extra, - StorageTargetNames: storageNames, - ReplicationTargetNames: replicationNames, - NodeName: nodeName, - DependsOnTaskNames: dependsOnNames, - Tags: item.Tags, - Compression: item.Compression, - Encrypt: item.Encrypt, - RetentionDays: item.RetentionDays, - MaxBackups: item.MaxBackups, - VerifyEnabled: item.VerifyEnabled, - VerifyCronExpr: item.VerifyCronExpr, - VerifyMode: item.VerifyMode, - SLAHoursRPO: item.SLAHoursRPO, + Name: item.Name, + Type: item.Type, + Enabled: item.Enabled, + CronExpr: item.CronExpr, + SourcePath: item.SourcePath, + SourcePaths: sourcePaths, + ExcludePatterns: excludes, + DBHost: item.DBHost, + DBPort: item.DBPort, + DBUser: item.DBUser, + DBName: item.DBName, + DBPath: item.DBPath, + ExtraConfig: extra, + StorageTargetNames: storageNames, + ReplicationTargetNames: replicationNames, + NodeName: nodeName, + DependsOnTaskNames: dependsOnNames, + Tags: item.Tags, + Compression: item.Compression, + Encrypt: item.Encrypt, + RetentionDays: item.RetentionDays, + MaxBackups: item.MaxBackups, + VerifyEnabled: item.VerifyEnabled, + VerifyCronExpr: item.VerifyCronExpr, + VerifyMode: item.VerifyMode, + SLAHoursRPO: item.SLAHoursRPO, AlertOnConsecutiveFails: item.AlertOnConsecutiveFails, - MaintenanceWindows: item.MaintenanceWindows, + MaintenanceWindows: item.MaintenanceWindows, } } func (s *TaskExportService) toUpsertInput(t ExportedTask, targetsByName, nodesByName map[string]uint, deps []uint) BackupTaskUpsertInput { return BackupTaskUpsertInput{ - Name: t.Name, - Type: t.Type, - Enabled: t.Enabled, - CronExpr: t.CronExpr, - SourcePath: t.SourcePath, - SourcePaths: t.SourcePaths, - ExcludePatterns: t.ExcludePatterns, - DBHost: t.DBHost, - DBPort: t.DBPort, - DBUser: t.DBUser, - DBName: t.DBName, - DBPath: t.DBPath, - ExtraConfig: t.ExtraConfig, - StorageTargetIDs: idsFromNames(t.StorageTargetNames, targetsByName), - ReplicationTargetIDs: idsFromNames(t.ReplicationTargetNames, targetsByName), - NodeID: nodesByName[t.NodeName], - Tags: t.Tags, - Compression: t.Compression, - Encrypt: t.Encrypt, - RetentionDays: t.RetentionDays, - MaxBackups: t.MaxBackups, - VerifyEnabled: t.VerifyEnabled, - VerifyCronExpr: t.VerifyCronExpr, - VerifyMode: t.VerifyMode, - SLAHoursRPO: t.SLAHoursRPO, + Name: t.Name, + Type: t.Type, + Enabled: t.Enabled, + CronExpr: t.CronExpr, + SourcePath: t.SourcePath, + SourcePaths: t.SourcePaths, + ExcludePatterns: t.ExcludePatterns, + DBHost: t.DBHost, + DBPort: t.DBPort, + DBUser: t.DBUser, + DBName: t.DBName, + DBPath: t.DBPath, + ExtraConfig: t.ExtraConfig, + StorageTargetIDs: idsFromNames(t.StorageTargetNames, targetsByName), + ReplicationTargetIDs: idsFromNames(t.ReplicationTargetNames, targetsByName), + NodeID: nodesByName[t.NodeName], + Tags: t.Tags, + Compression: t.Compression, + Encrypt: t.Encrypt, + RetentionDays: t.RetentionDays, + MaxBackups: t.MaxBackups, + VerifyEnabled: t.VerifyEnabled, + VerifyCronExpr: t.VerifyCronExpr, + VerifyMode: t.VerifyMode, + SLAHoursRPO: t.SLAHoursRPO, AlertOnConsecutiveFails: t.AlertOnConsecutiveFails, - MaintenanceWindows: t.MaintenanceWindows, - DependsOnTaskIDs: deps, + MaintenanceWindows: t.MaintenanceWindows, + DependsOnTaskIDs: deps, } } diff --git a/server/internal/storage/rclone/factory.go b/server/internal/storage/rclone/factory.go index bf342df..08e08af 100644 --- a/server/internal/storage/rclone/factory.go +++ b/server/internal/storage/rclone/factory.go @@ -43,7 +43,7 @@ type LocalDiskFactory struct{} func NewLocalDiskFactory() LocalDiskFactory { return LocalDiskFactory{} } func (LocalDiskFactory) Type() storage.ProviderType { return storage.ProviderTypeLocalDisk } -func (LocalDiskFactory) SensitiveFields() []string { return nil } +func (LocalDiskFactory) SensitiveFields() []string { return nil } func (LocalDiskFactory) New(ctx context.Context, rawConfig map[string]any) (storage.StorageProvider, error) { cfg, err := storage.DecodeConfig[storage.LocalDiskConfig](rawConfig) @@ -66,7 +66,7 @@ type S3Factory struct{} func NewS3Factory() S3Factory { return S3Factory{} } func (S3Factory) Type() storage.ProviderType { return storage.ProviderTypeS3 } -func (S3Factory) SensitiveFields() []string { return []string{"accessKeyId", "secretAccessKey"} } +func (S3Factory) SensitiveFields() []string { return []string{"accessKeyId", "secretAccessKey"} } func (S3Factory) New(ctx context.Context, rawConfig map[string]any) (storage.StorageProvider, error) { cfg, err := storage.DecodeConfig[storage.S3Config](rawConfig) @@ -116,7 +116,7 @@ type WebDAVFactory struct{} func NewWebDAVFactory() WebDAVFactory { return WebDAVFactory{} } func (WebDAVFactory) Type() storage.ProviderType { return storage.ProviderTypeWebDAV } -func (WebDAVFactory) SensitiveFields() []string { return []string{"username", "password"} } +func (WebDAVFactory) SensitiveFields() []string { return []string{"username", "password"} } func (WebDAVFactory) New(ctx context.Context, rawConfig map[string]any) (storage.StorageProvider, error) { cfg, err := storage.DecodeConfig[storage.WebDAVConfig](rawConfig) @@ -187,7 +187,7 @@ type FTPFactory struct{} func NewFTPFactory() FTPFactory { return FTPFactory{} } func (FTPFactory) Type() storage.ProviderType { return storage.ProviderTypeFTP } -func (FTPFactory) SensitiveFields() []string { return []string{"username", "password"} } +func (FTPFactory) SensitiveFields() []string { return []string{"username", "password"} } func (FTPFactory) New(ctx context.Context, rawConfig map[string]any) (storage.StorageProvider, error) { cfg, err := storage.DecodeConfig[storage.FTPConfig](rawConfig) @@ -228,7 +228,7 @@ type AliyunOSSFactory struct{} func NewAliyunOSSFactory() AliyunOSSFactory { return AliyunOSSFactory{} } func (AliyunOSSFactory) Type() storage.ProviderType { return storage.ProviderTypeAliyunOSS } -func (AliyunOSSFactory) SensitiveFields() []string { return []string{"accessKeyId", "secretAccessKey"} } +func (AliyunOSSFactory) SensitiveFields() []string { return []string{"accessKeyId", "secretAccessKey"} } // AliyunConfig 是阿里云 OSS 的用户配置。 type AliyunConfig struct { @@ -269,7 +269,9 @@ type TencentCOSFactory struct{} func NewTencentCOSFactory() TencentCOSFactory { return TencentCOSFactory{} } func (TencentCOSFactory) Type() storage.ProviderType { return storage.ProviderTypeTencentCOS } -func (TencentCOSFactory) SensitiveFields() []string { return []string{"accessKeyId", "secretAccessKey"} } +func (TencentCOSFactory) SensitiveFields() []string { + return []string{"accessKeyId", "secretAccessKey"} +} // TencentConfig 是腾讯云 COS 的用户配置。 type TencentConfig struct { @@ -305,7 +307,7 @@ type QiniuKodoFactory struct{} func NewQiniuKodoFactory() QiniuKodoFactory { return QiniuKodoFactory{} } func (QiniuKodoFactory) Type() storage.ProviderType { return storage.ProviderTypeQiniuKodo } -func (QiniuKodoFactory) SensitiveFields() []string { return []string{"accessKeyId", "secretAccessKey"} } +func (QiniuKodoFactory) SensitiveFields() []string { return []string{"accessKeyId", "secretAccessKey"} } // QiniuConfig 是七牛云 Kodo 的用户配置。 type QiniuConfig struct { @@ -355,7 +357,9 @@ type RcloneFactory struct{} func NewRcloneFactory() RcloneFactory { return RcloneFactory{} } func (RcloneFactory) Type() storage.ProviderType { return storage.ProviderTypeRclone } -func (RcloneFactory) SensitiveFields() []string { return []string{"pass", "password", "secret_access_key", "client_secret", "token"} } +func (RcloneFactory) SensitiveFields() []string { + return []string{"pass", "password", "secret_access_key", "client_secret", "token"} +} func (RcloneFactory) New(ctx context.Context, rawConfig map[string]any) (storage.StorageProvider, error) { backend, _ := rawConfig["backend"].(string) @@ -462,8 +466,10 @@ func NewBackendFactory(backendType string) GenericBackendFactory { return GenericBackendFactory{backendType: backendType, sensitive: sensitive} } -func (f GenericBackendFactory) Type() storage.ProviderType { return storage.ProviderType(f.backendType) } -func (f GenericBackendFactory) SensitiveFields() []string { return f.sensitive } +func (f GenericBackendFactory) Type() storage.ProviderType { + return storage.ProviderType(f.backendType) +} +func (f GenericBackendFactory) SensitiveFields() []string { return f.sensitive } func (f GenericBackendFactory) New(ctx context.Context, rawConfig map[string]any) (storage.StorageProvider, error) { root, _ := rawConfig["root"].(string)