chore: 准备第三期迁移脚手架
This commit is contained in:
parent
9db2e4bc5f
commit
3c3dc3a69f
12
docs/refactor-v3/api-admin-contract-matrix.md
Normal file
12
docs/refactor-v3/api-admin-contract-matrix.md
Normal file
@ -0,0 +1,12 @@
|
||||
# API/Admin Contract Matrix
|
||||
|
||||
| Batch | API Contract | Admin Surface | Smoke Evidence |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | `GET /health/runtime` plain JSON, runtime adapter internals | Runtime status remains available | `curl http://localhost:<port>/health/runtime` |
|
||||
| 2 | `/auth/*`, `/admin/user/*`, `/admin/menu/*`, `/admin/role/*`, `/admin/dept/*`, `/admin/dict/*`, `/admin/notice/*` | Login, menu, system pages | Login request, menu load, route render |
|
||||
| 3 | `/blog/*`, `/wordpress/*`, `/asset/*` | Blog, WordPress, Asset pages | Public blog request, Admin list request, asset upload smoke |
|
||||
| 4 | `/qqbot/account/*`, `/qqbot/command/*`, `/qqbot/rule/*`, `/qqbot/message/*`, `/qqbot/send/*` | QQBot core pages | `/qqbot/command/test` local request |
|
||||
| 5 | `/qqbot/plugin-platform/*` | Plugin upload/install/enable/config/health pages | local test plugin install and enable |
|
||||
| 6 | plugin operations exposed through QQBot command/event routing | Existing plugin pages and operation views | BangDream, FF14, FFLogs, Repeater smoke |
|
||||
| 7 | `/qqbot/napcat/*`, login SSE events | NapCat device/login progress pages | simulated captcha and new-device session |
|
||||
| 8 | public deployed URLs | deployed Admin | online smoke bundle |
|
||||
20
docs/refactor-v3/breaking-changes.md
Normal file
20
docs/refactor-v3/breaking-changes.md
Normal file
@ -0,0 +1,20 @@
|
||||
# Refactor V3 Breaking Changes
|
||||
|
||||
## Approved
|
||||
|
||||
| Area | Change | Reason | First Batch |
|
||||
| --- | --- | --- | --- |
|
||||
| Database | Rebuild all API-owned tables from new full schema | Current data is not important and old schema blocks clean module ownership | Batch 0 |
|
||||
| SQL init | Replace historical patch scripts with `sql/refactor-v3/*` | Avoid accumulated `ALTER TABLE` history | Batch 0 |
|
||||
| Admin QQBot API types | Replace old QQBot caller types with new contract | New QQBot Core, Plugin Platform, and NapCat state model | Batch 4 |
|
||||
|
||||
## Protected Behavior
|
||||
|
||||
- Admin login succeeds.
|
||||
- Admin menu loads.
|
||||
- Vben success/error wrappers remain stable for Admin APIs.
|
||||
- `/health/runtime` remains plain JSON.
|
||||
- Blog public list/detail remain available.
|
||||
- QQBot command test remains available.
|
||||
- QQBot status keeps OneBot, container, WebUI, and QQ login state separate.
|
||||
- NapCat cleanup failure blocks success.
|
||||
31
docs/refactor-v3/rebuild-runbook.md
Normal file
31
docs/refactor-v3/rebuild-runbook.md
Normal file
@ -0,0 +1,31 @@
|
||||
# Refactor V3 Rebuild Runbook
|
||||
|
||||
## Local Dry Run
|
||||
|
||||
1. Create an empty local database dedicated to refactor V3.
|
||||
2. Apply `sql/refactor-v3/00-full-schema.sql`.
|
||||
3. Apply `sql/refactor-v3/01-seed-core.sql`.
|
||||
4. Run `sql/refactor-v3/99-verify.sql`.
|
||||
5. Start API against the dry-run database.
|
||||
6. Run `scripts/refactor-v3/local-smoke.ps1`.
|
||||
|
||||
## Online Backup
|
||||
|
||||
1. Confirm the exact API image tag and current database name.
|
||||
2. Run `scripts/refactor-v3/db-backup-online.ps1`.
|
||||
3. Record backup path, timestamp, source database, and restore command.
|
||||
|
||||
## Online Rebuild
|
||||
|
||||
1. Stop or limit API write traffic.
|
||||
2. Apply full schema and seed scripts.
|
||||
3. Run verify SQL.
|
||||
4. Deploy API/Admin image versions bound to this schema.
|
||||
5. Run online smoke bundle.
|
||||
|
||||
## Rollback
|
||||
|
||||
1. Stop write traffic.
|
||||
2. Restore the recorded backup or previous schema bundle.
|
||||
3. Roll back API/Admin images.
|
||||
4. Re-run smoke for the restored version.
|
||||
25
docs/refactor-v3/schema-map.md
Normal file
25
docs/refactor-v3/schema-map.md
Normal file
@ -0,0 +1,25 @@
|
||||
# Refactor V3 Schema Map
|
||||
|
||||
## Global Rules
|
||||
|
||||
- Primary keys are Snowflake `BIGINT`; API/Admin boundary treats IDs as strings.
|
||||
- Table names use lower snake case.
|
||||
- Queryable values are structured columns, not JSON-only fields.
|
||||
- Event/log tables are append-only and have retention strategy.
|
||||
- New schema is full initialization SQL, not historical `ALTER TABLE` patches.
|
||||
|
||||
## Domains
|
||||
|
||||
| Domain | Tables | Owner Batch | Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| Admin Identity | `admin_user`, `admin_role`, `admin_permission`, `admin_menu`, `admin_department`, `admin_user_role`, `admin_role_permission`, `admin_role_menu` | Batch 2 | Login, menu, role, permission, department. |
|
||||
| Platform Config | `platform_dict_group`, `platform_dict_item`, `platform_component_template`, `platform_setting` | Batch 2 | Dict and component template split from legacy Admin misc. |
|
||||
| Blog Content | `blog_post`, `blog_taxonomy`, `blog_term`, `blog_post_term`, `blog_theme_profile`, `blog_import_job` | Batch 3 | Categories and tags use relation table. |
|
||||
| WordPress Mirror | `wordpress_site`, `wordpress_auth_session`, `wordpress_remote_post`, `wordpress_remote_term`, `wordpress_sync_job`, `wordpress_sync_mapping` | Batch 3 | Remote state separate from local Blog content. |
|
||||
| Asset | `asset_bucket`, `asset_object`, `asset_reference`, `asset_access_grant` | Batch 3 | MinIO object ownership and access grant. |
|
||||
| System Event | `system_notice`, `system_event`, `system_event_dedupe`, `system_event_delivery` | Batch 2 | MySQL stores actionable events; Loki remains log query source. |
|
||||
| Runtime Evidence | `runtime_evidence_index` | Batch 1 | Safe index only, no large logs or secrets. |
|
||||
| QQBot Core | `qqbot_account`, `qqbot_connection_session`, `qqbot_capability_binding`, `qqbot_permission_policy`, `qqbot_command`, `qqbot_command_alias`, `qqbot_rule`, `qqbot_conversation`, `qqbot_message`, `qqbot_send_task`, `qqbot_send_log`, `qqbot_dedupe_event` | Batch 4 | Account, connection, permission, command, message, send queue. |
|
||||
| NapCat Runtime | `napcat_container`, `napcat_device_identity`, `napcat_account_binding`, `napcat_login_session`, `napcat_login_challenge`, `napcat_runtime_cleanup` | Batch 7 | Device identity and login challenge state. |
|
||||
| QQBot Plugin Platform | `qqbot_plugin`, `qqbot_plugin_version`, `qqbot_plugin_installation`, `qqbot_plugin_operation`, `qqbot_plugin_event_handler`, `qqbot_plugin_account_binding`, `qqbot_plugin_config`, `qqbot_plugin_asset`, `qqbot_plugin_runtime_event` | Batch 5 | Manifest, install lifecycle, runtime health, bindings. |
|
||||
| Plugin-Owned Data | plugin namespace tables | Batch 6 | Table names start with registered plugin namespace. |
|
||||
@ -18,8 +18,8 @@ Every batch must leave the product in a locally verifiable state. Batch 8 is the
|
||||
|
||||
## Current State Evidence
|
||||
|
||||
- API repo: `D:\MyFiles\KT\Node\kt-template-online-api`, branch `main`, clean at plan start, package manager `pnpm@9.15.9`, no `.node-version`, no `engines`.
|
||||
- Admin repo: `D:\MyFiles\KT\Vue\kt-template-admin`, branch `main`, package manager `pnpm@10.28.2`, `.node-version=22.22.0`, `engines.node >=20.19.0`, `engines.pnpm >=10.0.0`.
|
||||
- API repo: `D:\MyFiles\KT\Node\kt-template-online-api`, implementation branch `dev-api-full-refactor-v3`, package manager `pnpm@9.15.9`, no `.node-version`, no `engines`.
|
||||
- Admin repo: `D:\MyFiles\KT\Vue\kt-template-admin`, implementation branch `dev-admin-full-refactor-v3`, package manager `pnpm@10.28.2`, `.node-version=22.22.0`, `engines.node >=20.19.0`, `engines.pnpm >=10.0.0`.
|
||||
- Admin repo has three old dirty files authorized by the user to discard during implementation preparation:
|
||||
- `README.md`
|
||||
- `apps/web-antdv-next/src/api/qqbot/index.ts`
|
||||
@ -106,7 +106,7 @@ Every batch must leave the product in a locally verifiable state. Batch 8 is the
|
||||
**Files:**
|
||||
- No file edits in this task.
|
||||
|
||||
- [ ] **Step 1: Verify API worktree is clean**
|
||||
- [x] **Step 1: Verify API worktree is clean**
|
||||
|
||||
Run:
|
||||
|
||||
@ -120,21 +120,21 @@ Expected:
|
||||
## main...origin/main [ahead 3]
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Create API implementation branch**
|
||||
- [x] **Step 2: Create API implementation branch**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
git -C D:\MyFiles\KT\Node\kt-template-online-api switch -c dev/api-full-refactor-v3
|
||||
git -C D:\MyFiles\KT\Node\kt-template-online-api switch -c dev-api-full-refactor-v3
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
```text
|
||||
Switched to a new branch 'dev/api-full-refactor-v3'
|
||||
Switched to a new branch 'dev-api-full-refactor-v3'
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Confirm branch**
|
||||
- [x] **Step 3: Confirm branch**
|
||||
|
||||
Run:
|
||||
|
||||
@ -145,9 +145,11 @@ git -C D:\MyFiles\KT\Node\kt-template-online-api branch --show-current
|
||||
Expected:
|
||||
|
||||
```text
|
||||
dev/api-full-refactor-v3
|
||||
dev-api-full-refactor-v3
|
||||
```
|
||||
|
||||
Actual note: `dev/api-full-refactor-v3` could not be created because the API repository already has a local `dev` branch, so Git cannot create a nested ref under `refs/heads/dev`. The implementation branch is `dev-api-full-refactor-v3` to preserve the existing `dev` branch.
|
||||
|
||||
### Task 0.2: Clean authorized Admin old artifacts and prepare branch
|
||||
|
||||
**Files:**
|
||||
@ -156,7 +158,7 @@ dev/api-full-refactor-v3
|
||||
- `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\api\qqbot\index.ts`
|
||||
- `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\qqbot\account\list.tsx`
|
||||
|
||||
- [ ] **Step 1: Verify Admin dirty set is exactly authorized**
|
||||
- [x] **Step 1: Verify Admin dirty set is exactly authorized**
|
||||
|
||||
Run:
|
||||
|
||||
@ -172,11 +174,11 @@ Expected:
|
||||
M apps/web-antdv-next/src/views/qqbot/account/list.tsx
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Stop if any extra path appears**
|
||||
- [x] **Step 2: Stop if any extra path appears**
|
||||
|
||||
If the output contains another path, stop and ask the user before cleanup.
|
||||
|
||||
- [ ] **Step 3: Restore authorized old files**
|
||||
- [x] **Step 3: Restore authorized old files**
|
||||
|
||||
Run:
|
||||
|
||||
@ -186,7 +188,7 @@ git -C D:\MyFiles\KT\Vue\kt-template-admin restore -- README.md apps/web-antdv-n
|
||||
|
||||
Expected: command exits `0`.
|
||||
|
||||
- [ ] **Step 4: Confirm Admin worktree is clean**
|
||||
- [x] **Step 4: Confirm Admin worktree is clean**
|
||||
|
||||
Run:
|
||||
|
||||
@ -200,18 +202,18 @@ Expected:
|
||||
## main...origin/main
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Create Admin implementation branch**
|
||||
- [x] **Step 5: Create Admin implementation branch**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
git -C D:\MyFiles\KT\Vue\kt-template-admin switch -c dev/admin-full-refactor-v3
|
||||
git -C D:\MyFiles\KT\Vue\kt-template-admin switch -c dev-admin-full-refactor-v3
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
```text
|
||||
Switched to a new branch 'dev/admin-full-refactor-v3'
|
||||
Switched to a new branch 'dev-admin-full-refactor-v3'
|
||||
```
|
||||
|
||||
### Task 0.3: Create migration control documents
|
||||
@ -222,7 +224,7 @@ Switched to a new branch 'dev/admin-full-refactor-v3'
|
||||
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\docs\refactor-v3\breaking-changes.md`
|
||||
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\docs\refactor-v3\rebuild-runbook.md`
|
||||
|
||||
- [ ] **Step 1: Add `schema-map.md`**
|
||||
- [x] **Step 1: Add `schema-map.md`**
|
||||
|
||||
Use this content:
|
||||
|
||||
@ -254,7 +256,7 @@ Use this content:
|
||||
| Plugin-Owned Data | plugin namespace tables | Batch 6 | Table names start with registered plugin namespace. |
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Add `api-admin-contract-matrix.md`**
|
||||
- [x] **Step 2: Add `api-admin-contract-matrix.md`**
|
||||
|
||||
Use this content:
|
||||
|
||||
@ -273,7 +275,7 @@ Use this content:
|
||||
| 8 | public deployed URLs | deployed Admin | online smoke bundle |
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Add `breaking-changes.md`**
|
||||
- [x] **Step 3: Add `breaking-changes.md`**
|
||||
|
||||
Use this content:
|
||||
|
||||
@ -300,7 +302,7 @@ Use this content:
|
||||
- NapCat cleanup failure blocks success.
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Add `rebuild-runbook.md`**
|
||||
- [x] **Step 4: Add `rebuild-runbook.md`**
|
||||
|
||||
Use this content:
|
||||
|
||||
@ -338,7 +340,7 @@ Use this content:
|
||||
4. Re-run smoke for the restored version.
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Verify docs exist**
|
||||
- [x] **Step 5: Verify docs exist**
|
||||
|
||||
Run:
|
||||
|
||||
@ -366,7 +368,7 @@ True
|
||||
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\sql\refactor-v3\99-verify.sql`
|
||||
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\test\refactor-v3\schema-map.spec.ts`
|
||||
|
||||
- [ ] **Step 1: Write failing schema test**
|
||||
- [x] **Step 1: Write failing schema test**
|
||||
|
||||
Create `test/refactor-v3/schema-map.spec.ts`:
|
||||
|
||||
@ -425,15 +427,17 @@ describe('refactor v3 schema skeleton', () => {
|
||||
);
|
||||
|
||||
expect(seed).toContain('INSERT INTO admin_user');
|
||||
expect(seed).toContain('INSERT INTO qqbot_command');
|
||||
expect(seed).toContain('INSERT INTO qqbot_plugin');
|
||||
expect(verify).toContain('admin_user');
|
||||
expect(verify).toContain('qqbot_command');
|
||||
expect(verify).toContain('qqbot_plugin');
|
||||
expect(verify).toContain('napcat_device_identity');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run RED check**
|
||||
- [x] **Step 2: Run RED check**
|
||||
|
||||
Run:
|
||||
|
||||
@ -443,11 +447,11 @@ pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --run
|
||||
|
||||
Expected: FAIL because `sql/refactor-v3/00-full-schema.sql` does not exist.
|
||||
|
||||
- [ ] **Step 3: Add minimal SQL skeleton**
|
||||
- [x] **Step 3: Add minimal SQL skeleton**
|
||||
|
||||
Create the three SQL files with table declarations, seed markers, and verify markers. Use full table definitions before ending Batch 0; the initial minimal version only makes the RED check meaningful.
|
||||
|
||||
- [ ] **Step 4: Run GREEN check**
|
||||
- [x] **Step 4: Run GREEN check**
|
||||
|
||||
Run:
|
||||
|
||||
@ -465,7 +469,7 @@ Expected: PASS.
|
||||
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\scripts\refactor-v3\db-restore-online.ps1`
|
||||
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\scripts\refactor-v3\local-smoke.ps1`
|
||||
|
||||
- [ ] **Step 1: Add dry-run script**
|
||||
- [x] **Step 1: Add dry-run script**
|
||||
|
||||
Create `db-dry-run.ps1`:
|
||||
|
||||
@ -478,18 +482,31 @@ param(
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
if ($Database -notmatch '^[A-Za-z0-9_]+$') {
|
||||
throw "Database must match ^[A-Za-z0-9_]+$"
|
||||
}
|
||||
|
||||
$root = Resolve-Path (Join-Path $PSScriptRoot "..\..")
|
||||
$schema = Join-Path $root "sql\refactor-v3\00-full-schema.sql"
|
||||
$seed = Join-Path $root "sql\refactor-v3\01-seed-core.sql"
|
||||
$verify = Join-Path $root "sql\refactor-v3\99-verify.sql"
|
||||
|
||||
function Invoke-MysqlSource {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$Path
|
||||
)
|
||||
|
||||
$sourcePath = (Resolve-Path -LiteralPath $Path).Path.Replace("\", "/")
|
||||
mysql -h $HostName -P $Port -u $User $Database --execute="source $sourcePath"
|
||||
}
|
||||
|
||||
mysql -h $HostName -P $Port -u $User -e "DROP DATABASE IF EXISTS ``$Database``; CREATE DATABASE ``$Database`` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
|
||||
mysql -h $HostName -P $Port -u $User $Database < $schema
|
||||
mysql -h $HostName -P $Port -u $User $Database < $seed
|
||||
mysql -h $HostName -P $Port -u $User $Database < $verify
|
||||
Invoke-MysqlSource -Path $schema
|
||||
Invoke-MysqlSource -Path $seed
|
||||
Invoke-MysqlSource -Path $verify
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Add online backup script**
|
||||
- [x] **Step 2: Add online backup script**
|
||||
|
||||
Create `db-backup-online.ps1`:
|
||||
|
||||
@ -500,13 +517,17 @@ param(
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
if ($Database -notmatch '^[A-Za-z0-9_]+$') {
|
||||
throw "Database must match ^[A-Za-z0-9_]+$"
|
||||
}
|
||||
|
||||
$stamp = Get-Date -Format "yyyyMMdd-HHmmss"
|
||||
$target = Join-Path $OutputDirectory "$Database-refactor-v3-$stamp.sql"
|
||||
mysqldump --set-gtid-purged=OFF --single-transaction --routines --triggers $Database | Out-File -Encoding utf8 $target
|
||||
mysqldump --set-gtid-purged=OFF --single-transaction --routines --triggers --default-character-set=utf8mb4 "--result-file=$target" $Database
|
||||
Write-Output $target
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Add restore script**
|
||||
- [x] **Step 3: Add restore script**
|
||||
|
||||
Create `db-restore-online.ps1`:
|
||||
|
||||
@ -517,11 +538,19 @@ param(
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
if ($Database -notmatch '^[A-Za-z0-9_]+$') {
|
||||
throw "Database must match ^[A-Za-z0-9_]+$"
|
||||
}
|
||||
if (-not (Test-Path -LiteralPath $BackupFile -PathType Leaf)) {
|
||||
throw "BackupFile does not exist"
|
||||
}
|
||||
|
||||
$sourcePath = (Resolve-Path -LiteralPath $BackupFile).Path.Replace("\", "/")
|
||||
mysql -e "DROP DATABASE IF EXISTS ``$Database``; CREATE DATABASE ``$Database`` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
|
||||
mysql $Database < $BackupFile
|
||||
mysql --default-character-set=utf8mb4 $Database --execute="source $sourcePath"
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Add local smoke script**
|
||||
- [x] **Step 4: Add local smoke script**
|
||||
|
||||
Create `local-smoke.ps1`:
|
||||
|
||||
@ -538,13 +567,15 @@ if (-not $runtime.service) {
|
||||
Write-Output "runtime.service=$($runtime.service)"
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Validate scripts parse**
|
||||
- [x] **Step 5: Validate scripts parse**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
powershell -NoProfile -Command "$null = [scriptblock]::Create((Get-Content -Raw D:\MyFiles\KT\Node\kt-template-online-api\scripts\refactor-v3\db-dry-run.ps1)); 'ok'"
|
||||
powershell -NoProfile -Command "$null = [scriptblock]::Create((Get-Content -Raw D:\MyFiles\KT\Node\kt-template-online-api\scripts\refactor-v3\local-smoke.ps1)); 'ok'"
|
||||
powershell -NoProfile -Command '$null = [scriptblock]::Create((Get-Content -Raw -LiteralPath "D:\MyFiles\KT\Node\kt-template-online-api\scripts\refactor-v3\db-dry-run.ps1")); "ok"'
|
||||
powershell -NoProfile -Command '$null = [scriptblock]::Create((Get-Content -Raw -LiteralPath "D:\MyFiles\KT\Node\kt-template-online-api\scripts\refactor-v3\local-smoke.ps1")); "ok"'
|
||||
powershell -NoProfile -Command '$null = [scriptblock]::Create((Get-Content -Raw -LiteralPath "D:\MyFiles\KT\Node\kt-template-online-api\scripts\refactor-v3\db-backup-online.ps1")); "ok"'
|
||||
powershell -NoProfile -Command '$null = [scriptblock]::Create((Get-Content -Raw -LiteralPath "D:\MyFiles\KT\Node\kt-template-online-api\scripts\refactor-v3\db-restore-online.ps1")); "ok"'
|
||||
```
|
||||
|
||||
Expected:
|
||||
@ -552,6 +583,8 @@ Expected:
|
||||
```text
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
```
|
||||
|
||||
### Task 0.6: Batch 0 verification and commits
|
||||
@ -1373,8 +1406,8 @@ After confirmation, push both repos.
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
git -C D:\MyFiles\KT\Node\kt-template-online-api push -u origin dev/api-full-refactor-v3
|
||||
git -C D:\MyFiles\KT\Vue\kt-template-admin push -u origin dev/admin-full-refactor-v3
|
||||
git -C D:\MyFiles\KT\Node\kt-template-online-api push -u origin dev-api-full-refactor-v3
|
||||
git -C D:\MyFiles\KT\Vue\kt-template-admin push -u origin dev-admin-full-refactor-v3
|
||||
```
|
||||
|
||||
Then collect Jenkins/K8s evidence:
|
||||
|
||||
14
scripts/refactor-v3/db-backup-online.ps1
Normal file
14
scripts/refactor-v3/db-backup-online.ps1
Normal file
@ -0,0 +1,14 @@
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$Database,
|
||||
[Parameter(Mandatory = $true)][string]$OutputDirectory
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
if ($Database -notmatch '^[A-Za-z0-9_]+$') {
|
||||
throw "Database must match ^[A-Za-z0-9_]+$"
|
||||
}
|
||||
|
||||
$stamp = Get-Date -Format "yyyyMMdd-HHmmss"
|
||||
$target = Join-Path $OutputDirectory "$Database-refactor-v3-$stamp.sql"
|
||||
mysqldump --set-gtid-purged=OFF --single-transaction --routines --triggers --default-character-set=utf8mb4 "--result-file=$target" $Database
|
||||
Write-Output $target
|
||||
30
scripts/refactor-v3/db-dry-run.ps1
Normal file
30
scripts/refactor-v3/db-dry-run.ps1
Normal file
@ -0,0 +1,30 @@
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$Database,
|
||||
[string]$HostName = "127.0.0.1",
|
||||
[int]$Port = 3306,
|
||||
[string]$User = "root"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
if ($Database -notmatch '^[A-Za-z0-9_]+$') {
|
||||
throw "Database must match ^[A-Za-z0-9_]+$"
|
||||
}
|
||||
|
||||
$root = Resolve-Path (Join-Path $PSScriptRoot "..\..")
|
||||
$schema = Join-Path $root "sql\refactor-v3\00-full-schema.sql"
|
||||
$seed = Join-Path $root "sql\refactor-v3\01-seed-core.sql"
|
||||
$verify = Join-Path $root "sql\refactor-v3\99-verify.sql"
|
||||
|
||||
function Invoke-MysqlSource {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$Path
|
||||
)
|
||||
|
||||
$sourcePath = (Resolve-Path -LiteralPath $Path).Path.Replace("\", "/")
|
||||
mysql -h $HostName -P $Port -u $User $Database --execute="source $sourcePath"
|
||||
}
|
||||
|
||||
mysql -h $HostName -P $Port -u $User -e "DROP DATABASE IF EXISTS ``$Database``; CREATE DATABASE ``$Database`` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
|
||||
Invoke-MysqlSource -Path $schema
|
||||
Invoke-MysqlSource -Path $seed
|
||||
Invoke-MysqlSource -Path $verify
|
||||
16
scripts/refactor-v3/db-restore-online.ps1
Normal file
16
scripts/refactor-v3/db-restore-online.ps1
Normal file
@ -0,0 +1,16 @@
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$Database,
|
||||
[Parameter(Mandatory = $true)][string]$BackupFile
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
if ($Database -notmatch '^[A-Za-z0-9_]+$') {
|
||||
throw "Database must match ^[A-Za-z0-9_]+$"
|
||||
}
|
||||
if (-not (Test-Path -LiteralPath $BackupFile -PathType Leaf)) {
|
||||
throw "BackupFile does not exist"
|
||||
}
|
||||
|
||||
$sourcePath = (Resolve-Path -LiteralPath $BackupFile).Path.Replace("\", "/")
|
||||
mysql -e "DROP DATABASE IF EXISTS ``$Database``; CREATE DATABASE ``$Database`` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
|
||||
mysql --default-character-set=utf8mb4 $Database --execute="source $sourcePath"
|
||||
10
scripts/refactor-v3/local-smoke.ps1
Normal file
10
scripts/refactor-v3/local-smoke.ps1
Normal file
@ -0,0 +1,10 @@
|
||||
param(
|
||||
[string]$BaseUrl = "http://127.0.0.1:5320"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$runtime = Invoke-RestMethod -Method Get -Uri "$BaseUrl/health/runtime" -TimeoutSec 10
|
||||
if (-not $runtime.service) {
|
||||
throw "Runtime health response did not include service"
|
||||
}
|
||||
Write-Output "runtime.service=$($runtime.service)"
|
||||
677
sql/refactor-v3/00-full-schema.sql
Normal file
677
sql/refactor-v3/00-full-schema.sql
Normal file
@ -0,0 +1,677 @@
|
||||
CREATE TABLE IF NOT EXISTS admin_user (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
username VARCHAR(64) NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
nickname VARCHAR(64) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_admin_user_username (username)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS admin_role (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
role_key VARCHAR(64) NOT NULL,
|
||||
role_name VARCHAR(64) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_admin_role_key (role_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS admin_permission (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
permission_key VARCHAR(128) NOT NULL,
|
||||
permission_name VARCHAR(128) NOT NULL,
|
||||
module_key VARCHAR(64) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_admin_permission_key (permission_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS admin_menu (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
parent_id BIGINT NULL,
|
||||
menu_key VARCHAR(128) NOT NULL,
|
||||
title VARCHAR(128) NOT NULL,
|
||||
path VARCHAR(255) NOT NULL,
|
||||
component VARCHAR(255) NULL,
|
||||
sort_no INT NOT NULL DEFAULT 0,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_admin_menu_key (menu_key),
|
||||
KEY idx_admin_menu_parent (parent_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS admin_department (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
parent_id BIGINT NULL,
|
||||
dept_name VARCHAR(128) NOT NULL,
|
||||
sort_no INT NOT NULL DEFAULT 0,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
KEY idx_admin_department_parent (parent_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS admin_user_role (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
role_id BIGINT NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_admin_user_role (user_id, role_id),
|
||||
KEY idx_admin_user_role_role (role_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS admin_role_permission (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
role_id BIGINT NOT NULL,
|
||||
permission_id BIGINT NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_admin_role_permission (role_id, permission_id),
|
||||
KEY idx_admin_role_permission_permission (permission_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS admin_role_menu (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
role_id BIGINT NOT NULL,
|
||||
menu_id BIGINT NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_admin_role_menu (role_id, menu_id),
|
||||
KEY idx_admin_role_menu_menu (menu_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS platform_dict_group (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
group_key VARCHAR(128) NOT NULL,
|
||||
group_name VARCHAR(128) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_platform_dict_group_key (group_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS platform_dict_item (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
group_id BIGINT NOT NULL,
|
||||
item_key VARCHAR(128) NOT NULL,
|
||||
item_label VARCHAR(128) NOT NULL,
|
||||
item_value VARCHAR(255) NOT NULL,
|
||||
sort_no INT NOT NULL DEFAULT 0,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_platform_dict_item (group_id, item_key),
|
||||
KEY idx_platform_dict_item_group (group_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS platform_component_template (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
template_key VARCHAR(128) NOT NULL,
|
||||
template_name VARCHAR(128) NOT NULL,
|
||||
schema_json JSON NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_platform_component_template_key (template_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS platform_setting (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
setting_key VARCHAR(128) NOT NULL,
|
||||
setting_value TEXT NULL,
|
||||
value_type VARCHAR(32) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_platform_setting_key (setting_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS blog_post (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
slug VARCHAR(255) NOT NULL,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
summary TEXT NULL,
|
||||
content_markdown LONGTEXT NULL,
|
||||
content_html LONGTEXT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
publish_time DATETIME NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_blog_post_slug (slug),
|
||||
KEY idx_blog_post_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS blog_taxonomy (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
taxonomy_key VARCHAR(64) NOT NULL,
|
||||
taxonomy_name VARCHAR(128) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_blog_taxonomy_key (taxonomy_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS blog_term (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
taxonomy_id BIGINT NOT NULL,
|
||||
slug VARCHAR(255) NOT NULL,
|
||||
term_name VARCHAR(128) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_blog_term_slug (taxonomy_id, slug),
|
||||
KEY idx_blog_term_taxonomy (taxonomy_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS blog_post_term (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
post_id BIGINT NOT NULL,
|
||||
term_id BIGINT NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_blog_post_term (post_id, term_id),
|
||||
KEY idx_blog_post_term_term (term_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS blog_theme_profile (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
profile_key VARCHAR(128) NOT NULL,
|
||||
profile_name VARCHAR(128) NOT NULL,
|
||||
config_json JSON NOT NULL,
|
||||
enabled TINYINT NOT NULL DEFAULT 0,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_blog_theme_profile_key (profile_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS blog_import_job (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
source_key VARCHAR(64) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
started_at DATETIME NULL,
|
||||
finished_at DATETIME NULL,
|
||||
summary_json JSON NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
KEY idx_blog_import_job_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS wordpress_site (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
site_key VARCHAR(128) NOT NULL,
|
||||
base_url VARCHAR(512) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_wordpress_site_key (site_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS wordpress_auth_session (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
site_id BIGINT NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
expires_at DATETIME NULL,
|
||||
safe_summary JSON NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
KEY idx_wordpress_auth_session_site (site_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS wordpress_remote_post (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
site_id BIGINT NOT NULL,
|
||||
remote_id VARCHAR(64) NOT NULL,
|
||||
slug VARCHAR(255) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
raw_payload JSON NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_wordpress_remote_post (site_id, remote_id),
|
||||
KEY idx_wordpress_remote_post_slug (slug)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS wordpress_remote_term (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
site_id BIGINT NOT NULL,
|
||||
remote_id VARCHAR(64) NOT NULL,
|
||||
taxonomy_key VARCHAR(64) NOT NULL,
|
||||
slug VARCHAR(255) NOT NULL,
|
||||
raw_payload JSON NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_wordpress_remote_term (site_id, taxonomy_key, remote_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS wordpress_sync_job (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
site_id BIGINT NOT NULL,
|
||||
job_type VARCHAR(64) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
started_at DATETIME NULL,
|
||||
finished_at DATETIME NULL,
|
||||
summary_json JSON NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
KEY idx_wordpress_sync_job_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS wordpress_sync_mapping (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
site_id BIGINT NOT NULL,
|
||||
remote_type VARCHAR(64) NOT NULL,
|
||||
remote_id VARCHAR(64) NOT NULL,
|
||||
local_type VARCHAR(64) NOT NULL,
|
||||
local_id BIGINT NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_wordpress_sync_mapping (site_id, remote_type, remote_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS asset_bucket (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
bucket_key VARCHAR(128) NOT NULL,
|
||||
bucket_name VARCHAR(128) NOT NULL,
|
||||
provider VARCHAR(64) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_asset_bucket_key (bucket_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS asset_object (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
bucket_id BIGINT NOT NULL,
|
||||
object_key VARCHAR(512) NOT NULL,
|
||||
source_module VARCHAR(64) NOT NULL,
|
||||
mime_type VARCHAR(128) NULL,
|
||||
size_bytes BIGINT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
metadata_json JSON NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_asset_object_key (bucket_id, object_key),
|
||||
KEY idx_asset_object_source (source_module)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS asset_reference (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
object_id BIGINT NOT NULL,
|
||||
owner_module VARCHAR(64) NOT NULL,
|
||||
owner_type VARCHAR(64) NOT NULL,
|
||||
owner_id BIGINT NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_asset_reference (object_id, owner_module, owner_type, owner_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS asset_access_grant (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
object_id BIGINT NOT NULL,
|
||||
grant_token VARCHAR(128) NOT NULL,
|
||||
expires_at DATETIME NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_asset_access_grant_token (grant_token),
|
||||
KEY idx_asset_access_grant_object (object_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS system_notice (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
notice_key VARCHAR(128) NOT NULL,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
level VARCHAR(32) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
KEY idx_system_notice_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS system_event (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
event_key VARCHAR(128) NOT NULL,
|
||||
source_module VARCHAR(64) NOT NULL,
|
||||
event_type VARCHAR(64) NOT NULL,
|
||||
payload_json JSON NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
KEY idx_system_event_key (event_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS system_event_dedupe (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
dedupe_key VARCHAR(255) NOT NULL,
|
||||
first_seen_at DATETIME NOT NULL,
|
||||
last_seen_at DATETIME NOT NULL,
|
||||
hit_count INT NOT NULL DEFAULT 1,
|
||||
UNIQUE KEY uk_system_event_dedupe_key (dedupe_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS system_event_delivery (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
event_id BIGINT NOT NULL,
|
||||
delivery_target VARCHAR(128) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
attempt_count INT NOT NULL DEFAULT 0,
|
||||
last_error TEXT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
KEY idx_system_event_delivery_event (event_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS runtime_evidence_index (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
evidence_key VARCHAR(128) NOT NULL,
|
||||
evidence_type VARCHAR(64) NOT NULL,
|
||||
artifact_path VARCHAR(512) NOT NULL,
|
||||
safe_summary JSON NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_runtime_evidence_key (evidence_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_account (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
self_id VARCHAR(64) NOT NULL,
|
||||
display_name VARCHAR(128) NULL,
|
||||
onebot_status VARCHAR(32) NOT NULL,
|
||||
container_status VARCHAR(32) NOT NULL,
|
||||
webui_status VARCHAR(32) NOT NULL,
|
||||
qq_login_status VARCHAR(32) NOT NULL,
|
||||
last_error TEXT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_qqbot_account_self_id (self_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_connection_session (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
account_id BIGINT NOT NULL,
|
||||
session_key VARCHAR(128) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
connected_at DATETIME NULL,
|
||||
disconnected_at DATETIME NULL,
|
||||
close_reason TEXT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_qqbot_connection_session_key (session_key),
|
||||
KEY idx_qqbot_connection_session_account (account_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_capability_binding (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
account_id BIGINT NOT NULL,
|
||||
capability_key VARCHAR(128) NOT NULL,
|
||||
enabled TINYINT NOT NULL DEFAULT 1,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_qqbot_capability_binding (account_id, capability_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_permission_policy (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
policy_key VARCHAR(128) NOT NULL,
|
||||
scope_type VARCHAR(64) NOT NULL,
|
||||
scope_value VARCHAR(128) NOT NULL,
|
||||
effect VARCHAR(32) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_qqbot_permission_policy (policy_key, scope_type, scope_value)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_command (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
operation_key VARCHAR(128) NOT NULL,
|
||||
command_key VARCHAR(128) NOT NULL,
|
||||
plugin_key VARCHAR(128) NULL,
|
||||
enabled TINYINT NOT NULL DEFAULT 1,
|
||||
cooldown_seconds INT NOT NULL DEFAULT 0,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_qqbot_command_key (command_key),
|
||||
KEY idx_qqbot_command_operation (operation_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_command_alias (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
command_id BIGINT NOT NULL,
|
||||
alias_text VARCHAR(128) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_qqbot_command_alias (command_id, alias_text)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_rule (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
rule_key VARCHAR(128) NOT NULL,
|
||||
account_id BIGINT NULL,
|
||||
command_id BIGINT NULL,
|
||||
matcher_json JSON NOT NULL,
|
||||
action_json JSON NOT NULL,
|
||||
enabled TINYINT NOT NULL DEFAULT 1,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_qqbot_rule_key (rule_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_conversation (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
account_id BIGINT NOT NULL,
|
||||
conversation_type VARCHAR(64) NOT NULL,
|
||||
conversation_key VARCHAR(128) NOT NULL,
|
||||
display_name VARCHAR(255) NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_qqbot_conversation (account_id, conversation_type, conversation_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_message (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
account_id BIGINT NOT NULL,
|
||||
conversation_id BIGINT NULL,
|
||||
message_id VARCHAR(128) NOT NULL,
|
||||
direction VARCHAR(32) NOT NULL,
|
||||
message_type VARCHAR(64) NOT NULL,
|
||||
summary TEXT NULL,
|
||||
raw_payload JSON NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_qqbot_message (account_id, message_id),
|
||||
KEY idx_qqbot_message_conversation (conversation_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_send_task (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
account_id BIGINT NOT NULL,
|
||||
conversation_id BIGINT NULL,
|
||||
task_key VARCHAR(128) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
payload_json JSON NOT NULL,
|
||||
reserved_at DATETIME NULL,
|
||||
sent_at DATETIME NULL,
|
||||
last_error TEXT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_qqbot_send_task_key (task_key),
|
||||
KEY idx_qqbot_send_task_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_send_log (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
task_id BIGINT NULL,
|
||||
account_id BIGINT NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
safe_summary JSON NULL,
|
||||
error_message TEXT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
KEY idx_qqbot_send_log_task (task_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_dedupe_event (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
dedupe_key VARCHAR(255) NOT NULL,
|
||||
account_id BIGINT NULL,
|
||||
expires_at DATETIME NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_qqbot_dedupe_event_key (dedupe_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_plugin (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
plugin_key VARCHAR(128) NOT NULL,
|
||||
plugin_name VARCHAR(128) NOT NULL,
|
||||
description TEXT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_qqbot_plugin_key (plugin_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_plugin_version (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
plugin_id BIGINT NOT NULL,
|
||||
version VARCHAR(64) NOT NULL,
|
||||
package_hash VARCHAR(128) NOT NULL,
|
||||
manifest_json JSON NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_qqbot_plugin_version (plugin_id, version)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_plugin_installation (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
plugin_id BIGINT NOT NULL,
|
||||
version_id BIGINT NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
runtime_status VARCHAR(32) NOT NULL,
|
||||
installed_path VARCHAR(512) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
KEY idx_qqbot_plugin_installation_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_plugin_operation (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
plugin_id BIGINT NOT NULL,
|
||||
operation_key VARCHAR(128) NOT NULL,
|
||||
operation_name VARCHAR(128) NOT NULL,
|
||||
handler_name VARCHAR(128) NOT NULL,
|
||||
enabled TINYINT NOT NULL DEFAULT 1,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_qqbot_plugin_operation (plugin_id, operation_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_plugin_event_handler (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
plugin_id BIGINT NOT NULL,
|
||||
event_key VARCHAR(128) NOT NULL,
|
||||
handler_name VARCHAR(128) NOT NULL,
|
||||
enabled TINYINT NOT NULL DEFAULT 1,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_qqbot_plugin_event_handler (plugin_id, event_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_plugin_account_binding (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
plugin_id BIGINT NOT NULL,
|
||||
account_id BIGINT NOT NULL,
|
||||
enabled TINYINT NOT NULL DEFAULT 1,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_qqbot_plugin_account_binding (plugin_id, account_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_plugin_config (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
plugin_id BIGINT NOT NULL,
|
||||
config_key VARCHAR(128) NOT NULL,
|
||||
config_value JSON NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_qqbot_plugin_config (plugin_id, config_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_plugin_asset (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
plugin_id BIGINT NOT NULL,
|
||||
asset_key VARCHAR(255) NOT NULL,
|
||||
asset_path VARCHAR(512) NOT NULL,
|
||||
content_hash VARCHAR(128) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_qqbot_plugin_asset (plugin_id, asset_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qqbot_plugin_runtime_event (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
plugin_id BIGINT NOT NULL,
|
||||
installation_id BIGINT NULL,
|
||||
event_type VARCHAR(64) NOT NULL,
|
||||
level VARCHAR(32) NOT NULL,
|
||||
safe_summary JSON NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
KEY idx_qqbot_plugin_runtime_event_plugin (plugin_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS napcat_container (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
account_id BIGINT NOT NULL,
|
||||
container_name VARCHAR(128) NOT NULL,
|
||||
image_name VARCHAR(255) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_napcat_container_name (container_name)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS napcat_device_identity (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
account_id BIGINT NOT NULL,
|
||||
container_id BIGINT NULL,
|
||||
data_dir VARCHAR(512) NOT NULL,
|
||||
hostname VARCHAR(128) NOT NULL,
|
||||
machine_id_path VARCHAR(512) NOT NULL,
|
||||
mac_address VARCHAR(64) NOT NULL,
|
||||
verification_status VARCHAR(32) NOT NULL,
|
||||
last_login_evidence JSON NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_napcat_device_identity_account (account_id),
|
||||
KEY idx_napcat_device_identity_container (container_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS napcat_account_binding (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
account_id BIGINT NOT NULL,
|
||||
container_id BIGINT NOT NULL,
|
||||
device_identity_id BIGINT NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_napcat_account_binding_account (account_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS napcat_login_session (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
account_id BIGINT NOT NULL,
|
||||
session_key VARCHAR(128) NOT NULL,
|
||||
login_stage VARCHAR(64) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
progress_message VARCHAR(255) NOT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_napcat_login_session_key (session_key),
|
||||
KEY idx_napcat_login_session_account (account_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS napcat_login_challenge (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
session_id BIGINT NOT NULL,
|
||||
challenge_type VARCHAR(64) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
challenge_url TEXT NULL,
|
||||
challenge_payload JSON NULL,
|
||||
resolved_at DATETIME NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
KEY idx_napcat_login_challenge_session (session_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS napcat_runtime_cleanup (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
session_id BIGINT NOT NULL,
|
||||
cleanup_type VARCHAR(64) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
error_message TEXT NULL,
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
KEY idx_napcat_runtime_cleanup_session (session_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
138
sql/refactor-v3/01-seed-core.sql
Normal file
138
sql/refactor-v3/01-seed-core.sql
Normal file
@ -0,0 +1,138 @@
|
||||
INSERT INTO admin_user (
|
||||
id,
|
||||
username,
|
||||
password_hash,
|
||||
nickname,
|
||||
status
|
||||
) VALUES (
|
||||
1000000000000000001,
|
||||
'admin',
|
||||
'!disabled-refactor-v3-password-hash!',
|
||||
'Administrator',
|
||||
'password_unset'
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
nickname = VALUES(nickname),
|
||||
status = VALUES(status);
|
||||
|
||||
INSERT INTO admin_role (
|
||||
id,
|
||||
role_key,
|
||||
role_name,
|
||||
status
|
||||
) VALUES (
|
||||
1000000000000000002,
|
||||
'super_admin',
|
||||
'Super Administrator',
|
||||
'enabled'
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
role_name = VALUES(role_name),
|
||||
status = VALUES(status);
|
||||
|
||||
INSERT INTO admin_user_role (
|
||||
id,
|
||||
user_id,
|
||||
role_id
|
||||
) VALUES (
|
||||
1000000000000000003,
|
||||
1000000000000000001,
|
||||
1000000000000000002
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
role_id = VALUES(role_id);
|
||||
|
||||
INSERT INTO admin_menu (
|
||||
id,
|
||||
parent_id,
|
||||
menu_key,
|
||||
title,
|
||||
path,
|
||||
component,
|
||||
sort_no,
|
||||
status
|
||||
) VALUES (
|
||||
1000000000000000004,
|
||||
NULL,
|
||||
'dashboard',
|
||||
'Dashboard',
|
||||
'/dashboard',
|
||||
'dashboard/workspace/index',
|
||||
10,
|
||||
'enabled'
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
title = VALUES(title),
|
||||
path = VALUES(path),
|
||||
component = VALUES(component),
|
||||
status = VALUES(status);
|
||||
|
||||
INSERT INTO platform_setting (
|
||||
id,
|
||||
setting_key,
|
||||
setting_value,
|
||||
value_type
|
||||
) VALUES (
|
||||
1000000000000000005,
|
||||
'schema.version',
|
||||
'refactor-v3',
|
||||
'string'
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
setting_value = VALUES(setting_value),
|
||||
value_type = VALUES(value_type);
|
||||
|
||||
INSERT INTO qqbot_plugin (
|
||||
id,
|
||||
plugin_key,
|
||||
plugin_name,
|
||||
description,
|
||||
status
|
||||
) VALUES
|
||||
(
|
||||
1000000000000000101,
|
||||
'bangdream',
|
||||
'BangDream',
|
||||
'Built-in BangDream command plugin metadata.',
|
||||
'installed'
|
||||
),
|
||||
(
|
||||
1000000000000000102,
|
||||
'ff14-market',
|
||||
'FF14 Market',
|
||||
'Built-in FF14 market command plugin metadata.',
|
||||
'installed'
|
||||
),
|
||||
(
|
||||
1000000000000000103,
|
||||
'fflogs',
|
||||
'FFLogs',
|
||||
'Built-in FFLogs command plugin metadata.',
|
||||
'installed'
|
||||
),
|
||||
(
|
||||
1000000000000000104,
|
||||
'repeater',
|
||||
'Repeater',
|
||||
'Built-in repeater event plugin metadata.',
|
||||
'installed'
|
||||
)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
plugin_name = VALUES(plugin_name),
|
||||
description = VALUES(description),
|
||||
status = VALUES(status);
|
||||
|
||||
INSERT INTO qqbot_command (
|
||||
id,
|
||||
operation_key,
|
||||
command_key,
|
||||
plugin_key,
|
||||
enabled,
|
||||
cooldown_seconds
|
||||
) VALUES (
|
||||
1000000000000000201,
|
||||
'bangdream.song.search',
|
||||
'bangdream_song',
|
||||
'bangdream',
|
||||
1,
|
||||
2
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
operation_key = VALUES(operation_key),
|
||||
plugin_key = VALUES(plugin_key),
|
||||
enabled = VALUES(enabled),
|
||||
cooldown_seconds = VALUES(cooldown_seconds);
|
||||
53
sql/refactor-v3/99-verify.sql
Normal file
53
sql/refactor-v3/99-verify.sql
Normal file
@ -0,0 +1,53 @@
|
||||
SELECT 'admin_user' AS table_name, COUNT(*) AS row_count FROM admin_user;
|
||||
SELECT 'admin_role' AS table_name, COUNT(*) AS row_count FROM admin_role;
|
||||
SELECT 'admin_menu' AS table_name, COUNT(*) AS row_count FROM admin_menu;
|
||||
SELECT 'platform_setting' AS table_name, COUNT(*) AS row_count FROM platform_setting;
|
||||
SELECT 'qqbot_command' AS table_name, COUNT(*) AS row_count FROM qqbot_command;
|
||||
SELECT 'qqbot_plugin' AS table_name, COUNT(*) AS row_count FROM qqbot_plugin;
|
||||
SELECT 'napcat_device_identity' AS table_name, COUNT(*) AS row_count FROM napcat_device_identity;
|
||||
|
||||
SELECT 'seed_admin_user' AS check_name, COUNT(*) AS matched_rows
|
||||
FROM admin_user
|
||||
WHERE username = 'admin'
|
||||
AND status = 'password_unset';
|
||||
|
||||
SELECT 'seed_platform_schema_version' AS check_name, COUNT(*) AS matched_rows
|
||||
FROM platform_setting
|
||||
WHERE setting_key = 'schema.version'
|
||||
AND setting_value = 'refactor-v3';
|
||||
|
||||
SELECT 'seed_qqbot_plugin_bangdream' AS check_name, COUNT(*) AS matched_rows
|
||||
FROM qqbot_plugin
|
||||
WHERE plugin_key = 'bangdream'
|
||||
AND status = 'installed';
|
||||
|
||||
SELECT 'seed_qqbot_command_bangdream_song' AS check_name, COUNT(*) AS matched_rows
|
||||
FROM qqbot_command
|
||||
WHERE command_key = 'bangdream_song'
|
||||
AND operation_key = 'bangdream.song.search'
|
||||
AND plugin_key = 'bangdream'
|
||||
AND enabled = 1;
|
||||
|
||||
SELECT 'index_admin_user_username' AS check_name, COUNT(*) AS matched_rows
|
||||
FROM information_schema.statistics
|
||||
WHERE table_schema = DATABASE()
|
||||
AND table_name = 'admin_user'
|
||||
AND index_name = 'uk_admin_user_username';
|
||||
|
||||
SELECT 'index_platform_setting_key' AS check_name, COUNT(*) AS matched_rows
|
||||
FROM information_schema.statistics
|
||||
WHERE table_schema = DATABASE()
|
||||
AND table_name = 'platform_setting'
|
||||
AND index_name = 'uk_platform_setting_key';
|
||||
|
||||
SELECT 'index_qqbot_command_key' AS check_name, COUNT(*) AS matched_rows
|
||||
FROM information_schema.statistics
|
||||
WHERE table_schema = DATABASE()
|
||||
AND table_name = 'qqbot_command'
|
||||
AND index_name = 'uk_qqbot_command_key';
|
||||
|
||||
SELECT 'index_napcat_device_identity_account' AS check_name, COUNT(*) AS matched_rows
|
||||
FROM information_schema.statistics
|
||||
WHERE table_schema = DATABASE()
|
||||
AND table_name = 'napcat_device_identity'
|
||||
AND index_name = 'uk_napcat_device_identity_account';
|
||||
56
test/refactor-v3/schema-map.spec.ts
Normal file
56
test/refactor-v3/schema-map.spec.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
const root = join(__dirname, '..', '..');
|
||||
|
||||
const extractSchemaMapTables = () => {
|
||||
const schemaMap = readFileSync(
|
||||
join(root, 'docs/refactor-v3/schema-map.md'),
|
||||
'utf8',
|
||||
);
|
||||
|
||||
const matches = schemaMap.match(/`[a-z][a-z0-9_]+`/g) || [];
|
||||
|
||||
return Array.from(
|
||||
new Set(
|
||||
matches
|
||||
.map((match) => match.slice(1, -1))
|
||||
.filter((tableName) => !tableName.endsWith('_*')),
|
||||
),
|
||||
).sort();
|
||||
};
|
||||
|
||||
describe('refactor v3 schema skeleton', () => {
|
||||
it('declares every table listed in the schema map in the full schema file', () => {
|
||||
const sql = readFileSync(
|
||||
join(root, 'sql/refactor-v3/00-full-schema.sql'),
|
||||
'utf8',
|
||||
);
|
||||
const requiredTables = extractSchemaMapTables();
|
||||
|
||||
expect(requiredTables.length).toBeGreaterThan(50);
|
||||
|
||||
for (const table of requiredTables) {
|
||||
expect(sql).toContain(`CREATE TABLE IF NOT EXISTS ${table}`);
|
||||
}
|
||||
});
|
||||
|
||||
it('declares core seed and verification scripts', () => {
|
||||
const seed = readFileSync(
|
||||
join(root, 'sql/refactor-v3/01-seed-core.sql'),
|
||||
'utf8',
|
||||
);
|
||||
const verify = readFileSync(
|
||||
join(root, 'sql/refactor-v3/99-verify.sql'),
|
||||
'utf8',
|
||||
);
|
||||
|
||||
expect(seed).toContain('INSERT INTO admin_user');
|
||||
expect(seed).toContain('INSERT INTO qqbot_command');
|
||||
expect(seed).toContain('INSERT INTO qqbot_plugin');
|
||||
expect(verify).toContain('admin_user');
|
||||
expect(verify).toContain('qqbot_command');
|
||||
expect(verify).toContain('qqbot_plugin');
|
||||
expect(verify).toContain('napcat_device_identity');
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user